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

Fetch image #229

Merged
merged 19 commits into from
Aug 12, 2023
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,6 @@ app.*.map.json
/android/app/debug
/android/app/profile
/android/app/release

# env variables and secrets
*.env
1 change: 1 addition & 0 deletions lib/core/di/di_setup.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import 'package:hypha_wallet/core/network/api/services/sign_transaction_callback
import 'package:hypha_wallet/core/network/api/services/token_service.dart';
import 'package:hypha_wallet/core/network/api/services/transaction_history_service.dart';
import 'package:hypha_wallet/core/network/api/services/user_account_service.dart';
import 'package:hypha_wallet/core/network/ipfs/ipfs_manager.dart';
import 'package:hypha_wallet/core/network/models/network.dart';
import 'package:hypha_wallet/core/network/models/user_profile_data.dart';
import 'package:hypha_wallet/core/network/networking_manager.dart';
Expand Down
1 change: 1 addition & 0 deletions lib/core/di/services_module.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Future<void> _registerServicesModule() async {

// TODO(n13): Only remaining hard-coded reference to Telos - I guess we can't create NetworkingManager with base URL since the base URL depends on the network?
_registerLazySingleton(() => NetworkingManager(_getIt<RemoteConfigService>().baseUrl(network: Network.telos)));
_registerLazySingleton(() => IPFSManager());

/// Secure Storage
_registerLazySingleton(() => const FlutterSecureStorage());
Expand Down
17 changes: 17 additions & 0 deletions lib/core/network/ipfs/ipfs_manager.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:ipfs_client_flutter/ipfs_client_flutter.dart';

class IPFSManager {
final serverUlr = 'https://ipfs.infura.io:5001';
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ok... guess we need secret - let's load it from firebase?! At least it won't be in the code then..

late IpfsClient ipfsClient;

IPFSManager() {
final apiKeySecret = dotenv.env['IPFS_API_KEY_SECRET'];
ipfsClient = IpfsClient(url: serverUlr, authorizationToken: apiKeySecret);
}

Future getImage(String imageToken) async {
final response = await ipfsClient.read(dir: imageToken);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@n13 this doesnt work. it fail. can you take a look when you get some time pls.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Hmmm

return response;
}
}
3 changes: 1 addition & 2 deletions lib/core/network/networking_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,11 @@ class NetworkingManager extends DioForNative {
compact: true,
);

interceptors.add(retryInterceptor);
if (_isDebugNetworking) {
interceptors.add(loggerInterceptor);
}

interceptors.add(retryInterceptor);

options.connectTimeout = Endpoints.connectionTimeout;
options.receiveTimeout = Endpoints.receiveTimeout;
options.responseType = ResponseType.json;
Expand Down
2 changes: 2 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:hypha_wallet/app.dart';
import 'package:hypha_wallet/core/di/di_setup.dart';
import 'package:hypha_wallet/ui/blocs/bloc_observer.dart';
Expand All @@ -10,6 +11,7 @@ void main() async {
// Initialize Flutter
WidgetsFlutterBinding.ensureInitialized();

await dotenv.load(fileName: '.env');
await setupDependencies();

if (kDebugMode) {
Expand Down
109 changes: 64 additions & 45 deletions lib/ui/profile/components/dao_widget.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import 'package:flutter/material.dart';
import 'package:hypha_wallet/core/network/models/dao_data_model.dart';
import 'package:hypha_wallet/design/dividers/hypha_divider.dart';
import 'package:hypha_wallet/design/hypha_card.dart';
import 'package:hypha_wallet/design/hypha_colors.dart';
import 'package:hypha_wallet/design/themes/extensions/theme_extension_provider.dart';

class DaoWidget extends StatelessWidget {
Expand All @@ -13,54 +15,71 @@ class DaoWidget extends StatelessWidget {

@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),
],
return HyphaCard(
child: InkWell(
borderRadius: BorderRadius.circular(16),
onTap: () {
/// Navigate to Hypha URL
},
child: Stack(
children: [
const Positioned(
right: 12,
top: 12,
child: Icon(Icons.navigate_next),
),
),
Padding(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
const Icon(Icons.ac_unit, size: 48),
const SizedBox(width: 8),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(dao.settingsDaoTitle, style: context.hyphaTextTheme.smallTitles),
Text(
'dao.hypha.earth/${dao.settingsDaoUrl}',
Copy link
Collaborator

Choose a reason for hiding this comment

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

I thought this field was called short URL or something

style: context.hyphaTextTheme.reducedTitles.copyWith(color: HyphaColors.primaryBlu),
),
],
)
],
),
const SizedBox(height: 12),
const HyphaDivider(),
const SizedBox(height: 12),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
const Icon(Icons.calendar_month),
const SizedBox(width: 4),
Text(
'The date here',
n13 marked this conversation as resolved.
Show resolved Hide resolved
style: context.hyphaTextTheme.ralMediumSmallNote.copyWith(
height: 0,
color: HyphaColors.midGrey,
),
),
],
),
Text('Core member', style: context.hyphaTextTheme.ralMediumBody.copyWith(height: 0)),
],
)
],
),
),
],
),
),
);
}
}

// 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}');
// }
// }
36 changes: 33 additions & 3 deletions lib/ui/profile/components/profile_view.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hypha_wallet/core/network/models/dao_data_model.dart';
import 'package:hypha_wallet/design/avatar_image/hypha_avatar_image.dart';
import 'package:hypha_wallet/design/background/hypha_half_background.dart';
import 'package:hypha_wallet/design/background/hypha_page_background.dart';
Expand Down Expand Up @@ -119,9 +120,7 @@ class ProfileView extends StatelessWidget {
onChanged: (value) {},
),
],
Wrap(
children: state.profileData?.daos.map((e) => DaoWidget(dao: e)).toList() ?? [],
),
DaosView(daos: state.profileData?.daos ?? []),
],
),
],
Expand All @@ -134,3 +133,34 @@ class ProfileView extends StatelessWidget {
);
}
}

class DaosView extends StatelessWidget {
final List<DaoData> daos;

const DaosView({super.key, required this.daos});

@override
Widget build(BuildContext context) {
if (daos.isEmpty) {
return const SizedBox.shrink();
} else {
final List<DaoWidget> widgets = daos.map((e) => DaoWidget(dao: e)).toList();
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Organizations you are part of',
style: context.hyphaTextTheme.ralMediumBody.copyWith(
color: HyphaColors.midGrey,
),
),
const SizedBox(height: 12),
...widgets
],
),
);
}
}
}
16 changes: 16 additions & 0 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "8.1.3"
flutter_dotenv:
dependency: "direct main"
description:
name: flutter_dotenv
sha256: "9357883bdd153ab78cbf9ffa07656e336b8bbb2b5a3ca596b0b27e119f7c7d77"
url: "https://pub.dev"
source: hosted
version: "5.1.0"
flutter_launcher_icons:
dependency: "direct dev"
description:
Expand Down Expand Up @@ -800,6 +808,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.4"
ipfs_client_flutter:
dependency: "direct main"
description:
name: ipfs_client_flutter
sha256: e9ec8c3b33af20240cdfcb1316ef0804be68d5237df65a82ff3f3a2cfc2fd497
url: "https://pub.dev"
source: hosted
version: "1.0.7"
js:
dependency: transitive
description:
Expand Down
10 changes: 10 additions & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,15 @@ dependencies:
# Get the app version
package_info_plus: ^4.0.2

# Load images and files from IPFS
ipfs_client_flutter: ^1.0.7

# Env variables
flutter_dotenv: ^5.1.0

dependency_overrides:
dio: ^5.3.0

dev_dependencies:
flutter_test:
sdk: flutter
Expand Down Expand Up @@ -188,6 +197,7 @@ flutter:
- assets/images/shield.png
- assets/images/logos/dark/hypha_logo_composite.svg
- assets/config/profile_service/config.json
- .env

# An image asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/assets-and-images/#resolution-aware
Expand Down
Loading