// ignore_for_file: avoid_print import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:gdev_annuaire/queries.dart'; import 'package:graphql_flutter/graphql_flutter.dart'; // import 'package:hive_flutter/hive_flutter.dart'; import 'package:qr_flutter/qr_flutter.dart'; import 'package:truncate/truncate.dart'; // late Box addressBox; bool canAdd = false; List profiles = []; bool showAll = false; Future main() async { WidgetsFlutterBinding.ensureInitialized(); const indexerEndpoint = "https://duniter-indexer.coinduf.eu/v1/graphql"; // await Hive.initFlutter(); // addressBox = await Hive.openBox("addressBox"); // await addressBox.clear(); runApp(const MyApp(indexerEndpoint)); } class MyApp extends StatelessWidget { const MyApp(this.indexerEndpoint, {Key? key}) : super(key: key); final String? indexerEndpoint; @override Widget build(BuildContext context) { final httpLink = HttpLink( indexerEndpoint!, ); final client = ValueNotifier( GraphQLClient( cache: GraphQLCache(), link: httpLink, ), ); return GraphQLProvider( client: client, child: MaterialApp( title: 'ĞDev annuaire', theme: ThemeData( primarySwatch: Colors.blue, ), home: const MyHomePage(title: 'ĞDev annuaire'), ), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({Key? key, required this.title}) : super(key: key); final String title; @override State createState() => _MyHomePageState(); } class _MyHomePageState extends State { refresh() { setState(() {}); } @override void initState() { // showAll = false; super.initState(); } @override Widget build(BuildContext context) { // profiles.clear(); // addressBox.toMap().forEach((key, value) { // profiles.add(value); // }); return Scaffold( backgroundColor: yellowC, body: profileTiles(context, refresh), ); } } Widget profileTiles(BuildContext context, refresh) { final double screenWidth = MediaQuery.of(context).size.width; int nbrColumn = 9; if (screenWidth <= 600) { nbrColumn = 1; } else if (screenWidth <= 900) { nbrColumn = 2; } else if (screenWidth <= 1200) { nbrColumn = 3; } else if (screenWidth <= 1500) { nbrColumn = 4; } else if (screenWidth <= 1800) { nbrColumn = 5; } else if (screenWidth <= 2100) { nbrColumn = 6; } else if (screenWidth <= 2400) { nbrColumn = 7; } else if (screenWidth <= 2700) { nbrColumn = 8; } return Query( options: QueryOptions( document: gql(showAll ? getAllAccountsQ : getAllIdentitiesQ), // pollInterval: const Duration(seconds: 10), ), builder: (QueryResult resultQ, {VoidCallback? refetch, FetchMore? fetchMore}) { if (resultQ.hasException) { return Text(resultQ.exception.toString()); } if (resultQ.isLoading) { return const Text('Loading'); } final List listProfiles = resultQ.data?['account'] ?? []; return CustomScrollView( slivers: [ const SliverToBoxAdapter(child: SizedBox(height: 15)), SliverToBoxAdapter( child: InkWell( onTap: () { showAll = !showAll; refresh(); }, child: Row(children: [ const SizedBox(width: 10), Icon( showAll ? Icons.check_box : Icons.check_box_outline_blank, color: orangeC, ), const SizedBox(width: 8), Text( 'Afficher tous les comptes existants', style: TextStyle(fontSize: 16, color: Colors.grey[700]), ), ]), ), ), const SliverToBoxAdapter(child: SizedBox(height: 15)), SliverGrid.count( key: const Key('listWallets'), crossAxisCount: nbrColumn, childAspectRatio: 1, crossAxisSpacing: 0, mainAxisSpacing: 0, children: [ for (Map profile in listProfiles) Container( color: yellowC, child: Padding( padding: const EdgeInsets.all(0), child: Container( // color: Colors.orange[100], decoration: BoxDecoration( // shape: BoxShape.circle, gradient: RadialGradient( radius: 1.3, colors: [ // yellowC, Colors.white, Colors.orange[300]!, ], ), ), child: Padding( padding: const EdgeInsets.all(10), child: tile( context, profile['id'], profile['identity']?['name'] ?? '', profile['identity']?['validated_at'] == null ? false : true), ), ), ), ), ], ), ], ); }); } Widget tile(BuildContext context, String address, String name, bool isMember) { return Container( decoration: BoxDecoration( color: Colors.orange[50], shape: BoxShape.circle, ), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ GestureDetector( onTap: () {}, child: Text( name, style: TextStyle( fontWeight: FontWeight.w600, fontSize: 17, color: isMember ? orangeC : Colors.black), ), ), const SizedBox(height: 3), InkWell( onTap: () => snackCopyKey(context, address), child: Text( getShortPubkey(address), style: const TextStyle(fontWeight: FontWeight.w500, fontSize: 17), ), ), QrImageWidget( // gapless: false, data: address, version: QrVersions.auto, size: 200, ), ], )), ); } String getShortPubkey(String pubkey) { String pubkeyShort = truncate(pubkey, 7, omission: String.fromCharCode(0x2026), position: TruncatePosition.end) + truncate(pubkey, 6, omission: "", position: TruncatePosition.start); return pubkeyShort; } snackCopyKey(BuildContext context, String address) { // _copyToClipboardHack(address); Clipboard.setData(ClipboardData(text: address)); const snackBar = SnackBar( padding: EdgeInsets.all(20), content: Text("Cette adresse a été copié dans votre presse-papier.", style: TextStyle(fontSize: 16)), duration: Duration(seconds: 2)); ScaffoldMessenger.of(context).showSnackBar(snackBar); } Future getDbData() async { return profiles; } bool isAddress(address) { final RegExp regExp = RegExp( r'^[a-zA-Z0-9]+$', caseSensitive: false, multiLine: false, ); if (regExp.hasMatch(address) == true && address.length > 45 && address.length < 52) { // canAdd = true; return true; } else { // canAdd = false; return false; } } // Colors Color orangeC = const Color(0xffd07316); Color yellowC = const Color(0xffFFD68E); Color floattingYellow = const Color(0xffEFEFBF); Color backgroundColor = const Color(0xFFF5F5F5);