Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/Wallet-162: Show daos #223

Merged
merged 11 commits into from
Aug 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions lib/core/di/services_module.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ Future<void> _registerServicesModule() async {
_registerLazySingleton(() => SignTransactionCallbackService(
_getIt<NetworkingManager>(),
));
_registerLazySingleton(() =>
DaoService(networkingManager: _getIt<NetworkingManager>(), remoteConfigService: _getIt<RemoteConfigService>()));
_registerLazySingleton(() => DaoService(_getIt<NetworkingManager>(), _getIt<RemoteConfigService>()));

_registerLazySingleton(() => CryptoAuthService());

Expand Down
6 changes: 5 additions & 1 deletion lib/core/di/usecases_module.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ void _registerUseCasesModule() {
_registerFactory(() => FindAvailableAccountUseCase(_getIt<UserAccountRepository>()));
_registerFactory(() => CreateAccountUseCase(_getIt<AuthRepository>()));
_registerFactory(() => ParseQRCodeUseCase(_getIt<AuthRepository>()));
_registerFactory(() => FetchProfileUseCase(_getIt<ProfileService>(), _getIt<HyphaSharedPrefs>()));
_registerFactory(() => FetchProfileUseCase(
_getIt<ProfileService>(),
_getIt<HyphaSharedPrefs>(),
_getIt<DaoService>(),
));
_registerFactory(() => GenerateKeyFromSeedsPassportWordsUseCase(_getIt<CryptoAuthService>()));
_registerFactory(() => GenerateKeyFromRecoveryWordsUseCase(_getIt<CryptoAuthService>()));
_registerFactory(() => FindAccountsUseCase(
Expand Down
34 changes: 20 additions & 14 deletions lib/core/network/api/services/dao_service.dart
Original file line number Diff line number Diff line change
@@ -1,42 +1,48 @@
import 'package:dio/dio.dart';
import 'package:hypha_wallet/core/error_handler/model/hypha_error.dart';
import 'package:hypha_wallet/core/logging/log_helper.dart';
import 'package:hypha_wallet/core/network/api/services/remote_config_service.dart';
import 'package:hypha_wallet/core/network/models/dao_data_model.dart';
import 'package:hypha_wallet/core/network/models/user_profile_data.dart';
import 'package:hypha_wallet/core/network/networking_manager.dart';
import 'package:hypha_wallet/ui/architecture/result/result.dart';

class DaoService {
final NetworkingManager networkingManager;
final RemoteConfigService remoteConfigService;
final NetworkingManager _networkingManager;
final RemoteConfigService _remoteConfigService;

DaoService({required this.networkingManager, required this.remoteConfigService});
const DaoService(this._networkingManager, this._remoteConfigService);

Future<List<DaoData>> getDaos({
/// Get dao's for this account
Future<Result<List<DaoData>, HyphaError>> getDaos({
required UserProfileData user,
}) async {
final String accountName = user.accountName;
final String query =
'{"query":"query profileDhos(\$username: String!, \$first: Int, \$offset: Int) { getMember(details_member_n: \$username) { docId __typename createdDate details_member_n memberofAggregate { count } memberof(first: \$first, offset: \$offset) { ... on Dao { docId details_daoName_n settings { settings_daoTitle_s settings_isHypha_i settings_logo_s settings_daoUrl_s } } } applicantof { ... on Dao { details_daoName_n settings { settings_daoTitle_s settings_daoUrl_s } } } } }","variables":{"username":"$accountName"}}';

final url = remoteConfigService.graphQLEndpoint(network: user.network);
final url = _remoteConfigService.graphQLEndpoint(network: user.network);
try {
final res = await networkingManager.post(url, data: query);
final res = await _networkingManager.post(url, data: query);
final Map<String, dynamic> response = res.data;
final List<dynamic> memberOfList = response['data']['getMember']['memberof'];
final List<DaoData> daos = memberOfList.map((member) {
return DaoData.fromJson(member);
}).toList();
return daos;
return Result.value(daos);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pls return Result from all services.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am creating a ticket for this

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

} catch (error) {
print('Error accessing graphQL');
print(error);
if (error is DioException) {
final dioError = error;
print('message: ${dioError.message}');
print('status code: ${dioError.response?.statusCode}');
print('message: ${dioError.response?.statusMessage}');
print('dioError: $dioError');
LogHelper.d('message: ${dioError.message}');
LogHelper.d('status code: ${dioError.response?.statusCode}');
LogHelper.d('message: ${dioError.response?.statusMessage}');
LogHelper.d('dioError: $dioError');
}
rethrow;


LogHelper.e('Error accessing graphQL');
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pls use log helper and not print

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code you replaced this with doesn't do the same thing - in this case I needed to know specifically what the error responses look like.. We should probably keep it this way, although, OK, I can add it back when debugging.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If your need to know is for debug purposes then we should not release with debug code.
I added the loggers back tho

LogHelper.e(error.toString());
return Result.error(HyphaError.fromError(error));
}
}
}
10 changes: 5 additions & 5 deletions lib/core/network/api/services/remote_config_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,10 @@ class RemoteConfigService {
'accountCreatorEndpoint': 'http://34.236.29.152:9108',
'profileServiceEndpoint': 'http://34.236.29.152:9109',
'profileService': json.encode({
'telos': pppConfig.getProfileSeriviceConfig(Network.telos),
'telosTestnet': pppConfig.getProfileSeriviceConfig(Network.telosTestnet),
'eos': pppConfig.getProfileSeriviceConfig(Network.eos),
'eosTestnet': pppConfig.getProfileSeriviceConfig(Network.eosTestnet),
'telos': pppConfig.getProfileServiceConfig(Network.telos),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo rename

'telosTestnet': pppConfig.getProfileServiceConfig(Network.telosTestnet),
'eos': pppConfig.getProfileServiceConfig(Network.eos),
'eosTestnet': pppConfig.getProfileServiceConfig(Network.eosTestnet),
}),
'signUpEnabled': false,
'walletEnabled': false,
Expand All @@ -184,7 +184,7 @@ class RemoteConfigService {
}

extension MapExtensions on Map<String, dynamic> {
Map<String, dynamic> getProfileSeriviceConfig(Network network) {
Map<String, dynamic> getProfileServiceConfig(Network network) {
final networkMap = {
Network.telos: 'prod',
Network.telosTestnet: 'test',
Expand Down
2 changes: 1 addition & 1 deletion lib/core/network/repository/profile_repository.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class ProfileService extends NetworkingManager {
final response = await get(url);
if (response.statusCode == 200) {
final map = Map<String, dynamic>.from(response.data);
return Result.value(ProfileData.fromJson(map, network));
return Result.value(ProfileData.fromJson(map, network, []));
} else {
print('get profile status error: ${response.statusCode} ${response.statusMessage}');
return Result.error(HyphaError(type: HyphaErrorType.api, message: 'server error ${response.statusMessage}'));
Expand Down
29 changes: 24 additions & 5 deletions lib/design/avatar_image/hypha_avatar_image.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class HyphaAvatarImage extends StatelessWidget {
final String? name;
final double imageRadius;
final GestureTapCallback? onTap;
final bool withBorder;

const HyphaAvatarImage({
super.key,
Expand All @@ -20,6 +21,7 @@ class HyphaAvatarImage extends StatelessWidget {
this.name,
required this.imageRadius,
this.onTap,
this.withBorder = false,
});

bool get hasImage => imageFromUrl != null || imageFromFile != null;
Expand Down Expand Up @@ -82,13 +84,30 @@ class HyphaAvatarImage extends StatelessWidget {
image = Icon(HyphaIcons.image, size: imageRadius, color: context.textTheme.titleSmall?.color);
}

final view = withBorder
? DecoratedBox(
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(color: Colors.white, width: 1),
),
child: Padding(
padding: const EdgeInsets.all(1),
child: CircleAvatar(
radius: imageRadius,
backgroundColor: HyphaColors.transparent,
child: image,
),
),
)
: CircleAvatar(
radius: imageRadius + (hasImage ? 2 : 1),
backgroundColor: HyphaColors.transparent,
child: image,
);

return GestureDetector(
onTap: onTap,
child: CircleAvatar(
radius: imageRadius + (hasImage ? 2 : 1),
backgroundColor: HyphaColors.transparent,
child: image,
),
child: view,
);
}
}
3 changes: 3 additions & 0 deletions lib/design/avatar_image/hypha_editable_avatar_image.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class HyphaEditableAvatarImage extends StatelessWidget {
final double imageRadius;
final Function(XFile image)? onImageSelected;
final GestureTapCallback? onImageRemoved;
final bool withBorder;

bool get hasImage => imageFromFile != null || imageFromUrl != null;

Expand All @@ -21,6 +22,7 @@ class HyphaEditableAvatarImage extends StatelessWidget {
required this.imageRadius,
this.onImageSelected,
this.onImageRemoved,
this.withBorder = false,
});

@override
Expand All @@ -37,6 +39,7 @@ class HyphaEditableAvatarImage extends StatelessWidget {
onTap: () async {
await _selectImage();
},
withBorder: withBorder,
),
Positioned(
top: -10,
Expand Down
58 changes: 42 additions & 16 deletions lib/design/cards/hypha_transaction_details_card.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,29 @@ class HyphaTransactionDetailsCard extends StatelessWidget {
@override
Widget build(BuildContext context) {
final List rows = List.empty(growable: true);
String? memo;
data.data.forEach((key, value) {
rows.add(Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(key, style: context.hyphaTextTheme.ralMediumBody.copyWith(color: HyphaColors.midGrey)),
const SizedBox(width: 4),
Flexible(
child: Text(
value.toString(),
style: context.hyphaTextTheme.ralMediumBody,
textAlign: TextAlign.right,
maxLines: 4,
overflow: TextOverflow.ellipsis,
if (key != 'memo') {
rows.add(Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(key, style: context.hyphaTextTheme.ralMediumBody.copyWith(color: HyphaColors.midGrey)),
const SizedBox(width: 4),
Flexible(
child: Text(
value.toString(),
style: context.hyphaTextTheme.ralMediumBody,
textAlign: TextAlign.right,
maxLines: 4,
overflow: TextOverflow.ellipsis,
),
),
),
],
));
rows.add(const SizedBox(height: 8));
],
));
rows.add(const SizedBox(height: 8));
} else {
memo = value;
}
});

return HyphaCard(
Expand Down Expand Up @@ -70,6 +75,27 @@ class HyphaTransactionDetailsCard extends StatelessWidget {
const HyphaDivider(),
const SizedBox(height: 22),
...rows,
if (memo != null) ...[
const SizedBox(height: 16),
const HyphaDivider(),
const SizedBox(height: 16),
Text(
'Memo',
style: context.hyphaTextTheme.ralMediumBody.copyWith(color: HyphaColors.midGrey),
),
const SizedBox(height: 8),
Container(
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 12),
width: double.infinity,
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(12)),
color: context.isDarkTheme
? HyphaColors.midGrey.withOpacity(0.10)
: HyphaColors.midGrey.withOpacity(0.05),
),
child: Text(memo!, style: context.hyphaTextTheme.ralMediumBody),
)
],
const SizedBox(height: 22),
const HyphaDivider(),
const SizedBox(height: 22),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,13 @@ class BottomNavigationView extends StatelessWidget {
),
clipBehavior: Clip.antiAlias,
child: Padding(
padding: const EdgeInsets.only(bottom: 12, left: 30, right: 30, top: 12),
padding: const EdgeInsets.only(bottom: 8, left: 30, right: 30, top: 12),
child: BottomNavigationBar(
elevation: 0,
backgroundColor: context.isDarkTheme ? HyphaColors.lightBlack : HyphaColors.white,
currentIndex: state.indexOfSelected,
selectedFontSize: 12,
unselectedFontSize: 12,
onTap: (int index) {
BlocProvider.of<BottomNavigationBloc>(context).add(
BottomNavigationEvent.onPageSelected(state.allPages[index]),
Expand Down
66 changes: 66 additions & 0 deletions lib/ui/profile/components/dao_widget.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import 'package:flutter/material.dart';
import 'package:hypha_wallet/core/network/models/dao_data_model.dart';
import 'package:hypha_wallet/design/hypha_card.dart';
import 'package:hypha_wallet/design/themes/extensions/theme_extension_provider.dart';

class DaoWidget extends StatelessWidget {
final DaoData dao;

const DaoWidget({
super.key,
required this.dao,
});

@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 22),
child: HyphaCard(
child: InkWell(
borderRadius: BorderRadius.circular(16),
onTap: () {},
child: Padding(
padding: const EdgeInsets.only(left: 22, right: 22, top: 12, bottom: 22),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ListTile(
dense: true,
// leading: FutureBuilder<String>(
// future: fetchSVGFromIPFS('QmV3KmaoqCCXuCDvHzYWS9Jg3RfjrDTQSXK1e7453qfSRS'),
// builder: (context, snapshot) {
// if (snapshot.connectionState == ConnectionState.waiting) {
// return CircularProgressIndicator();
// } else if (snapshot.hasError) {
// return Text('Error: ${snapshot.error}');
// } else {
// return SvgPicture.string(snapshot.data!);
// }
// },
// ),
visualDensity: VisualDensity.compact,
title: Text(dao.settingsDaoTitle, style: context.hyphaTextTheme.smallTitles),
),
// const SizedBox(height: 14),
// const HyphaDivider(),
// const SizedBox(height: 20),
],
),
),
),
),
);
}
}

// Future<String> fetchSVGFromIPFS(String ipfsHash) async {
// final ipfsURL = 'https://ipfs.io/ipfs/$ipfsHash:svg';
// final response = await http.get(Uri.parse(ipfsURL));
//
// if (response.statusCode == 200) {
// return response.body;
// } else {
// throw Exception('Failed to fetch SVG from IPFS. Status code: ${response.statusCode}');
// }
// }
Loading
Loading