Merge branch 'implementFigma'

This commit is contained in:
poka 2021-12-05 06:24:01 +01:00
commit 4bef232002
73 changed files with 6150 additions and 1585 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

BIN
assets/chests/secret_code.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

BIN
assets/chests/vector.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 331 B

After

Width:  |  Height:  |  Size: 6.9 KiB

BIN
assets/copy_key.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

BIN
assets/home/background.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 KiB

BIN
assets/home/background.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 620 KiB

BIN
assets/home/bout_de_bulle.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 630 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

BIN
assets/home/header.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

14
assets/home/header.svg Executable file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 30 KiB

BIN
assets/home/loupe.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

1
assets/home/loupe.svg Executable file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 57 KiB

BIN
assets/home/qrcode.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
assets/home/wallet.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

92
assets/home/wallet.svg Normal file
View File

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
x="0px"
y="0px"
viewBox="0 0 100 125"
id="svg10"
sodipodi:docname="wallet.svg"
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
<metadata
id="metadata16">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs14">
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath138">
<rect
style="fill:#000000;fill-opacity:1"
id="rect140"
width="91.747101"
height="91.747101"
x="4.4194174"
y="957.15405" />
</clipPath>
</defs>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1015"
id="namedview12"
showgrid="true"
inkscape:zoom="5.6568543"
inkscape:cx="35.337997"
inkscape:cy="80.718182"
inkscape:window-x="1920"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg10" />
<g
transform="translate(0,-952.36218)"
id="g4"
clip-path="url(#clipPath138)"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
style="fill:#ffffff">
<path
style="font-size:medium;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:normal;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;baseline-shift:baseline;opacity:1;color:#000000;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:4;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Sans;-inkscape-font-specification:Sans"
d="M 50.90625 6 A 2.0002 2.0002 0 0 0 49.84375 6.5 L 30.0625 24.46875 L 18.1875 24.46875 C 15.543683 24.44965 13.123155 25.17569 11.25 26.46875 C 9.3768448 27.76181 7.9999596 29.75493 8 32.09375 L 8.03125 86.625 C 8.03684 88.8921 9.3819629 90.8203 11.1875 92.0625 C 12.993037 93.3047 15.308353 94 17.84375 94 L 77.6875 94 C 80.644255 94 83.374448 92.089642 84.4375 89.25 C 86.113053 89.114967 87.744729 88.6459 89.125 87.6875 C 90.81563 86.5136 92 84.44345 92 82.03125 L 92 32.09375 C 92 30.15621 91.430591 28.26221 90.1875 26.8125 C 88.944409 25.36279 86.997793 24.47521 84.8125 24.46875 L 74.96875 24.4375 L 69.5 13.25 A 2.0002 2.0002 0 0 0 67.53125 12.125 A 2.0002 2.0002 0 0 0 66.78125 12.34375 L 60.46875 15.59375 L 52.71875 6.6875 A 2.0002 2.0002 0 0 0 50.90625 6 z M 51.03125 10.84375 L 56.8125 17.5 L 26.5 33.125 L 51.03125 10.84375 z M 66.8125 16.84375 L 75.1875 33.96875 L 33.5625 34 L 66.8125 16.84375 z M 76.9375 28.4375 L 84.8125 28.46875 C 86.009294 28.47275 86.654841 28.85275 87.15625 29.4375 C 87.657659 30.0223 88 30.92895 88 32.09375 L 88 50.1875 L 67.625 50.1875 C 65.302589 50.1875 63.593739 52.225 63.59375 54.4375 L 63.59375 64.5 C 63.593768 66.7125 65.302709 68.78125 67.625 68.78125 L 88 68.78125 L 88 82.03125 C 88 83.31875 87.603802 83.87855 86.84375 84.40625 C 86.37816 84.729568 85.69117 84.975519 84.90625 85.125 L 84.90625 73.5625 A 2.0002 2.0002 0 1 0 80.90625 73.5625 L 80.90625 86.625 C 80.90625 88.7156 79.289498 90 77.6875 90 L 17.84375 90 C 16.046389 90 14.457371 89.48295 13.4375 88.78125 C 12.417629 88.07965 12.033004 87.30545 12.03125 86.59375 L 12 36.84375 C 13.469144 37.606227 15.201391 38.000302 17.0625 38 L 78.5 37.96875 C 79.316994 37.96862 79.724605 38.2578 80.15625 38.84375 C 80.587895 39.4297 80.906252 40.37836 80.90625 41.34375 L 80.90625 44.53125 A 2.0002 2.0002 0 1 0 84.90625 44.53125 L 84.90625 41.34375 C 84.906254 39.6214 84.425391 37.89465 83.375 36.46875 C 82.541915 35.337841 81.241284 34.452882 79.71875 34.125 L 76.9375 28.4375 z M 18.15625 28.46875 A 2.0002 2.0002 0 0 0 18.1875 28.46875 L 25.6875 28.46875 L 19.59375 34 L 17.0625 34 C 15.604391 34.00024 14.294499 33.60485 13.4375 33.0625 C 12.580501 32.52015 12.218298 31.89481 12.15625 31.40625 A 2.0002 2.0002 0 0 0 12.15625 31.375 C 12.362153 30.832741 12.788717 30.262578 13.53125 29.75 C 14.615705 29.00139 16.267859 28.45508 18.15625 28.46875 z M 67.625 54.1875 L 88 54.1875 L 88 64.78125 L 67.65625 64.78125 C 67.655285 64.784472 67.64577 64.78125 67.625 64.78125 C 67.611788 64.759611 67.59375 64.685125 67.59375 64.5 L 67.59375 54.4375 C 67.593749 54.1412 67.708223 54.1875 67.625 54.1875 z M 71.5 55.6875 A 2.0002 2.0002 0 0 0 69.71875 57.71875 L 69.71875 61.25 A 2.0002 2.0002 0 1 0 73.71875 61.25 L 73.71875 57.71875 A 2.0002 2.0002 0 0 0 71.5 55.6875 z "
transform="translate(0,952.36218)"
id="path2" />
</g>
<text
x="0"
y="115"
fill="#000000"
font-size="5px"
font-weight="bold"
font-family="'Helvetica Neue', Helvetica, Arial-Unicode, Arial, Sans-serif"
id="text6">Created by counloucon</text>
<text
x="0"
y="120"
fill="#000000"
font-size="5px"
font-weight="bold"
font-family="'Helvetica Neue', Helvetica, Arial-Unicode, Arial, Sans-serif"
id="text8">from the Noun Project</text>
</svg>

After

Width:  |  Height:  |  Size: 5.7 KiB

BIN
assets/loupe-noire.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
assets/printer.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 460 B

After

Width:  |  Height:  |  Size: 11 KiB

BIN
assets/vector_white.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
assets/walletOptions/android-checkmark.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 264 B

After

Width:  |  Height:  |  Size: 11 KiB

BIN
assets/walletOptions/camera.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 585 B

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
assets/walletOptions/clock.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 19 KiB

BIN
assets/walletOptions/copy-white.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 482 B

After

Width:  |  Height:  |  Size: 7.6 KiB

BIN
assets/walletOptions/edit.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 284 B

After

Width:  |  Height:  |  Size: 11 KiB

BIN
assets/walletOptions/icon_oeuil.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 719 B

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

BIN
assets/walletOptions/key.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 492 B

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
assets/walletOptions/trash.png Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -1,6 +1,7 @@
import 'dart:io'; import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:gecko/models/chest_data.dart'; import 'package:gecko/models/chest_data.dart';
import 'package:gecko/models/g1_wallets_list.dart';
import 'package:gecko/models/wallet_data.dart'; import 'package:gecko/models/wallet_data.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:logger/logger.dart'; import 'package:logger/logger.dart';
@ -16,9 +17,10 @@ int ramSys;
Box<WalletData> walletBox; Box<WalletData> walletBox;
Box<ChestData> chestBox; Box<ChestData> chestBox;
Box configBox; Box configBox;
Box<G1WalletsList> g1WalletsBox;
// String cesiumPod = "https://g1.data.le-sou.org"; String cesiumPod = "https://g1.data.le-sou.org";
String cesiumPod = "https://g1.data.e-is.pro"; // String cesiumPod = "https://g1.data.e-is.pro";
// Responsive ratios // Responsive ratios
bool isTall; bool isTall;

View File

@ -23,16 +23,20 @@ import 'package:gecko/models/cesium_plus.dart';
import 'package:gecko/models/change_pin.dart'; import 'package:gecko/models/change_pin.dart';
import 'package:gecko/models/chest_data.dart'; import 'package:gecko/models/chest_data.dart';
import 'package:gecko/models/chest_provider.dart'; import 'package:gecko/models/chest_provider.dart';
import 'package:gecko/models/g1_wallets_list.dart';
import 'package:gecko/models/generate_wallets.dart'; import 'package:gecko/models/generate_wallets.dart';
import 'package:gecko/models/history.dart'; import 'package:gecko/models/wallets_profiles.dart';
import 'package:gecko/models/home.dart'; import 'package:gecko/models/home.dart';
import 'package:gecko/models/my_wallets.dart'; import 'package:gecko/models/my_wallets.dart';
import 'package:gecko/models/search.dart';
import 'package:gecko/models/wallet_data.dart'; import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/models/wallet_options.dart'; import 'package:gecko/models/wallet_options.dart';
import 'package:gecko/screens/home.dart'; import 'package:gecko/screens/home.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:gecko/screens/myWallets/wallets_home.dart'; import 'package:gecko/screens/myWallets/wallets_home.dart';
import 'package:gecko/screens/search.dart';
import 'package:gecko/screens/search_result.dart';
import 'package:graphql_flutter/graphql_flutter.dart'; import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:hive_flutter/hive_flutter.dart'; import 'package:hive_flutter/hive_flutter.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
@ -41,17 +45,14 @@ import 'package:flutter/foundation.dart';
import 'package:responsive_framework/responsive_framework.dart'; import 'package:responsive_framework/responsive_framework.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_flutter/sentry_flutter.dart';
import 'package:flutter_driver/driver_extension.dart';
const bool enableSentry = true; const bool enableSentry = true;
Future<void> main() async { Future<void> main() async {
enableFlutterDriverExtension();
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
HomeProvider _homeProvider = HomeProvider(); HomeProvider _homeProvider = HomeProvider();
appPath = await getApplicationDocumentsDirectory(); appPath = await getApplicationDocumentsDirectory();
await _homeProvider.createDefaultAvatar();
appVersion = await _homeProvider.getAppVersion(); appVersion = await _homeProvider.getAppVersion();
prefs = await SharedPreferences.getInstance(); prefs = await SharedPreferences.getInstance();
@ -59,15 +60,21 @@ Future<void> main() async {
await Hive.initFlutter(appPath.path); await Hive.initFlutter(appPath.path);
Hive.registerAdapter(WalletDataAdapter()); Hive.registerAdapter(WalletDataAdapter());
Hive.registerAdapter(ChestDataAdapter()); Hive.registerAdapter(ChestDataAdapter());
Hive.registerAdapter(G1WalletsListAdapter());
Hive.registerAdapter(IdAdapter());
walletBox = await Hive.openBox<WalletData>("walletBox"); walletBox = await Hive.openBox<WalletData>("walletBox");
chestBox = await Hive.openBox<ChestData>("chestBox"); chestBox = await Hive.openBox<ChestData>("chestBox");
configBox = await Hive.openBox("configBox"); configBox = await Hive.openBox("configBox");
g1WalletsBox = await Hive.openBox<G1WalletsList>("g1WalletsBox");
g1WalletsBox.clear();
// final HiveStore _store = // final HiveStore _store =
// await HiveStore.open(path: '${appPath.path}/gqlCache'); // await HiveStore.open(path: '${appPath.path}/gqlCache');
// Get a valid GVA endpoint // Get a valid GVA endpoint
endPointGVA = 'https://g1.librelois.fr/gva'; // endPointGVA = 'https://g1.librelois.fr/gva';
endPointGVA = 'https://duniter-g1.p2p.legal/gva';
// await _homeProvider.getValidEndpoint(); // await _homeProvider.getValidEndpoint();
// if (endPointGVA == 'HS') { // if (endPointGVA == 'HS') {
@ -76,6 +83,8 @@ Future<void> main() async {
// _homeProvider.playSound('start', 0.2); // _homeProvider.playSound('start', 0.2);
// } // }
HttpOverrides.global = MyHttpOverrides();
if (kReleaseMode && enableSentry) { if (kReleaseMode && enableSentry) {
// CatcherOptions debugOptions = CatcherOptions(DialogReportMode(), [ // CatcherOptions debugOptions = CatcherOptions(DialogReportMode(), [
// SentryHandler(SentryClient(SentryOptions( // SentryHandler(SentryClient(SentryOptions(
@ -107,8 +116,6 @@ Future<void> main() async {
} else { } else {
print('Debug mode enabled: No sentry alerte'); print('Debug mode enabled: No sentry alerte');
HttpOverrides.global = MyHttpOverrides();
runApp(Gecko(endPointGVA)); runApp(Gecko(endPointGVA));
} }
} }
@ -134,54 +141,58 @@ class Gecko extends StatelessWidget {
// HistoryProvider _historyProvider = Provider.of<HistoryProvider>(context); // HistoryProvider _historyProvider = Provider.of<HistoryProvider>(context);
// HistoryProvider('').snackNode(context); // HistoryProvider('').snackNode(context);
return MultiProvider( return MultiProvider(
providers: [ providers: [
// Provider(create: (context) => HistoryProvider()), // Provider(create: (context) => HistoryProvider()),
ChangeNotifierProvider(create: (_) => HomeProvider()), ChangeNotifierProvider(create: (_) => HomeProvider()),
ChangeNotifierProvider(create: (_) => HistoryProvider('')), ChangeNotifierProvider(create: (_) => WalletsProfilesProvider('')),
ChangeNotifierProvider(create: (_) => MyWalletsProvider()), ChangeNotifierProvider(create: (_) => MyWalletsProvider()),
ChangeNotifierProvider(create: (_) => ChestProvider()), ChangeNotifierProvider(create: (_) => ChestProvider()),
ChangeNotifierProvider(create: (_) => GenerateWalletsProvider()), ChangeNotifierProvider(create: (_) => GenerateWalletsProvider()),
ChangeNotifierProvider(create: (_) => WalletOptionsProvider()), ChangeNotifierProvider(create: (_) => WalletOptionsProvider()),
ChangeNotifierProvider(create: (_) => ChangePinProvider()), ChangeNotifierProvider(create: (_) => ChangePinProvider()),
ChangeNotifierProvider(create: (_) => CesiumPlusProvider()) ChangeNotifierProvider(create: (_) => SearchProvider()),
], ChangeNotifierProvider(create: (_) => CesiumPlusProvider())
child: GraphQLProvider( ],
client: _client, child: GraphQLProvider(
child: MaterialApp( client: _client,
builder: (context, widget) => ResponsiveWrapper.builder( child: MaterialApp(
BouncingScrollWrapper.builder(context, widget), builder: (context, widget) => ResponsiveWrapper.builder(
maxWidth: 1200, BouncingScrollWrapper.builder(context, widget),
minWidth: 480, maxWidth: 1200,
defaultScale: true, minWidth: 480,
breakpoints: [ defaultScale: true,
const ResponsiveBreakpoint.resize(480, name: MOBILE), breakpoints: [
const ResponsiveBreakpoint.autoScale(800, name: TABLET), const ResponsiveBreakpoint.resize(480, name: MOBILE),
const ResponsiveBreakpoint.resize(1000, name: DESKTOP), const ResponsiveBreakpoint.autoScale(800, name: TABLET),
], const ResponsiveBreakpoint.resize(1000, name: DESKTOP),
background: Container(color: backgroundColor)), ],
title: 'Ğecko', background: Container(color: backgroundColor)),
theme: ThemeData( title: 'Ğecko',
appBarTheme: const AppBarTheme( theme: ThemeData(
color: Color(0xffFFD58D), appBarTheme: const AppBarTheme(
foregroundColor: Color(0xFF000000), color: Color(0xffFFD58D),
), foregroundColor: Color(0xFF000000),
primaryColor: const Color(0xffFFD58D),
textTheme: const TextTheme(
bodyText1: TextStyle(),
bodyText2: TextStyle(),
).apply(
bodyColor: const Color(0xFF000000),
),
colorScheme: ColorScheme.fromSwatch()
.copyWith(secondary: Colors.grey[850]),
), ),
home: const HomeScreen(), primaryColor: const Color(0xffFFD58D),
initialRoute: "/", textTheme: const TextTheme(
routes: { bodyText1: TextStyle(),
'/mywallets': (context) => WalletsHome(), bodyText2: TextStyle(),
}, ).apply(
bodyColor: const Color(0xFF000000),
),
colorScheme:
ColorScheme.fromSwatch().copyWith(secondary: Colors.grey[850]),
), ),
)); home: const HomeScreen(),
initialRoute: "/",
routes: {
'/mywallets': (context) => WalletsHome(),
'/search': (context) => const SearchScreen(),
'/searchResult': (context) => const SearchResultScreen(),
},
),
),
);
} }
} }

2050
lib/models/bip39_words.dart Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +1,18 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:gecko/globals.dart'; import 'package:gecko/globals.dart';
import 'package:http/http.dart' as http;
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
// import 'package:http/http.dart' as http;
class CesiumPlusProvider with ChangeNotifier { class CesiumPlusProvider with ChangeNotifier {
TextEditingController cesiumName = TextEditingController(); TextEditingController cesiumName = TextEditingController();
int iAvatar = 0; Image defaultAvatar(double size) =>
bool isComplete = false; Image.asset(('assets/icon_user.png'), height: size);
CancelToken avatarCancelToken = CancelToken();
Future<List> _buildQuery(_pubkey) async { Future<List> _buildQuery(_pubkey) async {
var queryGetAvatar = json.encode({ var queryGetAvatar = json.encode({
@ -61,45 +64,95 @@ class CesiumPlusProvider with ChangeNotifier {
Future<String> getName(String _pubkey) async { Future<String> getName(String _pubkey) async {
String _name; String _name;
if (g1WalletsBox.get(_pubkey).csName != null) {
return g1WalletsBox.get(_pubkey).csName;
}
List queryOptions = await _buildQuery(_pubkey); List queryOptions = await _buildQuery(_pubkey);
final response = await http.post((Uri.parse(queryOptions[0])),
body: queryOptions[1], headers: queryOptions[2]); var dio = Dio();
final responseJson = json.decode(response.body); Response response;
if (responseJson['hits']['hits'].toString() == '[]') { try {
response = await dio.post(
queryOptions[0],
data: queryOptions[1],
options: Options(
headers: queryOptions[2],
sendTimeout: 3000,
receiveTimeout: 5000,
),
);
// response = await http.post((Uri.parse(queryOptions[0])),
// body: queryOptions[1], headers: queryOptions[2]);
} catch (e) {
log.e(e);
}
if (response.data['hits']['hits'].toString() == '[]') {
return ''; return '';
} }
final bool _nameExist = final bool _nameExist =
responseJson['hits']['hits'][0]['_source'].containsKey("title"); response.data['hits']['hits'][0]['_source'].containsKey("title");
if (!_nameExist) { if (!_nameExist) {
return ''; return '';
} }
_name = responseJson['hits']['hits'][0]['_source']['title']; _name = response.data['hits']['hits'][0]['_source']['title'];
g1WalletsBox.get(_pubkey).csName = _name;
return _name; return _name;
} }
Future<List> getAvatar(String _pubkey) async { Future<Image> getAvatar(String _pubkey, double size) async {
if (g1WalletsBox.get(_pubkey).avatar != null) {
return g1WalletsBox.get(_pubkey).avatar;
}
var dio = Dio();
// log.d(_pubkey);
List queryOptions = await _buildQuery(_pubkey); List queryOptions = await _buildQuery(_pubkey);
final response = await http.post((Uri.parse(queryOptions[0])),
body: queryOptions[1], headers: queryOptions[2]); Response response;
final responseJson = json.decode(response.body); try {
if (responseJson['hits']['hits'].toString() == '[]') { response = await dio
return [File(appPath.path + '/default_avatar.png')]; .post(queryOptions[0],
data: queryOptions[1],
options: Options(
headers: queryOptions[2],
sendTimeout: 4000,
receiveTimeout: 15000,
),
cancelToken: avatarCancelToken)
.timeout(
const Duration(seconds: 15),
);
// response = await http.post((Uri.parse(queryOptions[0])),
// body: queryOptions[1], headers: queryOptions[2]);
} catch (e) {
log.e(e);
} }
final bool avatarExist =
responseJson['hits']['hits'][0]['_source'].containsKey("avatar"); if (response.data['hits']['hits'].toString() == '[]' ||
if (!avatarExist) { !response.data['hits']['hits'][0]['_source'].containsKey("avatar")) {
return [File(appPath.path + '/default_avatar.png')]; return defaultAvatar(size);
} }
final _avatar = final _avatar =
responseJson['hits']['hits'][0]['_source']['avatar']['_content']; response.data['hits']['hits'][0]['_source']['avatar']['_content'];
var avatarFile = var avatarFile =
File('${(await getTemporaryDirectory()).path}/avatar$iAvatar.png'); File('${(await getTemporaryDirectory()).path}/avatar_$_pubkey.png');
await avatarFile.writeAsBytes(base64.decode(_avatar)); await avatarFile.writeAsBytes(base64.decode(_avatar));
iAvatar++;
isComplete = true;
return [avatarFile]; final finalAvatar = Image.file(
avatarFile,
height: size,
fit: BoxFit.fitWidth,
);
g1WalletsBox.get(_pubkey).avatar = finalAvatar;
return finalAvatar;
} }
} }

View File

@ -0,0 +1,74 @@
import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';
part 'g1_wallets_list.g.dart';
@HiveType(typeId: 2)
class G1WalletsList {
@HiveField(0)
String pubkey;
@HiveField(1)
double balance;
@HiveField(3)
Id id;
@HiveField(4)
Image avatar;
@HiveField(5)
String username;
@HiveField(6)
String csName;
@HiveField(7)
bool isMembre;
G1WalletsList({
this.pubkey,
this.balance,
this.id,
this.avatar,
this.username,
this.csName,
this.isMembre,
});
G1WalletsList.fromJson(Map<String, dynamic> json) {
pubkey = json['pubkey'];
balance = json['balance'];
id = json['id'] != null ? Id.fromJson(json['id']) : null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['pubkey'] = pubkey;
data['balance'] = balance;
if (id != null) {
data['id'] = id.toJson();
}
return data;
}
}
@HiveType(typeId: 3)
class Id {
bool isMember;
String username;
Id({this.isMember, this.username});
Id.fromJson(Map<String, dynamic> json) {
isMember = json['isMember'];
username = json['username'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['isMember'] = isMember;
data['username'] = username;
return data;
}
}

View File

@ -0,0 +1,90 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: unused_local_variable
part of 'g1_wallets_list.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class G1WalletsListAdapter extends TypeAdapter<G1WalletsList> {
@override
final int typeId = 2;
@override
G1WalletsList read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return G1WalletsList(
pubkey: fields[0] as String,
balance: fields[1] as double,
id: fields[3] as Id,
avatar: fields[4] as Image,
username: fields[5] as String,
csName: fields[6] as String,
isMembre: fields[7] as bool,
);
}
@override
void write(BinaryWriter writer, G1WalletsList obj) {
writer
..writeByte(7)
..writeByte(0)
..write(obj.pubkey)
..writeByte(1)
..write(obj.balance)
..writeByte(3)
..write(obj.id)
..writeByte(4)
..write(obj.avatar)
..writeByte(5)
..write(obj.username)
..writeByte(6)
..write(obj.csName)
..writeByte(7)
..write(obj.isMembre);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is G1WalletsListAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}
class IdAdapter extends TypeAdapter<Id> {
@override
final int typeId = 3;
@override
Id read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return Id();
}
@override
void write(BinaryWriter writer, Id obj) {
writer.writeByte(0);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is IdAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

View File

@ -5,6 +5,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:gecko/globals.dart'; import 'package:gecko/globals.dart';
import 'package:gecko/models/bip39_words.dart';
import 'package:gecko/models/chest_data.dart'; import 'package:gecko/models/chest_data.dart';
import 'package:gecko/models/wallet_data.dart'; import 'package:gecko/models/wallet_data.dart';
import 'package:pdf/pdf.dart'; import 'package:pdf/pdf.dart';
@ -39,6 +40,21 @@ class GenerateWalletsProvider with ChangeNotifier {
bool canImport = false; bool canImport = false;
bool isPinChanged = false; bool isPinChanged = false;
// Import Chest
TextEditingController cellController0 = TextEditingController();
TextEditingController cellController1 = TextEditingController();
TextEditingController cellController2 = TextEditingController();
TextEditingController cellController3 = TextEditingController();
TextEditingController cellController4 = TextEditingController();
TextEditingController cellController5 = TextEditingController();
TextEditingController cellController6 = TextEditingController();
TextEditingController cellController7 = TextEditingController();
TextEditingController cellController8 = TextEditingController();
TextEditingController cellController9 = TextEditingController();
TextEditingController cellController10 = TextEditingController();
TextEditingController cellController11 = TextEditingController();
bool isFirstTimeSentenceComplete = true;
Future storeHDWChest( Future storeHDWChest(
NewWallet _wallet, String _name, BuildContext context) async { NewWallet _wallet, String _name, BuildContext context) async {
int chestNumber = 0; int chestNumber = 0;
@ -140,7 +156,7 @@ class GenerateWalletsProvider with ChangeNotifier {
Future<String> generateMnemonic() async { Future<String> generateMnemonic() async {
try { try {
generatedMnemonic = await DubpRust.genMnemonic(language: Language.french); generatedMnemonic = await DubpRust.genMnemonic(language: Language.french);
actualWallet = await generateWallet(generatedMnemonic); actualWallet = await generateWallet(generatedMnemonic, isImport: false);
walletIsGenerated = true; walletIsGenerated = true;
} catch (e) { } catch (e) {
log.e(e); log.e(e);
@ -148,7 +164,8 @@ class GenerateWalletsProvider with ChangeNotifier {
return generatedMnemonic; return generatedMnemonic;
} }
Future<NewWallet> generateWallet(generatedMnemonic) async { Future<NewWallet> generateWallet(String generatedMnemonic,
{@required bool isImport}) async {
try { try {
actualWallet = await DubpRust.genWalletFromMnemonic( actualWallet = await DubpRust.genWalletFromMnemonic(
language: Language.french, language: Language.french,
@ -159,8 +176,10 @@ class GenerateWalletsProvider with ChangeNotifier {
log.e(e); log.e(e);
} }
mnemonicController.text = generatedMnemonic; if (!isImport) {
pin.text = actualWallet.pin; mnemonicController.text = generatedMnemonic;
pin.text = actualWallet.pin;
}
// notifyListeners(); // notifyListeners();
return actualWallet; return actualWallet;
@ -288,15 +307,9 @@ class GenerateWalletsProvider with ChangeNotifier {
notifyListeners(); notifyListeners();
} }
void resetImportView() { void resetCesiumImportView() {
cesiumID.text = ''; cesiumID.text = cesiumPWD.text = cesiumPubkey.text = pin.text = '';
cesiumPWD.text = ''; canImport = isPinChanged = isCesiumIDVisible = isCesiumPWDVisible = false;
cesiumPubkey.text = '';
pin.text = '';
canImport = false;
isPinChanged = false;
isCesiumIDVisible = false;
isCesiumPWDVisible = false;
actualWallet = null; actualWallet = null;
notifyListeners(); notifyListeners();
} }
@ -315,6 +328,83 @@ class GenerateWalletsProvider with ChangeNotifier {
return _wordsList; return _wordsList;
} }
bool isBipWord(String word) {
notifyListeners();
// Needed for bad encoding of UTF-8
word = word.replaceAll('é', '');
word = word.replaceAll('è', '');
return bip39Words.contains(word);
}
bool isBipWordsList(List words) {
bool isValid = true;
for (String word in words) {
// Needed for bad encoding of UTF-8
word = word.replaceAll('é', '');
word = word.replaceAll('è', '');
if (!bip39Words.contains(word)) {
isValid = false;
}
}
return isValid;
}
void resetImportView() {
cellController0.text = cellController1.text = cellController2.text =
cellController3.text = cellController4.text = cellController5.text =
cellController6.text = cellController7.text = cellController8.text =
cellController9.text =
cellController10.text = cellController11.text = '';
isFirstTimeSentenceComplete = true;
notifyListeners();
}
bool isSentenceComplete(BuildContext context) {
if (isBipWordsList(
[
cellController0.text,
cellController1.text,
cellController2.text,
cellController3.text,
cellController4.text,
cellController5.text,
cellController6.text,
cellController7.text,
cellController8.text,
cellController9.text,
cellController10.text,
cellController11.text
],
)) {
if (isFirstTimeSentenceComplete) {
FocusScope.of(context).unfocus();
}
isFirstTimeSentenceComplete = false;
return true;
} else {
return false;
}
}
Future<bool> isSentenceValid() async {
String inputMnemonic =
'${cellController0.text} ${cellController1.text} ${cellController2.text} ${cellController3.text} ${cellController4.text} ${cellController5.text} ${cellController6.text} ${cellController7.text} ${cellController8.text} ${cellController9.text} ${cellController10.text} ${cellController11.text}';
// Needed for bad encoding of UTF-8
inputMnemonic = inputMnemonic.replaceAll('é', '');
inputMnemonic = inputMnemonic.replaceAll('è', '');
NewWallet generatedWallet =
await generateWallet(inputMnemonic, isImport: true);
if (generatedWallet == null) {
return false;
} else {
return true;
}
}
void reloadBuild() { void reloadBuild() {
notifyListeners(); notifyListeners();
} }

View File

@ -8,7 +8,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'dart:async'; import 'dart:async';
import 'package:gecko/globals.dart'; import 'package:gecko/globals.dart';
import 'package:gecko/screens/history.dart'; import 'package:gecko/screens/old_history_pay.dart';
import 'package:gecko/screens/myWallets/wallets_home.dart'; import 'package:gecko/screens/myWallets/wallets_home.dart';
import 'package:package_info/package_info.dart'; import 'package:package_info/package_info.dart';
@ -21,7 +21,8 @@ class HomeProvider with ChangeNotifier {
Widget appBarExplorer = Widget appBarExplorer =
Text('Explorateur', style: TextStyle(color: Colors.grey[850])); Text('Explorateur', style: TextStyle(color: Colors.grey[850]));
List currentTab = [HistoryScreen(), WalletsHome()]; List currentTab = [OldHistoryScreen(), WalletsHome()];
bool isFirstBuild = true;
// AudioCache player = AudioCache(prefix: 'sounds/'); // AudioCache player = AudioCache(prefix: 'sounds/');
get currentIndex => _currentIndex; get currentIndex => _currentIndex;
@ -99,16 +100,6 @@ class HomeProvider with ChangeNotifier {
return _endpoint; return _endpoint;
} }
Future createDefaultAvatar() async {
File defaultAvatar = File(appPath.path + '/default_avatar.png');
final bool isAvatarExist = await defaultAvatar.exists();
if (!isAvatarExist) {
final byteData = await rootBundle.load('assets/icon_user.png');
await defaultAvatar.writeAsBytes(byteData.buffer
.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));
}
}
T getRandomElement<T>(List<T> list) { T getRandomElement<T>(List<T> list) {
final random = Random(); final random = Random();
var i = random.nextInt(list.length); var i = random.nextInt(list.length);
@ -139,6 +130,22 @@ class HomeProvider with ChangeNotifier {
notifyListeners(); notifyListeners();
} }
void snackNode(context) {
if (isFirstBuild) {
String _message;
if (endPointGVA == 'HS') {
_message =
"Aucun noeud Duniter disponible, veuillez réessayer ultérieurement";
} else {
_message = "Vous êtes connecté au noeud\n${endPointGVA.split('/')[2]}";
}
final snackBar = SnackBar(
content: Text(_message), duration: const Duration(seconds: 2));
isFirstBuild = false;
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
}
void rebuildWidget() { void rebuildWidget() {
notifyListeners(); notifyListeners();
} }

View File

@ -71,8 +71,13 @@ class MyWalletsProvider with ChangeNotifier {
await walletBox.clear(); await walletBox.clear();
await chestBox.clear(); await chestBox.clear();
await configBox.delete('defaultWallet'); await configBox.delete('defaultWallet');
// await Future.delayed(const Duration(milliseconds: 50));
// notifyListeners();
Navigator.pop(context); await Navigator.of(context).pushNamedAndRemoveUntil(
'/',
ModalRoute.withName('/'),
);
} }
return 0; return 0;
} catch (e) { } catch (e) {

View File

@ -29,14 +29,12 @@ const String getHistory = r'''
issuers issuers
comment comment
outputs outputs
writtenTime
} }
sending { sending {
currency currency
issuers issuers
comment comment
outputs outputs
writtenTime
} }
} }
currentUd { currentUd {
@ -62,3 +60,36 @@ const String getBalance = r'''
} }
} }
'''; ''';
const String getWallets = r'''
query ($number: Int!, $cursor: String) {
wallets(pagination: {ord: ASC, pageSize: $number, cursor: $cursor}) {
pageInfo {
hasNextPage
endCursor
}
edges {
node {
script
balance {
amount
base
}
idty {
isMember
username
}
}
}
}
}
''';
const String getId = r'''
query ($pubkey: PubKeyGva!) {
idty(pubkey: $pubkey) {
isMember
username
}
}
''';

80
lib/models/search.dart Normal file
View File

@ -0,0 +1,80 @@
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/g1_wallets_list.dart';
import 'package:gecko/models/wallets_profiles.dart';
class SearchProvider with ChangeNotifier {
TextEditingController searchController = TextEditingController();
List searchResult = [];
final cacheDuring = 20 * 60 * 1000; //First number is minutes
int cacheTime = 0;
void rebuildWidget() {
notifyListeners();
}
Future<List> searchBlockchain() async {
searchResult.clear();
int searchTime = DateTime.now().millisecondsSinceEpoch;
WalletsProfilesProvider _walletProfiles = WalletsProfilesProvider('pubkey');
if (cacheTime + cacheDuring <= searchTime) {
g1WalletsBox.clear();
// final url = Uri.parse('https://g1-stats.axiom-team.fr/data/forbes.json');
// final response = await http.get(url);
var dio = Dio();
Response response;
try {
response = await dio.get(
'https://g1-stats.axiom-team.fr/data/forbes.json',
options: Options(
sendTimeout: 5000,
receiveTimeout: 10000,
),
);
// response = await http.post((Uri.parse(queryOptions[0])),
// body: queryOptions[1], headers: queryOptions[2]);
} catch (e) {
log.e(e);
}
List<G1WalletsList> _listWallets = _parseG1Wallets(response.data);
Map<String, G1WalletsList> _mapWallets = {
for (var e in _listWallets) e.pubkey: e
};
await g1WalletsBox.putAll(_mapWallets);
cacheTime = DateTime.now().millisecondsSinceEpoch;
}
g1WalletsBox.toMap().forEach((key, value) {
if ((value.id != null &&
value.id.username != null &&
value.id.username
.toLowerCase()
.contains(searchController.text)) ||
value.pubkey.contains(searchController.text)) {
searchResult.add(value);
return;
}
});
if (searchResult.isEmpty &&
_walletProfiles.isPubkey(searchController.text)) {
searchResult = [G1WalletsList(pubkey: searchController.text)];
}
return searchResult;
}
}
List<G1WalletsList> _parseG1Wallets(var responseBody) {
final parsed = responseBody.cast<Map<String, dynamic>>();
return parsed
.map<G1WalletsList>((json) => G1WalletsList.fromJson(json))
.toList();
}

View File

@ -2,14 +2,12 @@ import 'package:dubp/dubp.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:gecko/globals.dart'; import 'package:gecko/globals.dart';
import 'package:gecko/models/home.dart';
import 'package:gecko/models/my_wallets.dart'; import 'package:gecko/models/my_wallets.dart';
import 'package:gecko/models/wallet_data.dart'; import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/screens/history.dart'; import 'package:gecko/screens/wallet_view.dart';
import 'package:graphql_flutter/graphql_flutter.dart'; import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:jdenticon_dart/jdenticon_dart.dart'; import 'package:jdenticon_dart/jdenticon_dart.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart';
import 'package:qrscan/qrscan.dart' as scanner; import 'package:qrscan/qrscan.dart' as scanner;
import 'dart:math'; import 'dart:math';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
@ -17,13 +15,13 @@ import 'package:truncate/truncate.dart';
import 'package:crypto/crypto.dart'; import 'package:crypto/crypto.dart';
import 'package:fast_base58/fast_base58.dart'; import 'package:fast_base58/fast_base58.dart';
class HistoryProvider with ChangeNotifier { class WalletsProfilesProvider with ChangeNotifier {
WalletsProfilesProvider(this.pubkey);
String pubkey = ''; String pubkey = '';
String pubkeyShort = ''; String pubkeyShort = '';
HistoryProvider(this.pubkey);
final TextEditingController outputPubkey = TextEditingController(); final TextEditingController outputPubkey = TextEditingController();
List transBC; List transBC;
bool isFirstBuild = true;
String fetchMoreCursor; String fetchMoreCursor;
Map pageInfo; Map pageInfo;
bool isHistoryScreen = false; bool isHistoryScreen = false;
@ -31,6 +29,9 @@ class HistoryProvider with ChangeNotifier {
String rawSvg; String rawSvg;
TextEditingController payAmount = TextEditingController(); TextEditingController payAmount = TextEditingController();
TextEditingController payComment = TextEditingController(); TextEditingController payComment = TextEditingController();
num balance;
int nRepositories = 20;
int nPage = 1;
Future scan(context) async { Future scan(context) async {
await Permission.camera.request(); await Permission.camera.request();
@ -41,9 +42,14 @@ class HistoryProvider with ChangeNotifier {
log.e(e); log.e(e);
return 'false'; return 'false';
} }
if (barcode != null) { if (barcode != null && isPubkey(barcode)) {
outputPubkey.text = barcode; outputPubkey.text = barcode;
isPubkey(context, barcode); Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return WalletViewScreen(pubkey: pubkey);
}),
);
} else { } else {
return 'false'; return 'false';
} }
@ -56,10 +62,17 @@ class HistoryProvider with ChangeNotifier {
WalletData defaultWallet = _myWalletModel.getDefaultWallet(currentChest); WalletData defaultWallet = _myWalletModel.getDefaultWallet(currentChest);
String dewif = chestBox.get(currentChest).dewif; String dewif = chestBox.get(currentChest).dewif;
int derivation;
if (chestBox.get(currentChest).isCesium) {
derivation = 0;
} else {
derivation = defaultWallet.derivation;
}
try { try {
await DubpRust.simplePaymentFromTransparentAccount( await DubpRust.simplePaymentFromTransparentAccount(
accountIndex: defaultWallet.derivation, accountIndex: derivation,
amount: double.parse(payAmount.text), amount: double.parse(payAmount.text),
txComment: payComment.text, txComment: payComment.text,
dewif: dewif, dewif: dewif,
@ -74,9 +87,7 @@ class HistoryProvider with ChangeNotifier {
} }
} }
String isPubkey(context, pubkey, {bool goHistory}) { bool isPubkey(pubkey) {
HomeProvider _homeProvider =
Provider.of<HomeProvider>(context, listen: false);
final RegExp regExp = RegExp( final RegExp regExp = RegExp(
r'^[a-zA-Z0-9]+$', r'^[a-zA-Z0-9]+$',
caseSensitive: false, caseSensitive: false,
@ -86,36 +97,25 @@ class HistoryProvider with ChangeNotifier {
if (regExp.hasMatch(pubkey) == true && if (regExp.hasMatch(pubkey) == true &&
pubkey.length > 42 && pubkey.length > 42 &&
pubkey.length < 45) { pubkey.length < 45) {
log.d("C'est une pubkey !!!"); log.d("C'est une pubkey !");
this.pubkey = pubkey; this.pubkey = pubkey;
getShortPubkey(pubkey); // getShortPubkey(pubkey);
outputPubkey.text = pubkey; // outputPubkey.text = pubkey;
goHistory ??= false; // Navigator.push(
// context,
// MaterialPageRoute(builder: (context) {
// return const WalletViewScreen();
// }),
// );
// notifyListeners();
if (goHistory) { return true;
isHistoryScreen = true; } else {
historySwitchButtun = "Payer"; return false;
} else {
isHistoryScreen = false;
historySwitchButtun = "Voir l'historique";
}
_homeProvider.handleSearchEnd();
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return HistoryScreen();
}),
);
notifyListeners();
return pubkey;
} }
return '';
} }
String getShortPubkey(String pubkey) { String getShortPubkey(String pubkey) {
@ -200,13 +200,25 @@ class HistoryProvider with ChangeNotifier {
FetchMoreOptions checkQueryResult(result, opts, _pubkey) { FetchMoreOptions checkQueryResult(result, opts, _pubkey) {
final List<dynamic> blockchainTX = final List<dynamic> blockchainTX =
(result.data['txsHistoryBc']['both']['edges'] as List<dynamic>); (result.data['txsHistoryBc']['both']['edges'] as List<dynamic>);
// final List<dynamic> mempoolTX =
// (result.data['txsHistoryMp']['receiving'] as List<dynamic>);
pageInfo = result.data['txsHistoryBc']['both']['pageInfo']; pageInfo = result.data['txsHistoryBc']['both']['pageInfo'];
fetchMoreCursor = pageInfo['endCursor']; fetchMoreCursor = pageInfo['endCursor'];
if (fetchMoreCursor == null) nPage = 1;
if (nPage == 1) {
nRepositories = 40;
} else if (nPage == 2) {
nRepositories = 100;
}
log.d(nPage);
log.d(nRepositories);
nPage++;
if (fetchMoreCursor != null) { if (fetchMoreCursor != null) {
opts = FetchMoreOptions( opts = FetchMoreOptions(
variables: {'cursor': fetchMoreCursor}, variables: {'cursor': fetchMoreCursor, 'number': nRepositories},
updateQuery: (previousResultData, fetchMoreResultData) { updateQuery: (previousResultData, fetchMoreResultData) {
final List<dynamic> repos = [ final List<dynamic> repos = [
...previousResultData['txsHistoryBc']['both']['edges'] ...previousResultData['txsHistoryBc']['both']['edges']
@ -232,22 +244,6 @@ class HistoryProvider with ChangeNotifier {
return opts; return opts;
} }
void snackNode(context) {
if (isFirstBuild) {
String _message;
if (endPointGVA == 'HS') {
_message =
"Aucun noeud Duniter disponible, veuillez réessayer ultérieurement";
} else {
_message = "Vous êtes connecté au noeud\n${endPointGVA.split('/')[2]}";
}
final snackBar = SnackBar(
content: Text(_message), duration: const Duration(seconds: 2));
isFirstBuild = false;
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
}
void resetdHistory() { void resetdHistory() {
outputPubkey.text = ''; outputPubkey.text = '';
notifyListeners(); notifyListeners();
@ -260,6 +256,7 @@ class HistoryProvider with ChangeNotifier {
snackCopyKey(context) { snackCopyKey(context) {
const snackBar = SnackBar( const snackBar = SnackBar(
padding: EdgeInsets.all(20),
content: content:
Text("Cette clé publique a été copié dans votre presse-papier."), Text("Cette clé publique a été copié dans votre presse-papier."),
duration: Duration(seconds: 2)); duration: Duration(seconds: 2));
@ -279,4 +276,27 @@ class HistoryProvider with ChangeNotifier {
String generateIdenticon(String _pubkey) { String generateIdenticon(String _pubkey) {
return Jdenticon.toSvg(_pubkey); return Jdenticon.toSvg(_pubkey);
} }
// Future<num> getBalance(String _pubkey) async {
// final url = Uri.parse(
// '$endPointGVA?query={%20balance(script:%20%22$_pubkey%22)%20{%20amount%20base%20}%20}');
// final response = await http.get(url);
// final result = json.decode(response.body);
// if (result['data']['balance'] == null) {
// balance = 0.0;
// } else {
// balance = removeDecimalZero(result['data']['balance']['amount'] / 100);
// }
// return balance;
// }
Future<num> getBalance(String _pubkey) async {
while (balance == null) {
await Future.delayed(const Duration(milliseconds: 50));
}
return balance;
}
} }

View File

@ -0,0 +1,54 @@
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:flutter/material.dart';
// import 'package:gecko/models/home.dart';
// import 'package:provider/provider.dart';
// ignore: must_be_immutable
class AvatarFullscreen extends StatelessWidget {
TextEditingController tplController = TextEditingController();
AvatarFullscreen(this.avatar, {this.title, this.color, Key key})
: super(key: key);
final Image avatar;
final String title;
final Color color;
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
// HomeProvider _homeProvider = Provider.of<HomeProvider>(context);
return Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: color ?? Colors.black,
toolbarHeight: 60 * ratio,
leading: IconButton(
icon: Icon(Icons.arrow_back, color: orangeC),
onPressed: () {
Navigator.pop(context);
}),
title: SizedBox(
height: 22,
child: Text(
title ?? 'Photo de profil',
style: TextStyle(color: orangeC),
),
)),
body: SafeArea(
child: SizedBox.expand(
child: Container(
color: color ?? Colors.black,
// alignment: Alignment.center,
// height: MediaQuery.of(context).size.height,
// width: MediaQuery.of(context).size.width,
child: Image(
image: avatar.image,
height: avatar.height,
fit: BoxFit.fitWidth),
),
),
),
);
}
}

View File

@ -34,14 +34,15 @@ class CommonElements {
margin: const BubbleEdges.fromLTRB(10, 0, 20, 10), margin: const BubbleEdges.fromLTRB(10, 0, 20, 10),
// nip: BubbleNip.leftTop, // nip: BubbleNip.leftTop,
child: RichText( child: RichText(
key: textKey, key: textKey,
text: TextSpan( text: TextSpan(
style: const TextStyle( style: const TextStyle(
fontSize: 18.0, fontSize: 18.0,
color: Colors.black, color: Colors.black,
), ),
children: text, children: text,
)), ),
),
); );
} }

View File

@ -1,124 +1,64 @@
import 'dart:io';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:gecko/globals.dart'; import 'package:gecko/globals.dart';
import 'package:gecko/models/cesium_plus.dart'; import 'package:gecko/models/cesium_plus.dart';
import 'package:gecko/models/home.dart';
import 'package:gecko/models/my_wallets.dart';
import 'package:gecko/models/queries.dart'; import 'package:gecko/models/queries.dart';
import 'package:gecko/models/history.dart'; import 'package:gecko/models/wallets_profiles.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:gecko/models/wallet_data.dart'; import 'package:gecko/screens/avatar_fullscreen.dart';
import 'package:gecko/screens/myWallets/unlocking_wallet.dart'; import 'package:gecko/screens/wallet_view.dart';
import 'dart:ui'; import 'dart:ui';
import 'package:graphql_flutter/graphql_flutter.dart'; import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:flutter_svg/flutter_svg.dart';
// ignore: must_be_immutable // ignore: must_be_immutable
class HistoryScreen extends StatelessWidget with ChangeNotifier { class HistoryScreen extends StatelessWidget with ChangeNotifier {
final TextEditingController _outputPubkey = TextEditingController(); HistoryScreen({@required this.pubkey, this.avatar, this.username, Key key})
ScrollController scrollController = ScrollController(); : super(key: key);
final nRepositories = 20; final ScrollController scrollController = ScrollController();
// HistoryProvider _historyProvider;
final _formKey = GlobalKey<FormState>();
final FocusNode _pubkeyFocus = FocusNode();
List cesiumData;
final double avatarsSize = 80; final double avatarsSize = 80;
final String pubkey;
final String username;
final Image avatar;
FetchMore fetchMore; FetchMore fetchMore;
FetchMoreOptions opts; FetchMoreOptions opts;
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
HistoryScreen({Key key}) : super(key: key); final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
HistoryProvider _historyProvider = Provider.of<HistoryProvider>(context); WalletsProfilesProvider _historyProvider =
HomeProvider _homeProvider = Provider.of<HomeProvider>(context); Provider.of<WalletsProfilesProvider>(context, listen: false);
_outputPubkey.text = _historyProvider.pubkey; CesiumPlusProvider _cesiumPlusProvider =
log.i('Build pubkey : ' + _historyProvider.pubkey); Provider.of<CesiumPlusProvider>(context, listen: false);
log.i('Build pubkey : ' + pubkey);
WidgetsBinding.instance.addPostFrameCallback((_) {}); WidgetsBinding.instance.addPostFrameCallback((_) {});
_historyProvider.balance = _historyProvider.transBC = null;
return Scaffold( return Scaffold(
key: _scaffoldKey, key: _scaffoldKey,
appBar: AppBar( appBar: AppBar(
elevation: 0,
toolbarHeight: 60 * ratio, toolbarHeight: 60 * ratio,
title: _homeProvider.appBarExplorer, title: const SizedBox(
actions: [ height: 22,
Padding( child: Text('Historique des transactions'),
padding: const EdgeInsets.symmetric(horizontal: 16),
child: IconButton(
icon: _homeProvider.searchIcon,
color: Colors.grey[850],
onPressed: () {
if (_homeProvider.searchIcon.icon == Icons.search) {
_homeProvider.searchIcon = Icon(
Icons.close,
color: Colors.grey[850],
);
_homeProvider.appBarExplorer = TextField(
autofocus: true,
controller: _homeProvider.searchQuery,
onChanged: (text) {
log.d("Clé tappé: $text");
final String searchResult =
_historyProvider.isPubkey(context, text);
if (searchResult != '') {
_homeProvider.currentIndex = 0;
}
},
style: TextStyle(
color: Colors.grey[850],
),
decoration: InputDecoration(
prefixIcon:
Icon(Icons.search, color: Colors.grey[850]),
hintText: "Rechercher ...",
hintStyle: TextStyle(color: Colors.grey[850])),
);
_homeProvider.handleSearchStart();
} else {
_homeProvider.handleSearchEnd();
}
}))
],
backgroundColor: const Color(0xffFFD58D),
),
floatingActionButton: SizedBox(
height: 80.0,
width: 80.0,
child: FittedBox(
child: FloatingActionButton(
heroTag: "buttonScan",
onPressed: () async {
await _historyProvider.scan(context);
},
child: SizedBox(
height: 40.0,
width: 40.0,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 3),
child: Image.asset('assets/qrcode-scan.png'))),
backgroundColor:
floattingYellow, //smoothYellow, //Color.fromARGB(500, 204, 255, 255),
),
), ),
), ),
body: Column(children: <Widget>[ body: Column(children: <Widget>[
const SizedBox(height: 0), headerProfileView(context, _historyProvider, _cesiumPlusProvider),
if (_historyProvider.pubkey != '') historyQuery(context, _cesiumPlusProvider),
historyQuery(context, _historyProvider),
])); ]));
} }
Widget historyQuery(context, HistoryProvider _historyProvider) { Widget historyQuery(context, CesiumPlusProvider _cesiumPlusProvider) {
_pubkeyFocus.unfocus(); WalletsProfilesProvider _historyProvider =
// HistoryProvider _historyProvider = Provider.of<HistoryProvider>(context); Provider.of<WalletsProfilesProvider>(context, listen: true);
CesiumPlusProvider _cesiumPlusProvider =
Provider.of<CesiumPlusProvider>(context);
bool _isFirstExec = true;
return Expanded( return Expanded(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
@ -128,8 +68,8 @@ class HistoryScreen extends StatelessWidget with ChangeNotifier {
options: QueryOptions( options: QueryOptions(
document: gql(getHistory), document: gql(getHistory),
variables: <String, dynamic>{ variables: <String, dynamic>{
'pubkey': _historyProvider.pubkey, 'pubkey': pubkey,
'number': nRepositories, 'number': 10,
'cursor': null 'cursor': null
}, },
), ),
@ -146,182 +86,47 @@ class HistoryScreen extends StatelessWidget with ChangeNotifier {
SizedBox(height: 50), SizedBox(height: 50),
Text( Text(
"Aucun noeud GVA valide n'a pu être trouvé.\nVeuillez réessayer ultérieurement.", "Aucun noeud GVA valide n'a pu être trouvé.\nVeuillez réessayer ultérieurement.",
style: TextStyle(fontSize: 17.0), style: TextStyle(fontSize: 18),
)
]);
} else if (result.data == null) {
return Column(children: const <Widget>[
SizedBox(height: 50),
Text(
"Aucune donnée à afficher.",
style: TextStyle(fontSize: 18),
) )
]); ]);
} }
if (result.data == null && result.exception.toString() == null) {
return const Text('Aucune donnée à afficher.');
}
num balance;
if (result.data['balance'] == null) { if (result.data['balance'] == null) {
balance = 0.0; _historyProvider.balance = 0.0;
} else { } else {
balance = _historyProvider _historyProvider.balance = _historyProvider
.removeDecimalZero(result.data['balance']['amount'] / 100); .removeDecimalZero(result.data['balance']['amount'] / 100);
} }
opts = _historyProvider.checkQueryResult( if (result.isNotLoading) {
result, opts, _outputPubkey.text); // log.d(result.data);
opts = _historyProvider.checkQueryResult(result, opts, pubkey);
// _historyProvider.transBC = null; }
// Build history list // Build history list
return NotificationListener( return NotificationListener(
child: Builder( child: Builder(
builder: (context) => Expanded( builder: (context) => Expanded(
child: ListView( child: ListView(
key: const Key('listTransactions'), key: const Key('listTransactions'),
controller: scrollController, controller: scrollController,
children: <Widget>[ children: <Widget>[historyView(context, result)],
const SizedBox(height: 20), ),
if (_historyProvider.pubkey != '') ),
Row( ),
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
if (_isFirstExec)
Container(
padding: const EdgeInsets.fromLTRB(
20, 0, 30, 0),
child: FutureBuilder(
future:
_cesiumPlusProvider.getAvatar(
_historyProvider.pubkey),
initialData: [
File(appPath.path +
'/default_avatar.png')
],
builder: (BuildContext context,
AsyncSnapshot<List> _avatar) {
cesiumData = _avatar.data;
// _cesiumPlusProvider.isComplete = true;
if (_avatar.connectionState !=
ConnectionState.done) {
return Image.file(
File(appPath.path +
'/default_avatar.png'),
height: avatarsSize);
}
if (_avatar.hasError) {
return Image.file(
File(appPath.path +
'/default_avatar.png'),
height: avatarsSize);
}
if (_avatar.hasData) {
return SingleChildScrollView(
padding:
const EdgeInsets.all(
0.0),
child: Image.file(
_avatar.data[0],
height: avatarsSize));
}
return Image.file(
File(appPath.path +
'/default_avatar.png'),
height: avatarsSize);
})),
GestureDetector(
key: const Key('copyPubkey'),
onTap: () {
Clipboard.setData(ClipboardData(
text: _historyProvider.pubkey));
_historyProvider.snackCopyKey(context);
},
child: Text(
_historyProvider.getShortPubkey(
_historyProvider.pubkey),
style: const TextStyle(
fontSize: 22,
fontWeight: FontWeight.w800,
fontFamily: 'Monospace')),
),
Container(
padding: const EdgeInsets.fromLTRB(
30, 0, 5, 0), // .only(right: 15),
child: Card(
child: Column(
children: <Widget>[
SvgPicture.string(
_historyProvider
.generateIdenticon(
_historyProvider
.pubkey),
fit: BoxFit.contain,
height: 64,
width: 64,
),
],
),
)),
const SizedBox(width: 0)
]),
if (_isFirstExec)
Row(
mainAxisAlignment:
MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
padding: const EdgeInsets.fromLTRB(
0, 0, 0, 0),
// padding: const EdgeInsets.,
child: FutureBuilder(
future: _cesiumPlusProvider.getName(
_historyProvider.pubkey),
initialData: '...',
builder: (context, snapshot) {
return Text(snapshot.data ?? '-',
style: const TextStyle(
fontSize: 20));
}))
]),
const SizedBox(height: 18),
if (_isFirstExec)
Container(
padding:
const EdgeInsets.fromLTRB(0, 0, 0, 0),
child: Text(balance.toString() + ' Ğ1',
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 18.0))),
const SizedBox(height: 20),
ElevatedButton(
key: const Key('switchPayHistory'),
style: ElevatedButton.styleFrom(
elevation: 1,
primary: Colors.grey[50], // background
onPrimary: Colors.black, // foreground
),
onPressed: () {
_historyProvider.switchProfileView();
},
child: Text(
_historyProvider.historySwitchButtun,
style: TextStyle(
fontSize: 15, color: orangeC))),
// const Divider(
// color: Colors.grey,
// height: 5,
// thickness: 0.5,
// indent: 0,
// endIndent: 0,
// ),
_historyProvider.isHistoryScreen
? historyView(context, result)
: payView(context, _historyProvider),
],
))),
onNotification: (t) { onNotification: (t) {
if (t is ScrollEndNotification && if (t is ScrollEndNotification &&
scrollController.position.pixels >= scrollController.position.pixels >=
scrollController.position.maxScrollExtent * 0.7) { scrollController.position.maxScrollExtent * 0.7 &&
_historyProvider.pageInfo['hasPreviousPage']) {
fetchMore(opts); fetchMore(opts);
} }
return true; return true;
@ -332,125 +137,28 @@ class HistoryScreen extends StatelessWidget with ChangeNotifier {
)); ));
} }
Widget payView(context, HistoryProvider _historyProvider) {
MyWalletsProvider _myWalletProvider = MyWalletsProvider();
WalletData defaultWallet =
_myWalletProvider.getDefaultWallet(configBox.get('currentChest'));
return Stack(
clipBehavior: Clip.hardEdge,
children: <Widget>[
Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const SizedBox(height: 20),
const Text('Commentaire:', style: TextStyle(fontSize: 20.0)),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
controller: _historyProvider.payComment,
maxLines: 2,
textAlign: TextAlign.center,
decoration: const InputDecoration(),
style: const TextStyle(
fontSize: 22,
color: Colors.black,
fontWeight: FontWeight.bold))),
const SizedBox(height: 20),
const Text('Montant (DU/Ğ1):', style: TextStyle(fontSize: 20.0)),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
style: const TextStyle(fontSize: 22),
controller: _historyProvider.payAmount,
textAlign: TextAlign.center,
maxLines: 1,
keyboardType: TextInputType.number,
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(
vertical: 25.0, horizontal: 10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0)),
),
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.allow(RegExp(r'(^\d*\.?\d*)'))
],
),
),
Padding(
padding: const EdgeInsets.only(top: 15),
child: OutlinedButton(
style: OutlinedButton.styleFrom(
side: BorderSide(width: 2, color: orangeC)),
onPressed: () {
// if (_formKey.currentState.validate()) {
// _formKey.currentState.save();
// }
// _historyProvider.pay(payAmount.text, payComment.text);
Navigator.push(context,
MaterialPageRoute(builder: (context) {
return UnlockingWallet(
wallet: defaultWallet, action: "pay");
}));
},
child: Padding(
padding: const EdgeInsets.all(12),
child: Text("PAYER",
style: TextStyle(
fontSize: 25, color: Colors.grey[850]))),
))
],
),
),
],
);
}
Widget historyView(context, result) { Widget historyView(context, result) {
HistoryProvider _historyProvider = Provider.of<HistoryProvider>(context); WalletsProfilesProvider _historyProvider =
int keyID = 0; Provider.of<WalletsProfilesProvider>(context, listen: false);
return _historyProvider.transBC == null return _historyProvider.transBC == null
? const Text('Aucune transaction à afficher.') ? Column(children: const <Widget>[
SizedBox(height: 50),
Text(
"Aucune transaction à afficher.",
style: TextStyle(fontSize: 18),
)
])
: Column(children: <Widget>[ : Column(children: <Widget>[
for (var repository in _historyProvider.transBC) getTransactionTile(context, _historyProvider),
Padding( if (result.isLoading &&
padding: const EdgeInsets.symmetric(horizontal: 5.0), _historyProvider.pageInfo['hasPreviousPage'])
child: ListTile(
key: Key('transaction${keyID++}'),
contentPadding: const EdgeInsets.all(5.0),
leading: Text(repository[1].toString(),
style: TextStyle(
fontSize: 12,
color: Colors.grey[800],
fontWeight: FontWeight.w700),
textAlign: TextAlign.center),
title: Text(repository[3],
style: const TextStyle(
fontSize: 15.0, fontFamily: 'Monospace'),
textAlign: TextAlign.center),
subtitle: Text(repository[6] != '' ? repository[6] : '-',
style: const TextStyle(fontSize: 12.0),
textAlign: TextAlign.center),
trailing: Text("${repository[4]} Ğ1",
style: const TextStyle(fontSize: 14.0),
textAlign: TextAlign.justify),
dense: true,
isThreeLine: false,
onTap: () {
// this._outputPubkey.text = repository[2];
_historyProvider.isPubkey(context, repository[2]);
})),
if (result.isLoading)
Row( Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[ children: const <Widget>[
CircularProgressIndicator(), CircularProgressIndicator(),
], ],
), ),
// if (_historyProvider.isTheEnd) // What I did before ...
if (!_historyProvider.pageInfo['hasPreviousPage']) if (!_historyProvider.pageInfo['hasPreviousPage'])
Column( Column(
children: const <Widget>[ children: const <Widget>[
@ -463,4 +171,384 @@ class HistoryScreen extends StatelessWidget with ChangeNotifier {
) )
]); ]);
} }
Widget getTransactionTile(
BuildContext context, WalletsProfilesProvider _historyProvider) {
CesiumPlusProvider _cesiumPlusProvider =
Provider.of<CesiumPlusProvider>(context, listen: false);
int keyID = 0;
String dateDelimiter;
String lastDateDelimiter;
const double _avatarSize = 200;
bool isTody = false;
bool isYesterday = false;
bool isThisWeek = false;
const Map<int, String> monthsInYear = {
1: "Janvier",
2: "Février",
3: "Mars",
4: "Avril",
5: "Mai",
6: "Juin",
7: "Juillet",
8: "Aout",
9: "Septembre",
10: "Octobre",
11: "Novembre",
12: "Décembre"
};
return Column(
children: _historyProvider.transBC.map((repository) {
DateTime now = DateTime.now();
DateTime date = DateTime.fromMillisecondsSinceEpoch(repository[0] * 1000);
String dateForm;
if ({4, 10, 11, 12}.contains(date.month)) {
dateForm = "${date.day} ${monthsInYear[date.month].substring(0, 3)}.";
} else if ({1, 2, 7, 9}.contains(date.month)) {
dateForm = "${date.day} ${monthsInYear[date.month].substring(0, 4)}.";
} else {
dateForm = "${date.day} ${monthsInYear[date.month]}";
}
int weekNumber(DateTime date) {
int dayOfYear = int.parse(DateFormat("D").format(date));
return ((dayOfYear - date.weekday + 10) / 7).floor();
}
if (DateTime(date.year, date.month, date.day) ==
DateTime(now.year, now.month, now.day) &&
!isTody) {
dateDelimiter = lastDateDelimiter = "Aujourd'hui";
isTody = true;
} else if (DateTime(date.year, date.month, date.day) ==
DateTime(now.year, now.month, now.day - 1) &&
!isYesterday) {
dateDelimiter = lastDateDelimiter = "Hier";
isYesterday = true;
} else if (weekNumber(date) == weekNumber(now) &&
date.year == now.year &&
lastDateDelimiter != "Cette semaine" &&
DateTime(date.year, date.month, date.day) !=
DateTime(now.year, now.month, now.day - 1) &&
!isThisWeek) {
dateDelimiter = lastDateDelimiter = "Cette semaine";
isThisWeek = true;
} else if (lastDateDelimiter != monthsInYear[date.month] &&
lastDateDelimiter != "${monthsInYear[date.month]} ${date.year}" &&
DateTime(date.year, date.month, date.day) !=
DateTime(now.year, now.month, now.day) &&
DateTime(date.year, date.month, date.day) !=
DateTime(now.year, now.month, now.day - 1) &&
!(weekNumber(date) == weekNumber(now) && date.year == now.year)) {
if (date.year == now.year) {
dateDelimiter = lastDateDelimiter = monthsInYear[date.month];
} else {
dateDelimiter =
lastDateDelimiter = "${monthsInYear[date.month]} ${date.year}";
}
} else {
dateDelimiter = null;
}
return Column(children: <Widget>[
if (dateDelimiter != null)
Padding(
padding: const EdgeInsets.symmetric(vertical: 30),
child: Text(
dateDelimiter,
style: TextStyle(
fontSize: 23, color: orangeC, fontWeight: FontWeight.w300),
),
),
Padding(
padding: const EdgeInsets.only(right: 0),
child:
// Row(children: [Column(children: [],)],)
ListTile(
key: Key('transaction${keyID++}'),
contentPadding: const EdgeInsets.only(
left: 20, right: 30, top: 15, bottom: 15),
leading: g1WalletsBox.get(repository[2])?.avatar == null
? FutureBuilder(
future: _cesiumPlusProvider.getAvatar(
repository[2], _avatarSize),
builder: (BuildContext context,
AsyncSnapshot<Image> _avatar) {
if (_avatar.connectionState !=
ConnectionState.done ||
_avatar.hasError) {
return Stack(children: [
_cesiumPlusProvider.defaultAvatar(_avatarSize),
Positioned(
top: 8,
right: 0,
width: 12,
height: 12,
child: CircularProgressIndicator(
strokeWidth: 1,
color: orangeC,
),
),
]);
}
if (_avatar.hasData) {
g1WalletsBox.get(repository[2]).avatar =
_avatar.data;
return ClipOval(child: _avatar.data);
} else {
g1WalletsBox.get(repository[2]).avatar =
_cesiumPlusProvider
.defaultAvatar(repository[2]);
return _cesiumPlusProvider
.defaultAvatar(_avatarSize);
}
})
: ClipOval(
child: Image(
image: g1WalletsBox.get(repository[2]).avatar.image,
height: _avatarSize,
),
),
title: Padding(
padding: EdgeInsets.only(
bottom: 5, top: repository[6] != '' ? 0 : 0),
child: Text(repository[3],
style: const TextStyle(
fontSize: 18, fontFamily: 'Monospace')),
),
subtitle: RichText(
text: TextSpan(
style: TextStyle(
fontSize: 16,
color: Colors.grey[700],
),
children: <TextSpan>[
TextSpan(
text: dateForm,
),
if (repository[6] != '')
TextSpan(
text: ' · ',
style: TextStyle(
fontSize: 20,
color: Colors.grey[550],
),
),
TextSpan(
text: repository[6],
style: TextStyle(
fontStyle: FontStyle.italic,
color: Colors.grey[600],
),
),
],
),
),
trailing: Text("${repository[4]} Ğ1",
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.w500),
textAlign: TextAlign.justify),
dense: false,
isThreeLine: false,
onTap: () {
_historyProvider.nPage = 1;
// _cesiumPlusProvider.avatarCancelToken.cancel('cancelled');
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return WalletViewScreen(pubkey: repository[2]);
}),
);
// Navigator.pop(context);
}),
),
]);
}).toList());
}
Widget headerProfileView(
BuildContext context,
WalletsProfilesProvider _historyProvider,
CesiumPlusProvider _cesiumPlusProvider) {
const double _avatarSize = 140;
return Column(children: <Widget>[
Container(
height: 10,
color: yellowC,
),
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
yellowC,
const Color(0xFFE7811A),
],
)),
child: Padding(
padding: const EdgeInsets.only(left: 30, right: 40),
child: Row(children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(children: [
GestureDetector(
key: const Key('copyPubkey'),
onTap: () {
Clipboard.setData(ClipboardData(text: pubkey));
_historyProvider.snackCopyKey(context);
},
child: Text(
_historyProvider.getShortPubkey(pubkey),
style: const TextStyle(
fontSize: 30,
fontWeight: FontWeight.w800,
),
),
),
]),
const SizedBox(height: 10),
if (username == null)
Query(
options: QueryOptions(
document: gql(getId),
variables: {
'pubkey': pubkey,
},
),
builder: (QueryResult result,
{VoidCallback refetch, FetchMore fetchMore}) {
if (result.isLoading || result.hasException) {
return const Text('...');
} else if (result.data['idty'] == null ||
result.data['idty']['username'] == null) {
return const Text('');
} else {
return SizedBox(
width: 230,
child: Text(
result?.data['idty']['username'] ?? '',
style: const TextStyle(
fontSize: 27,
color: Color(0xff814C00),
),
),
);
}
},
),
if (username != null)
SizedBox(
width: 230,
child: Text(
username,
style: const TextStyle(
fontSize: 27,
color: Color(0xff814C00),
),
),
),
const SizedBox(height: 25),
]),
FutureBuilder(
future: _historyProvider.getBalance(pubkey),
builder:
(BuildContext context, AsyncSnapshot<num> _balance) {
if (_balance.connectionState != ConnectionState.done ||
_balance.hasError) {
return const Text('...');
}
return Text(
"${_balance.data.toString()} Ğ1",
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 22, fontWeight: FontWeight.w500),
);
}),
const SizedBox(height: 30),
]),
const Spacer(),
Column(children: <Widget>[
if (avatar == null)
FutureBuilder(
future: _cesiumPlusProvider.getAvatar(pubkey, _avatarSize),
builder:
(BuildContext context, AsyncSnapshot<Image> _avatar) {
if (_avatar.connectionState != ConnectionState.done) {
return Stack(children: [
ClipOval(
child:
_cesiumPlusProvider.defaultAvatar(_avatarSize),
),
Positioned(
top: 15,
right: 45,
width: 51,
height: 51,
child: CircularProgressIndicator(
strokeWidth: 5,
color: orangeC,
),
),
]);
}
if (_avatar.hasData) {
return GestureDetector(
key: const Key('openAvatar'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return AvatarFullscreen(_avatar.data);
}),
);
},
child: ClipOval(
child: Image(
image: _avatar.data.image,
height: _avatarSize,
fit: BoxFit.cover,
),
),
);
}
return ClipOval(
child: _cesiumPlusProvider.defaultAvatar(_avatarSize),
);
}),
if (avatar != null)
GestureDetector(
key: const Key('openAvatar'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return AvatarFullscreen(avatar);
}),
);
},
child: ClipOval(
child: Image(
image: avatar.image,
height: _avatarSize,
fit: BoxFit.cover,
),
),
),
const SizedBox(height: 25),
]),
]),
),
),
]);
}
} }

View File

@ -1,13 +1,16 @@
import 'package:bubble/bubble.dart';
import 'package:dubp/dubp.dart'; import 'package:dubp/dubp.dart';
import 'package:gecko/globals.dart'; import 'package:gecko/globals.dart';
import 'package:gecko/models/chest_provider.dart'; import 'package:gecko/models/chest_provider.dart';
import 'package:gecko/models/history.dart'; import 'package:gecko/models/wallets_profiles.dart';
import 'package:gecko/models/home.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:gecko/models/home.dart';
import 'package:gecko/models/my_wallets.dart'; import 'package:gecko/models/my_wallets.dart';
import 'package:gecko/models/wallet_data.dart'; import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/screens/myWallets/restore_chest.dart';
import 'package:gecko/screens/myWallets/unlocking_wallet.dart'; import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
import 'package:gecko/screens/onBoarding/0_no_keychain_found.dart'; import 'package:gecko/screens/onBoarding/1.dart';
import 'package:gecko/screens/search.dart';
import 'dart:ui'; import 'dart:ui';
import 'package:gecko/screens/settings.dart'; import 'package:gecko/screens/settings.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
@ -19,21 +22,14 @@ class HomeScreen extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
HomeProvider _homeProvider = Provider.of<HomeProvider>(context); // HomeProvider _homeProvider = Provider.of<HomeProvider>(context);
HistoryProvider _historyProvider = Provider.of<HistoryProvider>(context);
HistoryProvider _historyStatic = HistoryProvider('');
MyWalletsProvider _myWalletProvider = MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context); Provider.of<MyWalletsProvider>(context);
Provider.of<ChestProvider>(context); Provider.of<ChestProvider>(context);
HomeProvider homeClass = HomeProvider();
final bool isWalletsExists = _myWalletProvider.checkIfWalletExist(); final bool isWalletsExists = _myWalletProvider.checkIfWalletExist();
// walletBox.toMap().forEach((key, value) {
// if (value.chest == 0) {
// print('$key: ${value.derivation}');
// }
// });
isTall = false; isTall = false;
ratio = 1; ratio = 1;
if (MediaQuery.of(context).size.height >= 930) { if (MediaQuery.of(context).size.height >= 930) {
@ -86,95 +82,225 @@ class HomeScreen extends StatelessWidget {
], ],
), ),
), ),
appBar: AppBar(
toolbarHeight: 60 * ratio,
leading: Builder(
builder: (context) => IconButton(
key: const Key('drawerMenu'),
icon: Icon(Icons.menu, color: Colors.grey[850]),
onPressed: () => Scaffold.of(context).openDrawer(),
)),
title: _homeProvider.appBarTitle,
actions: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: IconButton(
key: const Key('searchIcon'),
icon: _homeProvider.searchIcon,
color: Colors.grey[850],
onPressed: () {
if (_homeProvider.searchIcon.icon == Icons.search) {
_homeProvider.searchIcon = Icon(
Icons.close,
color: Colors.grey[850],
);
_homeProvider.appBarTitle = TextField(
key: const Key('searchInput'),
autofocus: true,
controller: _homeProvider.searchQuery,
onChanged: (text) {
log.d("Clé tappé: $text");
final String searchResult =
_historyProvider.isPubkey(context, text);
if (searchResult != '') {
_homeProvider.currentIndex = 0;
}
},
style: TextStyle(
color: Colors.grey[850],
),
decoration: InputDecoration(
prefixIcon:
Icon(Icons.search, color: Colors.grey[850]),
hintText: "Rechercher ...",
hintStyle: TextStyle(color: Colors.grey[850])),
);
_homeProvider.handleSearchStart();
} else {
_homeProvider.handleSearchEnd();
}
}))
],
backgroundColor: const Color(0xffFFD58D),
),
backgroundColor: const Color(0xffF9F9F1), backgroundColor: const Color(0xffF9F9F1),
body: Builder( body: Builder(
builder: (ctx) => StatefulWrapper( builder: (ctx) => StatefulWrapper(
onInit: () { onInit: () {
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
DubpRust.setup(); DubpRust.setup();
_historyStatic.snackNode(ctx); if (isWalletsExists) homeClass.snackNode(ctx);
}); });
}, },
child: isWalletsExists ? geckHome(context) : welcomeHome(context)
// bottomNavigationBar: BottomNavigationBar(
// backgroundColor: backgroundColor,
// fixedColor: Colors.grey[850],
// unselectedItemColor: const Color(0xffBD935C),
// type: BottomNavigationBarType.fixed,
// onTap: (index) {
// _homeProvider.currentIndex = index;
// },
// currentIndex: _homeProvider.currentIndex,
// items: [
// BottomNavigationBarItem(
// icon: Image.asset('assets/block-space-disabled.png', height: 26),
// activeIcon: Image.asset('assets/blockchain.png', height: 26),
// label: 'Explorateur',
// ),
// const BottomNavigationBarItem(
// icon: Icon(Icons.lock),
// label: 'Mes portefeuilles',
// ),
// ],
// ),
),
),
);
}
}
Widget geckHome(context) {
MyWalletsProvider _myWalletProvider = Provider.of<MyWalletsProvider>(context);
Provider.of<ChestProvider>(context);
WalletsProfilesProvider _historyProvider =
Provider.of<WalletsProfilesProvider>(context);
final double statusBarHeight = MediaQuery.of(context).padding.top;
return Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/home/background.jpg"),
fit: BoxFit.cover,
),
),
child:
Column(crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[
Stack(children: <Widget>[
Positioned(
top: statusBarHeight + 10,
left: 15,
child: Builder(
builder: (context) => IconButton(
key: const Key('drawerMenu'),
icon: const Icon(
Icons.menu,
color: Colors.white,
size: 35,
),
onPressed: () => Scaffold.of(context).openDrawer(),
),
),
),
const Align(
child:
Image(image: AssetImage('assets/home/header.png'), height: 210),
),
]),
Padding(
padding: EdgeInsets.only(top: 15 * ratio),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[
Text(
"y'a pas de lézard ;-)",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.w700,
shadows: <Shadow>[
Shadow(
offset: Offset(0, 0),
blurRadius: 20,
color: Colors.black,
),
Shadow(
offset: Offset(0, 0),
blurRadius: 20,
color: Colors.black,
),
],
),
)
]),
),
Expanded(
flex: 1,
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Colors.transparent,
Colors.black.withOpacity(0.9),
],
),
),
child: Column(children: <Widget>[ child: Column(children: <Widget>[
const Spacer(),
Row(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
Column(children: <Widget>[
Container(
child: ClipOval(
child: Material(
color: orangeC, // button color
child: InkWell(
child: const Padding(
padding: EdgeInsets.all(18),
child: Image(
image: AssetImage('assets/home/loupe.png'),
height: 70),
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return const SearchScreen();
}),
);
}),
),
),
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Colors.black,
boxShadow: [
BoxShadow(
blurRadius: 2,
offset: Offset(1, 1.5),
spreadRadius: 0.5)
],
),
),
const SizedBox(height: 12),
const Text(
"Rechercher un\nportefeuille",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 17,
fontWeight: FontWeight.w500),
)
]),
const SizedBox(width: 120),
Column(children: <Widget>[
Container(
child: ClipOval(
key: const Key('manageWallets'),
child: Material(
color: orangeC, // button color
child: InkWell(
child: const Padding(
padding: EdgeInsets.all(18),
child: Image(
image: AssetImage('assets/home/wallet.png'),
height: 75)),
onTap: () {
WalletData defaultWallet =
_myWalletProvider.getDefaultWallet(
configBox.get('currentChest'));
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return UnlockingWallet(
wallet: defaultWallet,
action: "mywallets",
);
},
),
);
// Navigator.pushNamed(
// context, '/mywallets')));
}),
),
),
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Colors.black,
boxShadow: [
BoxShadow(
blurRadius: 2,
offset: Offset(1, 1.5),
spreadRadius: 0.5)
],
),
),
const SizedBox(height: 12),
const Text(
"Gérer mes\nportefeuilles",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 17,
fontWeight: FontWeight.w500),
)
])
]),
Padding( Padding(
padding: const EdgeInsets.only(top: 20), padding: const EdgeInsets.only(top: 40),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[
SizedBox(width: 7),
Image(
image: AssetImage('assets/icon/gecko_final.png'),
height: 180),
]),
),
Padding(
padding: const EdgeInsets.only(top: 15),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[
Text(
"y'a pas de lézard !",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black,
fontSize: 17,
fontStyle: FontStyle.italic),
)
]),
),
Padding(
padding: EdgeInsets.only(top: isTall ? 100 : 60),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[ children: <Widget>[
@ -182,15 +308,14 @@ class HomeScreen extends StatelessWidget {
Container( Container(
child: ClipOval( child: ClipOval(
child: Material( child: Material(
color: const Color(0xffFFD58D), // button color color: orangeC, // button color
child: InkWell( child: InkWell(
splashColor: orangeC, // inkwell color
child: const Padding( child: const Padding(
padding: EdgeInsets.all(22), padding: EdgeInsets.all(18),
child: Image( child: Image(
image: AssetImage( image: AssetImage(
'assets/qrcode-scan.png'), 'assets/home/qrcode.png'),
height: 60)), height: 75)),
onTap: () async { onTap: () async {
await _historyProvider.scan(context); await _historyProvider.scan(context);
}), }),
@ -198,157 +323,194 @@ class HomeScreen extends StatelessWidget {
), ),
decoration: const BoxDecoration( decoration: const BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
color: Colors.white, color: Colors.black,
boxShadow: [ boxShadow: [
BoxShadow( BoxShadow(
color: Colors.grey, blurRadius: 2,
blurRadius: 4.0, offset: Offset(1, 1.5),
offset: Offset(2.0, 2.5),
spreadRadius: 0.5) spreadRadius: 0.5)
], ],
), ),
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
const Text( const Text(
"Payer par QR-Code", "Scanner un\nQR code",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle(color: Colors.black, fontSize: 16), style: TextStyle(
color: Colors.white,
fontSize: 17,
fontWeight: FontWeight.w500),
) )
]) ])
]), ]),
), ),
Padding( SizedBox(height: isTall ? 80 : 40)
padding: const EdgeInsets.only(top: 50),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Column(children: <Widget>[
Container(
child: ClipOval(
child: Material(
color: const Color(0xffFFD58D), // button color
child: InkWell(
splashColor: orangeC, // inkwell color
child: const Padding(
padding: EdgeInsets.symmetric(
horizontal: 20, vertical: 16),
child: Image(
image:
AssetImage('assets/blockchain.png'),
height: 70)),
onTap: () {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) {
// return TemplateScreen();
// }),
// );
}),
),
),
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey,
blurRadius: 4.0,
offset: Offset(2.0, 2.5),
spreadRadius: 0.5)
],
),
),
const SizedBox(height: 12),
const Text(
"Explorer\n",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.black, fontSize: 16),
)
]),
const SizedBox(width: 140),
Column(children: <Widget>[
Container(
child: ClipOval(
key: const Key('manageWallets'),
child: Material(
color: const Color(0xffFFD58D), // button color
child: InkWell(
splashColor: orangeC, // inkwell color
child: const Padding(
padding: EdgeInsets.all(23),
child: Image(
image: AssetImage('assets/lock.png'),
height: 57)),
onTap: () {
WalletData defaultWallet =
_myWalletProvider.getDefaultWallet(
configBox.get('currentChest'));
isWalletsExists
? Navigator.push(context,
MaterialPageRoute(builder: (context) {
return UnlockingWallet(
wallet: defaultWallet,
action: "mywallets",
);
}))
// Navigator.pushNamed(
// context, '/mywallets')
: Navigator.push(context,
MaterialPageRoute(builder: (context) {
return const NoKeyChainScreen();
}));
}),
),
),
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey,
blurRadius: 4.0,
offset: Offset(2.0, 2.5),
spreadRadius: 0.5)
],
),
),
const SizedBox(height: 12),
const Text(
"Gérer mes\nportefeuilles",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.black, fontSize: 16),
)
])
]),
)
]), ]),
// bottomNavigationBar: BottomNavigationBar(
// backgroundColor: Color(0xffFFD58D),
// fixedColor: Colors.grey[850],
// unselectedItemColor: Color(0xffBD935C),
// type: BottomNavigationBarType.fixed,
// onTap: (index) {
// _homeProvider.currentIndex = index;
// },
// currentIndex: _homeProvider.currentIndex,
// items: [
// BottomNavigationBarItem(
// icon: Image.asset('assets/block-space-disabled.png', height: 26),
// activeIcon: Image.asset('assets/blockchain.png', height: 26),
// label: 'Explorateur',
// ),
// BottomNavigationBarItem(
// icon: Icon(Icons.lock),
// label: 'Mes portefeuilles',
// ),
// ],
// ),
), ),
)
]),
);
}
Widget welcomeHome(context) {
final double statusBarHeight = MediaQuery.of(context).padding.top;
return Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/home/background.jpg"),
fit: BoxFit.cover,
), ),
); ),
} child:
Column(crossAxisAlignment: CrossAxisAlignment.start, children: <Widget>[
Stack(children: <Widget>[
Positioned(
top: statusBarHeight + 10,
left: 15,
child: Builder(
builder: (context) => IconButton(
key: const Key('drawerMenu'),
icon: const Icon(
Icons.menu,
color: Colors.white,
size: 35,
),
onPressed: () => Scaffold.of(context).openDrawer(),
),
),
),
const Align(
child:
Image(image: AssetImage('assets/home/header.png'), height: 210),
),
]),
Padding(
padding: EdgeInsets.only(top: 1 * ratio),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[
Text(
"Lapplication de paiement Ğ1\nplus rapide quun reptile du Vietnam",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.w700,
shadows: <Shadow>[
Shadow(
offset: Offset(0, 0),
blurRadius: 20,
color: Colors.black,
),
Shadow(
offset: Offset(0, 0),
blurRadius: 20,
color: Colors.black,
),
],
),
)
]),
),
Expanded(
flex: 1,
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Colors.transparent,
Colors.black.withOpacity(0.9),
],
),
),
child: Center(
child: Column(children: <Widget>[
const Spacer(),
Row(children: <Widget>[
Expanded(
child: Stack(children: <Widget>[
const Padding(
padding: EdgeInsets.only(top: 55),
child: Image(
image: AssetImage('assets/home/gecko-bienvenue.png'),
height: 220,
),
),
Positioned(
left: 180,
child: bubbleSpeak("y'a pas de lézard !"),
),
const Positioned(
left: 200,
top: 60,
child: Image(
image: AssetImage('assets/home/bout_de_bulle.png'),
),
),
]),
),
]),
SizedBox(
width: 410,
height: 70,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 4,
primary: orangeC, // background
onPrimary: Colors.white, // foreground
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return OnboardingStepOne();
},
),
);
},
child: const Text(
'Créer un portefeuille',
style:
TextStyle(fontSize: 24, fontWeight: FontWeight.w600),
),
),
),
SizedBox(height: 25 * ratio),
SizedBox(
width: 410,
height: 70,
child: OutlinedButton(
style: OutlinedButton.styleFrom(
side: BorderSide(width: 4, color: orangeC)),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return const RestoreChest();
},
),
);
},
child: Text(
"Restaurer mes portefeuilles",
style: TextStyle(
fontSize: 24,
color: orangeC,
fontWeight: FontWeight.w600),
),
),
),
SizedBox(height: isTall ? 100 : 50)
]),
),
))
]),
);
} }
class StatefulWrapper extends StatefulWidget { class StatefulWrapper extends StatefulWidget {
@ -374,3 +536,19 @@ class _StatefulWrapperState extends State<StatefulWrapper> {
return widget.child; return widget.child;
} }
} }
Widget bubbleSpeak(String text, {double long, Key textKey}) {
return Bubble(
padding: long == null
? const BubbleEdges.all(20)
: BubbleEdges.symmetric(horizontal: long, vertical: 30),
elevation: 5,
color: Colors.white,
child: Text(
text,
key: textKey,
style: const TextStyle(
color: Colors.black, fontSize: 21, fontWeight: FontWeight.w400),
),
);
}

View File

@ -5,10 +5,11 @@ import 'package:flutter/material.dart';
import 'package:gecko/globals.dart'; import 'package:gecko/globals.dart';
import 'package:gecko/models/chest_data.dart'; import 'package:gecko/models/chest_data.dart';
import 'package:gecko/models/chest_provider.dart'; import 'package:gecko/models/chest_provider.dart';
import 'package:gecko/models/history.dart'; import 'package:gecko/models/wallets_profiles.dart';
import 'package:gecko/models/my_wallets.dart'; import 'package:gecko/models/my_wallets.dart';
import 'package:gecko/models/queries.dart'; import 'package:gecko/models/queries.dart';
import 'package:gecko/models/wallet_options.dart'; import 'package:gecko/models/wallet_options.dart';
import 'package:gecko/screens/history.dart';
import 'package:gecko/screens/myWallets/change_pin.dart'; import 'package:gecko/screens/myWallets/change_pin.dart';
import 'package:graphql_flutter/graphql_flutter.dart'; import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -17,336 +18,404 @@ import 'package:flutter/services.dart';
int _nbrLinesName = 1; int _nbrLinesName = 1;
bool _isNewNameValid = false; bool _isNewNameValid = false;
Widget cesiumWalletOptions(BuildContext context, ChestData cesiumWallet, class CesiumWalletOptions extends StatelessWidget {
MyWalletsProvider _myWalletProvider) { const CesiumWalletOptions(
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); {Key key, Key keyMyWallets, @required this.cesiumWallet})
WalletOptionsProvider _walletOptions = : super(key: key);
Provider.of<WalletOptionsProvider>(context);
ChestProvider _chestProvider =
Provider.of<ChestProvider>(context, listen: false);
HistoryProvider _historyProvider = Provider.of<HistoryProvider>(context);
final String shortPubkey = final ChestData cesiumWallet;
_walletOptions.getShortPubkey(_walletOptions.pubkey.text);
if (_walletOptions.nameController.text == null || _isNewNameValid == false) { @override
_walletOptions.nameController.text = cesiumWallet.name; Widget build(BuildContext context) {
} else { SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
cesiumWallet.name = _walletOptions.nameController.text; WalletOptionsProvider _walletOptions =
} Provider.of<WalletOptionsProvider>(context, listen: false);
ChestProvider _chestProvider =
Provider.of<ChestProvider>(context, listen: false);
WalletsProfilesProvider _historyProvider =
Provider.of<WalletsProfilesProvider>(context, listen: false);
MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context, listen: false);
_walletOptions.nameController.text.length >= 15 final String shortPubkey =
? _nbrLinesName = 2 _walletOptions.getShortPubkey(_walletOptions.pubkey.text);
: _nbrLinesName = 1;
if (_walletOptions.nameController.text.length >= 26 && isTall) {
_nbrLinesName = 3;
}
return Scaffold( if (_walletOptions.nameController.text == null ||
resizeToAvoidBottomInset: false, _isNewNameValid == false) {
body: Builder( _walletOptions.nameController.text = cesiumWallet.name;
builder: (ctx) => SafeArea( } else {
child: Column(children: <Widget>[ cesiumWallet.name = _walletOptions.nameController.text;
Container( }
height: isTall ? 30 : 15,
color: yellowC,
),
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
yellowC,
const Color(0xfffafafa),
],
)),
child: Row(children: <Widget>[
const SizedBox(width: 25),
InkWell(
onTap: () async {
File newAvatar = await _walletOptions.changeAvatar();
if (newAvatar != null) {
cesiumWallet.imageFile = newAvatar;
}
_walletOptions.reloadBuild();
},
child: cesiumWallet.imageFile == null
? Image.asset(
'assets/chests/${cesiumWallet.imageName}',
width: 110,
)
: Image.file(cesiumWallet.imageFile, width: 110),
),
InkWell(
onTap: () async {
File newAvatar = await _walletOptions.changeAvatar();
if (newAvatar != null) {
cesiumWallet.imageFile = newAvatar;
}
_walletOptions.reloadBuild();
},
child: Column(children: <Widget>[
Image.asset(
'assets/walletOptions/camera.png',
),
const SizedBox(height: 100)
])),
Column(children: <Widget>[
Row(children: <Widget>[
Column(children: <Widget>[
SizedBox(
width: 260,
child: TextField(
key: const Key('walletName'),
autofocus: false,
focusNode: _walletOptions.walletNameFocus,
enabled: _walletOptions.isEditing,
controller: _walletOptions.nameController,
maxLines: _nbrLinesName,
textAlign: TextAlign.center,
decoration: const InputDecoration(
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
disabledBorder: InputBorder.none,
contentPadding: EdgeInsets.all(15.0),
),
style: TextStyle(
fontSize: isTall ? 27 : 23,
color: Colors.black,
fontWeight: FontWeight.w400,
fontFamily: 'Monospace')),
),
SizedBox(height: isTall ? 5 : 0),
Query(
options: QueryOptions(
document: gql(getBalance),
variables: {
'pubkey': _walletOptions.pubkey.text,
},
// pollInterval: Duration(seconds: 1),
),
builder: (QueryResult result,
{VoidCallback refetch, FetchMore fetchMore}) {
if (result.hasException) {
return Text(result.exception.toString());
}
if (result.isLoading) { _walletOptions.nameController.text.length >= 15
return const Text('Loading'); ? _nbrLinesName = 2
} : _nbrLinesName = 1;
if (_walletOptions.nameController.text.length >= 26 && isTall) {
_nbrLinesName = 3;
}
// List repositories = result.data['viewer']['repositories']['nodes']; return WillPopScope(
String wBalanceUD; onWillPop: () {
if (result.data['balance'] == null) { _walletOptions.isEditing = false;
wBalanceUD = '0.0'; _walletOptions.isBalanceBlur = true;
} else { Navigator.popUntil(
int wBalanceG1 = result.data['balance']['amount']; context,
int currentUD = result.data['currentUd']['amount']; ModalRoute.withName('/'),
double wBalanceUDBrut = );
wBalanceG1 / currentUD; // .toString(); return Future<bool>.value(true);
wBalanceUD = double.parse( },
(wBalanceUDBrut).toStringAsFixed(2)) child: Scaffold(
.toString(); resizeToAvoidBottomInset: false,
} appBar: AppBar(
return Row(children: <Widget>[ toolbarHeight: 60 * ratio,
ImageFiltered( elevation: 0,
imageFilter: ImageFilter.blur( leading: IconButton(
sigmaX: _walletOptions.isBalanceBlur ? 6 : 0, icon: const Icon(Icons.arrow_back, color: Colors.black),
sigmaY: _walletOptions.isBalanceBlur ? 5 : 0), onPressed: () {
child: Text(wBalanceUD, _walletOptions.isEditing = false;
style: TextStyle( _walletOptions.isBalanceBlur = true;
fontSize: isTall ? 20 : 18, Navigator.popUntil(
color: Colors.black)), context,
), ModalRoute.withName('/'),
Text(' DU', );
style: TextStyle(
fontSize: isTall ? 20 : 18,
color: Colors.black))
]);
// Text(
// '$wBalanceUD DU',
// style: TextStyle(
// fontSize: 20, color: Colors.black),
// );
},
),
const SizedBox(height: 5),
InkWell(
key: const Key('displayBalance'),
onTap: () {
_walletOptions.bluringBalance();
},
child: Image.asset(
_walletOptions.isBalanceBlur
? 'assets/walletOptions/icon_oeuil.png'
: 'assets/walletOptions/icon_oeuil_close.png',
)),
]),
const SizedBox(width: 0),
Column(children: <Widget>[
InkWell(
key: const Key('renameWallet'),
onTap: () async {
_isNewNameValid = _walletOptions.editWalletName(
[cesiumWallet.key, 0],
isCesium: cesiumWallet.isCesium);
await Future.delayed(
const Duration(milliseconds: 30));
_walletOptions.walletNameFocus.requestFocus();
},
child: ClipRRect(
child: Image.asset(
_walletOptions.isEditing
? 'assets/walletOptions/android-checkmark.png'
: 'assets/walletOptions/edit.png',
width: 20,
height: 20),
)),
const SizedBox(
height: 60,
)
])
]),
]),
])),
SizedBox(height: 4 * ratio),
FutureBuilder(
future: _walletOptions.generateQRcode(_walletOptions.pubkey.text),
builder: (context, snapshot) {
return snapshot.data != null
? Image.memory(snapshot.data, height: isTall ? 300 : 270)
: const Text('-', style: TextStyle(fontSize: 20));
}), }),
SizedBox(height: 15 * ratio), title: SizedBox(
GestureDetector( height: 22,
key: const Key('copyPubkey'), child: Consumer<WalletOptionsProvider>(
onTap: () { builder: (context, walletProvider, _) {
Clipboard.setData( return Text(_walletOptions.nameController.text);
ClipboardData(text: _walletOptions.pubkey.text)); }),
_walletOptions.snackCopyKey(ctx); ),
}, ),
child: SizedBox( body: Builder(
height: 50, builder: (ctx) => SafeArea(
child: Column(children: <Widget>[
Consumer<WalletOptionsProvider>(
builder: (context, walletProvider, _) {
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
yellowC,
const Color(0xfffafafa),
],
)),
child: Row(children: <Widget>[ child: Row(children: <Widget>[
const SizedBox(width: 30), const SizedBox(width: 25),
Image.asset( InkWell(
'assets/walletOptions/key.png', onTap: () async {
File newAvatar = await _walletOptions.changeAvatar();
if (newAvatar != null) {
cesiumWallet.imageFile = newAvatar;
}
_walletOptions.reloadBuild();
},
child: cesiumWallet.imageFile == null
? Image.asset(
'assets/chests/${cesiumWallet.imageName}',
width: 110,
)
: Image.file(cesiumWallet.imageFile, width: 110),
), ),
const SizedBox(width: 20), InkWell(
Text("${shortPubkey.split(':')[0]}:", onTap: () async {
style: const TextStyle( File newAvatar = await _walletOptions.changeAvatar();
fontSize: 22, if (newAvatar != null) {
fontWeight: FontWeight.w800, cesiumWallet.imageFile = newAvatar;
fontFamily: 'Monospace', }
color: Colors.black)), _walletOptions.reloadBuild();
Text(shortPubkey.split(':')[1], },
style: const TextStyle( child: Column(children: <Widget>[
fontSize: 22, Image.asset(
fontWeight: FontWeight.w800, 'assets/walletOptions/camera.png',
fontFamily: 'Monospace')), height: 40,
const SizedBox(width: 15), ),
SizedBox( const SizedBox(height: 80)
height: 40, ])),
child: ElevatedButton( Column(children: <Widget>[
style: ElevatedButton.styleFrom( Row(children: <Widget>[
shape: RoundedRectangleBorder( Column(children: <Widget>[
borderRadius: BorderRadius.circular(8), SizedBox(
), width: 260,
elevation: 1, child: TextField(
primary: orangeC, // background key: const Key('walletName'),
onPrimary: Colors.black, // foreground autofocus: false,
focusNode: _walletOptions.walletNameFocus,
enabled: _walletOptions.isEditing,
controller: _walletOptions.nameController,
maxLines: _nbrLinesName,
textAlign: TextAlign.center,
decoration: const InputDecoration(
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
disabledBorder: InputBorder.none,
contentPadding: EdgeInsets.all(15.0),
),
style: TextStyle(
fontSize: isTall ? 27 : 23,
color: Colors.black,
fontWeight: FontWeight.w400,
fontFamily: 'Monospace')),
),
SizedBox(height: isTall ? 5 : 0),
Query(
options: QueryOptions(
document: gql(getBalance),
variables: {
'pubkey': _walletOptions.pubkey.text,
},
// pollInterval: Duration(seconds: 1),
), ),
onPressed: () { builder: (QueryResult result,
Clipboard.setData(ClipboardData( {VoidCallback refetch, FetchMore fetchMore}) {
text: _walletOptions.pubkey.text)); if (result.hasException) {
_walletOptions.snackCopyKey(ctx); return Text(result.exception.toString());
}
if (result.isLoading) {
return const Text('Loading');
}
// List repositories = result.data['viewer']['repositories']['nodes'];
String wBalanceUD;
if (result.data['balance'] == null) {
wBalanceUD = '0.0';
} else {
int wBalanceG1 =
result.data['balance']['amount'];
int currentUD =
result.data['currentUd']['amount'];
double wBalanceUDBrut =
wBalanceG1 / currentUD; // .toString();
wBalanceUD = double.parse(
(wBalanceUDBrut).toStringAsFixed(2))
.toString();
}
return Row(children: <Widget>[
ImageFiltered(
imageFilter: ImageFilter.blur(
sigmaX:
_walletOptions.isBalanceBlur ? 6 : 0,
sigmaY:
_walletOptions.isBalanceBlur ? 5 : 0),
child: Text(wBalanceUD,
style: TextStyle(
fontSize: isTall ? 20 : 18,
color: Colors.black)),
),
Text(' DU',
style: TextStyle(
fontSize: isTall ? 20 : 18,
color: Colors.black))
]);
// Text(
// '$wBalanceUD DU',
// style: TextStyle(
// fontSize: 20, color: Colors.black),
// );
}, },
child: Row(children: <Widget>[ ),
Image.asset( const SizedBox(height: 5),
'assets/walletOptions/copy-white.png', InkWell(
), key: const Key('displayBalance'),
const SizedBox(width: 7), onTap: () {
Text('Copier', _walletOptions.bluringBalance();
style: TextStyle( },
fontSize: 15, color: Colors.grey[50])) child: Image.asset(
]))), _walletOptions.isBalanceBlur
]))), ? 'assets/walletOptions/icon_oeuil.png'
SizedBox(height: 10 * ratio), : 'assets/walletOptions/icon_oeuil_close.png',
InkWell( height: 35,
key: const Key('displayHistory'), ),
onTap: () { ),
_historyProvider.isPubkey(ctx, _walletOptions.pubkey.text, ]),
goHistory: true); const SizedBox(width: 0),
}, Column(children: <Widget>[
child: SizedBox( InkWell(
height: 50, key: const Key('renameWallet'),
child: Row(children: <Widget>[ onTap: () async {
const SizedBox(width: 30), _isNewNameValid = _walletOptions.editWalletName(
Image.asset( [cesiumWallet.key, 0],
'assets/walletOptions/clock.png', isCesium: cesiumWallet.isCesium);
), await Future.delayed(
const SizedBox(width: 22), const Duration(milliseconds: 30));
const Text('Historique des transactions', _walletOptions.walletNameFocus.requestFocus();
style: TextStyle(fontSize: 20, color: Colors.black)), },
]))), child: ClipRRect(
SizedBox(height: 7 * ratio), child: Image.asset(
InkWell( _walletOptions.isEditing
key: const Key('changePin'), ? 'assets/walletOptions/android-checkmark.png'
onTap: () async { : 'assets/walletOptions/edit.png',
// await _chestProvider.changePin(context, cesiumWallet); width: 20,
_myWalletProvider.pinCode = await Navigator.push( height: 20),
context, )),
MaterialPageRoute( const SizedBox(
builder: (context) { height: 60,
return ChangePinScreen( )
walletName: cesiumWallet.name, ])
walletProvider: _myWalletProvider, ]),
]),
]),
);
}),
SizedBox(height: 4 * ratio),
FutureBuilder(
future:
_walletOptions.generateQRcode(_walletOptions.pubkey.text),
builder: (context, snapshot) {
return snapshot.data != null
? Image.memory(snapshot.data,
height: isTall ? 300 : 270)
: const Text('-', style: TextStyle(fontSize: 20));
}),
SizedBox(height: 15 * ratio),
GestureDetector(
key: const Key('copyPubkey'),
onTap: () {
Clipboard.setData(
ClipboardData(text: _walletOptions.pubkey.text));
_walletOptions.snackCopyKey(ctx);
},
child: SizedBox(
height: 50,
child: Row(children: <Widget>[
const SizedBox(width: 30),
Image.asset(
'assets/walletOptions/key.png',
height: 45,
),
const SizedBox(width: 20),
Text("${shortPubkey.split(':')[0]}:",
style: const TextStyle(
fontSize: 22,
fontWeight: FontWeight.w800,
fontFamily: 'Monospace',
color: Colors.black)),
Text(shortPubkey.split(':')[1],
style: const TextStyle(
fontSize: 22,
fontWeight: FontWeight.w800,
fontFamily: 'Monospace')),
const SizedBox(width: 15),
SizedBox(
height: 40,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
elevation: 1,
primary: orangeC, // background
onPrimary: Colors.black, // foreground
),
onPressed: () {
Clipboard.setData(ClipboardData(
text: _walletOptions.pubkey.text));
_walletOptions.snackCopyKey(ctx);
},
child: Row(children: <Widget>[
Image.asset(
'assets/walletOptions/copy-white.png',
height: 25,
),
const SizedBox(width: 7),
Text('Copier',
style: TextStyle(
fontSize: 15, color: Colors.grey[50]))
]))),
]))),
SizedBox(height: 10 * ratio),
InkWell(
key: const Key('displayHistory'),
onTap: () {
_historyProvider.nPage = 1;
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return HistoryScreen(
pubkey: _walletOptions.pubkey.text);
}),
); );
}, },
child: SizedBox(
height: 50,
child: Row(children: <Widget>[
const SizedBox(width: 30),
Image.asset(
'assets/walletOptions/clock.png',
height: 45,
),
const SizedBox(width: 22),
const Text('Historique des transactions',
style:
TextStyle(fontSize: 20, color: Colors.black)),
]))),
SizedBox(height: 7 * ratio),
InkWell(
key: const Key('changePin'),
onTap: () async {
// await _chestProvider.changePin(context, cesiumWallet);
String newPin = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return ChangePinScreen(
walletName: cesiumWallet.name,
walletProvider: _myWalletProvider,
);
},
),
);
if (newPin != null) _myWalletProvider.pinCode = newPin;
},
child: SizedBox(
height: 50,
child: Row(children: <Widget>[
const SizedBox(width: 31),
Image.asset(
'assets/chests/secret_code.png',
height: 24,
),
const SizedBox(width: 20),
const Text('Changer mon code secret',
style: TextStyle(fontSize: 20, color: Colors.black)),
]),
), ),
); ),
}, SizedBox(height: 7 * ratio),
child: SizedBox( InkWell(
height: 50, key: const Key('deleteWallet'),
child: Row(children: <Widget>[ onTap: () async {
const SizedBox(width: 28), await _chestProvider.deleteChest(context, cesiumWallet);
Image.asset( },
'assets/chests/secret_code.png', child: SizedBox(
), height: 50,
const SizedBox(width: 18), child: Row(children: <Widget>[
const Text('Changer mon code secret', const SizedBox(width: 33),
style: TextStyle(fontSize: 20, color: Colors.black)), Image.asset(
])), 'assets/walletOptions/trash.png',
height: 45,
),
const SizedBox(width: 21),
const Text(
'Supprimer ce coffre',
style: TextStyle(
fontSize: 20,
color: Color(0xffD80000),
),
),
]),
),
),
]),
), ),
SizedBox(height: 7 * ratio), ),
InkWell(
key: const Key('deleteWallet'),
onTap: () async {
await _chestProvider.deleteChest(context, cesiumWallet);
},
child: SizedBox(
height: 50,
child: Row(children: <Widget>[
const SizedBox(width: 33),
Image.asset(
'assets/walletOptions/trash.png',
),
const SizedBox(width: 25),
const Text(
'Supprimer ce coffre',
style: TextStyle(
fontSize: 20,
color: Color(0xffD80000),
),
),
]),
),
),
]),
), ),
), );
); }
} }

View File

@ -34,20 +34,28 @@ class ChangePinScreen extends StatelessWidget with ChangeNotifier {
child: Scaffold( child: Scaffold(
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
appBar: AppBar( appBar: AppBar(
toolbarHeight: 60 * ratio, toolbarHeight: 60 * ratio,
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black), icon: const Icon(Icons.arrow_back, color: Colors.black),
onPressed: () { onPressed: () {
_changePin.newPin.text = ''; _changePin.newPin.text = '';
Navigator.of(context).pop(); Navigator.of(context).pop();
}), }),
title: SizedBox( title: SizedBox(
height: 22, height: 22,
child: Text(walletName), child: Text(walletName),
)), ),
),
body: Center( body: Center(
child: SafeArea( child: SafeArea(
child: Column(children: <Widget>[ child: Column(children: <Widget>[
StatefulWrapper(
onInit: () async {
_newWalletFile =
await _changePin.changePin(walletProvider.pinCode);
},
child: Container(),
),
const SizedBox(height: 80), const SizedBox(height: 80),
Text( Text(
'Choisissez un code secret autogénéré :', 'Choisissez un code secret autogénéré :',
@ -111,3 +119,27 @@ class ChangePinScreen extends StatelessWidget with ChangeNotifier {
); );
} }
} }
class StatefulWrapper extends StatefulWidget {
final Function onInit;
final Widget child;
const StatefulWrapper({Key key, @required this.onInit, @required this.child})
: super(key: key);
@override
_StatefulWrapperState createState() => _StatefulWrapperState();
}
class _StatefulWrapperState extends State<StatefulWrapper> {
@override
void initState() {
if (widget.onInit != null) {
widget.onInit();
}
super.initState();
}
@override
Widget build(BuildContext context) {
return widget.child;
}
}

View File

@ -46,7 +46,7 @@ class ChestOptions extends StatelessWidget {
key: const Key('changePin'), key: const Key('changePin'),
onTap: () async { onTap: () async {
// await _chestProvider.changePin(context, cesiumWallet); // await _chestProvider.changePin(context, cesiumWallet);
walletProvider.pinCode = await Navigator.push( String pinResult = await Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) { builder: (context) {
@ -57,6 +57,10 @@ class ChestOptions extends StatelessWidget {
}, },
), ),
); );
if (pinResult != null) {
walletProvider.pinCode = pinResult;
}
}, },
child: SizedBox( child: SizedBox(
height: 50, height: 50,
@ -64,6 +68,7 @@ class ChestOptions extends StatelessWidget {
const SizedBox(width: 28), const SizedBox(width: 28),
Image.asset( Image.asset(
'assets/chests/secret_code.png', 'assets/chests/secret_code.png',
height: 25,
), ),
const SizedBox(width: 18), const SizedBox(width: 18),
const Text('Changer mon code secret', const Text('Changer mon code secret',
@ -79,11 +84,12 @@ class ChestOptions extends StatelessWidget {
child: SizedBox( child: SizedBox(
height: 50, height: 50,
child: Row(children: <Widget>[ child: Row(children: <Widget>[
const SizedBox(width: 33), const SizedBox(width: 30),
Image.asset( Image.asset(
'assets/walletOptions/trash.png', 'assets/walletOptions/trash.png',
height: 45,
), ),
const SizedBox(width: 24), const SizedBox(width: 20),
const Text( const Text(
'Supprimer ce coffre', 'Supprimer ce coffre',
style: TextStyle( style: TextStyle(

View File

@ -9,7 +9,8 @@ import 'package:carousel_slider/carousel_slider.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class ChooseChest extends StatefulWidget { class ChooseChest extends StatefulWidget {
const ChooseChest({Key key}) : super(key: key); const ChooseChest({this.action, Key key}) : super(key: key);
final String action;
@override @override
State<StatefulWidget> createState() { State<StatefulWidget> createState() {
@ -29,6 +30,8 @@ class _ChooseChestState extends State<ChooseChest> {
MyWalletsProvider _myWalletProvider = MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context); Provider.of<MyWalletsProvider>(context);
log.d(widget.action);
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
toolbarHeight: 60 * ratio, toolbarHeight: 60 * ratio,
@ -113,13 +116,16 @@ class _ChooseChestState extends State<ChooseChest> {
WalletData defaultWallet = WalletData defaultWallet =
_myWalletProvider.getDefaultWallet(currentChest); _myWalletProvider.getDefaultWallet(currentChest);
_myWalletProvider.rebuildWidget(); _myWalletProvider.rebuildWidget();
Navigator.pushAndRemoveUntil(context, Navigator.pushAndRemoveUntil(
MaterialPageRoute(builder: (context) { context,
return UnlockingWallet( MaterialPageRoute(builder: (context) {
wallet: defaultWallet, return UnlockingWallet(
action: "mywallets", wallet: defaultWallet,
); action: widget.action ?? "mywallets",
}), ModalRoute.withName('/')); );
}),
ModalRoute.withName('/'),
);
}, },
child: Text( child: Text(
'Ouvrir ce coffre', 'Ouvrir ce coffre',

View File

@ -6,7 +6,7 @@ import 'package:flutter/services.dart';
import 'package:gecko/globals.dart'; import 'package:gecko/globals.dart';
import 'package:gecko/models/generate_wallets.dart'; import 'package:gecko/models/generate_wallets.dart';
import 'package:gecko/models/my_wallets.dart'; import 'package:gecko/models/my_wallets.dart';
import 'package:gecko/models/wallet_options.dart'; import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
// ignore: must_be_immutable // ignore: must_be_immutable
@ -32,8 +32,6 @@ class ConfirmStoreWallet extends StatelessWidget with ChangeNotifier {
Provider.of<GenerateWalletsProvider>(context); Provider.of<GenerateWalletsProvider>(context);
MyWalletsProvider _myWalletProvider = MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context); Provider.of<MyWalletsProvider>(context);
WalletOptionsProvider _walletOptions =
Provider.of<WalletOptionsProvider>(context);
final int _currentChest = _myWalletProvider.getCurrentChest(); final int _currentChest = _myWalletProvider.getCurrentChest();
_mnemonicController.text = generatedMnemonic; _mnemonicController.text = generatedMnemonic;
@ -136,7 +134,7 @@ class ConfirmStoreWallet extends StatelessWidget with ChangeNotifier {
onPressed: (_generateWalletProvider onPressed: (_generateWalletProvider
.isAskedWordValid && .isAskedWordValid &&
walletName.text != '') walletName.text != '')
? () { ? () async {
_generateWalletProvider.storeHDWChest( _generateWalletProvider.storeHDWChest(
generatedWallet, generatedWallet,
walletName.text, walletName.text,
@ -148,12 +146,19 @@ class ConfirmStoreWallet extends StatelessWidget with ChangeNotifier {
_myWalletProvider.listWallets = _myWalletProvider.listWallets =
_myWalletProvider _myWalletProvider
.readAllWallets(_currentChest); .readAllWallets(_currentChest);
scheduleMicrotask(() { await Future.delayed(
_walletOptions.reloadBuild(); const Duration(milliseconds: 50));
_myWalletProvider.rebuildWidget(); _myWalletProvider.rebuildWidget();
}); Navigator.pushAndRemoveUntil(context,
Navigator.popUntil( MaterialPageRoute(builder: (context) {
context, ModalRoute.withName('/')); return UnlockingWallet(
wallet:
_myWalletProvider.getDefaultWallet(
configBox.get('currentChest'),
),
action: "mywallets",
);
}), ModalRoute.withName('/'));
} }
: null, : null,
child: const Text('Confirmer', child: const Text('Confirmer',

View File

@ -1,10 +1,8 @@
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:gecko/globals.dart'; import 'package:gecko/globals.dart';
import 'package:gecko/models/generate_wallets.dart'; import 'package:gecko/models/generate_wallets.dart';
import 'package:gecko/models/my_wallets.dart';
import 'package:gecko/screens/myWallets/confirm_wallet_storage.dart'; import 'package:gecko/screens/myWallets/confirm_wallet_storage.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
import 'package:printing/printing.dart'; import 'package:printing/printing.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:super_tooltip/super_tooltip.dart'; import 'package:super_tooltip/super_tooltip.dart';
@ -29,8 +27,6 @@ class GenerateFastChestScreen extends StatelessWidget {
Provider.of<GenerateWalletsProvider>(context); Provider.of<GenerateWalletsProvider>(context);
_generateWalletProvider.generateMnemonic(); _generateWalletProvider.generateMnemonic();
MyWalletsProvider _myWalletClass = MyWalletsProvider();
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
toolbarHeight: 60 * ratio, toolbarHeight: 60 * ratio,
@ -122,14 +118,17 @@ class GenerateFastChestScreen extends StatelessWidget {
); );
await Future.delayed( await Future.delayed(
const Duration(milliseconds: 20)); const Duration(milliseconds: 20));
await Navigator.pushAndRemoveUntil(context, // if (_generateWalletProvider.hasBeenStored) {
MaterialPageRoute(builder: (context) { // _generateWalletProvider.hasBeenStored = false;
return UnlockingWallet( // await Navigator.pushAndRemoveUntil(context,
wallet: _myWalletClass.getDefaultWallet( // MaterialPageRoute(builder: (context) {
configBox.get('currentChest')), // return UnlockingWallet(
action: "mywallets", // wallet: _myWalletClass.getDefaultWallet(
); // configBox.get('currentChest')),
}), ModalRoute.withName('/')); // action: "mywallets",
// );
// }), ModalRoute.withName('/'));
// }
} }
: null, : null,
child: const Text('Enregistrer ce trousseau', child: const Text('Enregistrer ce trousseau',

View File

@ -24,7 +24,7 @@ class ImportWalletScreen extends StatelessWidget {
return WillPopScope( return WillPopScope(
onWillPop: () { onWillPop: () {
_generateWalletProvider.resetImportView(); _generateWalletProvider.resetCesiumImportView();
return Future<bool>.value(true); return Future<bool>.value(true);
}, },
child: Scaffold( child: Scaffold(
@ -33,7 +33,7 @@ class ImportWalletScreen extends StatelessWidget {
leading: IconButton( leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black), icon: const Icon(Icons.arrow_back, color: Colors.black),
onPressed: () { onPressed: () {
_generateWalletProvider.resetImportView(); _generateWalletProvider.resetCesiumImportView();
Navigator.of(context).pop(); Navigator.of(context).pop();
}), }),
title: const SizedBox( title: const SizedBox(
@ -171,7 +171,8 @@ class ImportWalletScreen extends StatelessWidget {
.importCesiumWallet() .importCesiumWallet()
.then((value) { .then((value) {
_myWalletProvider.rebuildWidget(); _myWalletProvider.rebuildWidget();
_generateWalletProvider.resetImportView(); _generateWalletProvider
.resetCesiumImportView();
Navigator.popUntil( Navigator.popUntil(
context, context,
ModalRoute.withName('/'), ModalRoute.withName('/'),

View File

@ -0,0 +1,184 @@
import 'package:bubble/bubble.dart';
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:flutter/material.dart';
import 'package:gecko/models/generate_wallets.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/onBoarding/11.dart';
import 'package:provider/provider.dart';
// import 'package:gecko/models/home.dart';
// import 'package:provider/provider.dart';
class RestoreChest extends StatelessWidget {
const RestoreChest({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
GenerateWalletsProvider generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context, listen: false);
generateWalletProvider.actualWallet = null;
return WillPopScope(
onWillPop: () {
generateWalletProvider.resetImportView();
return Future<bool>.value(true);
},
child: Scaffold(
appBar: AppBar(
toolbarHeight: 60 * ratio,
leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black),
onPressed: () {
generateWalletProvider.resetImportView();
Navigator.of(context).pop();
}),
title: const SizedBox(
height: 22,
child: Text('Restaurer un coffre'),
)),
body: SafeArea(
child: Column(children: <Widget>[
SizedBox(height: isTall ? 30 : 15),
bubbleSpeak(
'Pour restaurer vos portefeuilles Gecko, rentrez dans les champs ci-dessous les 12 mots qui constituent votre phrase de restauration :'),
SizedBox(height: isTall ? 30 : 15),
Column(children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
arrayCell(context, generateWalletProvider.cellController0),
arrayCell(context, generateWalletProvider.cellController1),
arrayCell(context, generateWalletProvider.cellController2),
arrayCell(context, generateWalletProvider.cellController3),
]),
const SizedBox(height: 15),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
arrayCell(context, generateWalletProvider.cellController4),
arrayCell(context, generateWalletProvider.cellController5),
arrayCell(context, generateWalletProvider.cellController6),
arrayCell(context, generateWalletProvider.cellController7),
]),
const SizedBox(height: 15),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
arrayCell(context, generateWalletProvider.cellController8),
arrayCell(context, generateWalletProvider.cellController9),
arrayCell(context, generateWalletProvider.cellController10),
arrayCell(context, generateWalletProvider.cellController11),
]),
]),
// const Spacer(),
if (generateWalletProvider.isSentenceComplete(context))
Expanded(
child: Align(
alignment: Alignment.center,
child: SizedBox(
width: 410,
height: 70,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 4,
primary: orangeC, // background
onPrimary: Colors.white, // foreground
),
onPressed: () async {
if (await generateWalletProvider.isSentenceValid()) {
generateWalletProvider.resetImportView();
await Navigator.push(
context,
FaderTransition(
page: OnboardingStepThirteen(), isFast: true),
);
} else {
await badMnemonicPopup(context);
}
},
child: const Text(
'Restaurer ce coffre',
style:
TextStyle(fontSize: 24, fontWeight: FontWeight.w600),
),
),
),
// SizedBox(height: isTall ? 80 : 80),
))
]),
),
),
);
}
Widget bubbleSpeak(String text) {
return Bubble(
margin: const BubbleEdges.symmetric(horizontal: 20),
padding: BubbleEdges.all(isTall ? 25 : 15),
borderWidth: 1,
borderColor: Colors.black,
radius: Radius.zero,
color: Colors.white,
child: Text(
text,
key: const Key('importText'),
textAlign: TextAlign.justify,
style: const TextStyle(
color: Colors.black, fontSize: 19, fontWeight: FontWeight.w400),
),
);
}
Widget arrayCell(BuildContext context, TextEditingController cellCtl) {
GenerateWalletsProvider generateWalletProvider =
Provider.of<GenerateWalletsProvider>(context);
return Container(
width: 102,
height: 40 * ratio,
child: TextField(
autofocus: true,
controller: cellCtl,
textInputAction: TextInputAction.next,
onChanged: (v) {
bool isValid = generateWalletProvider.isBipWord(v);
if (isValid && generateWalletProvider.cellController11.text.isEmpty) {
FocusScope.of(context).nextFocus();
}
},
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 20),
),
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
color: Colors.white,
borderRadius: BorderRadius.circular(3),
),
);
}
Future<bool> badMnemonicPopup(BuildContext context) async {
return showDialog<bool>(
context: context,
barrierDismissible: true, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Phrase incorrecte'),
content: const Text(
'Votre phrase de restauration semble incorrecte, veuillez la corriger.'),
actions: <Widget>[
TextButton(
child: const Text("OK"),
onPressed: () {
Navigator.pop(context);
},
),
],
);
},
);
}
}

View File

@ -2,11 +2,12 @@ import 'dart:async';
import 'package:dubp/dubp.dart'; import 'package:dubp/dubp.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:gecko/models/chest_data.dart'; import 'package:gecko/models/chest_data.dart';
import 'package:gecko/models/history.dart'; import 'package:gecko/models/wallets_profiles.dart';
import 'package:gecko/models/my_wallets.dart'; import 'package:gecko/models/my_wallets.dart';
import 'package:gecko/models/wallet_data.dart'; import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/models/wallet_options.dart'; import 'package:gecko/models/wallet_options.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:gecko/screens/myWallets/cesium_wallet_options.dart';
import 'package:gecko/screens/myWallets/choose_chest.dart'; import 'package:gecko/screens/myWallets/choose_chest.dart';
import 'package:pin_code_fields/pin_code_fields.dart'; import 'package:pin_code_fields/pin_code_fields.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -36,7 +37,6 @@ class UnlockingWallet extends StatelessWidget {
Provider.of<WalletOptionsProvider>(context); Provider.of<WalletOptionsProvider>(context);
int _pinLenght; int _pinLenght;
ChestData currentChest = chestBox.get(configBox.get('currentChest')); ChestData currentChest = chestBox.get(configBox.get('currentChest'));
if (currentChest.isCesium) { if (currentChest.isCesium) {
@ -53,7 +53,7 @@ class UnlockingWallet extends StatelessWidget {
child: Column(children: <Widget>[ child: Column(children: <Widget>[
Expanded( Expanded(
child: Column(children: <Widget>[ child: Column(children: <Widget>[
SizedBox(height: isTall ? 80 : 20), SizedBox(height: isTall ? 100 : 20),
Row(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Row(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
currentChest.imageFile == null currentChest.imageFile == null
? Image.asset( ? Image.asset(
@ -87,7 +87,7 @@ class UnlockingWallet extends StatelessWidget {
fontWeight: FontWeight.w400), fontWeight: FontWeight.w400),
)), )),
SizedBox(height: 40 * ratio), SizedBox(height: 40 * ratio),
pinForm(context, _pinLenght), pinForm(context, _pinLenght, currentChest),
SizedBox(height: 3 * ratio), SizedBox(height: 3 * ratio),
InkWell( InkWell(
key: const Key('chooseChest'), key: const Key('chooseChest'),
@ -95,7 +95,7 @@ class UnlockingWallet extends StatelessWidget {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute(builder: (context) { MaterialPageRoute(builder: (context) {
return const ChooseChest(); return ChooseChest(action: action);
}), }),
); );
}, },
@ -103,11 +103,14 @@ class UnlockingWallet extends StatelessWidget {
width: 400, width: 400,
height: 70, height: 70,
child: Center( child: Center(
child: Text('Changer de coffre', child: Text(
style: TextStyle( 'Changer de coffre',
fontSize: 22, style: TextStyle(
color: orangeC, fontSize: 22,
fontWeight: FontWeight.w600))), color: orangeC,
fontWeight: FontWeight.w600),
),
),
)), )),
]), ]),
), ),
@ -115,7 +118,7 @@ class UnlockingWallet extends StatelessWidget {
)); ));
} }
Widget pinForm(context, _pinLenght) { Widget pinForm(context, _pinLenght, ChestData currentChest) {
// var _walletPin = ''; // var _walletPin = '';
// ignore: close_sinks // ignore: close_sinks
StreamController<ErrorAnimationType> errorController = StreamController<ErrorAnimationType> errorController =
@ -125,7 +128,8 @@ class UnlockingWallet extends StatelessWidget {
Provider.of<WalletOptionsProvider>(context); Provider.of<WalletOptionsProvider>(context);
MyWalletsProvider _myWalletProvider = MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context); Provider.of<MyWalletsProvider>(context);
HistoryProvider _historyProvider = Provider.of<HistoryProvider>(context); WalletsProfilesProvider _historyProvider =
Provider.of<WalletsProfilesProvider>(context);
FocusNode pinFocus = FocusNode(); FocusNode pinFocus = FocusNode();
@ -194,7 +198,16 @@ class UnlockingWallet extends StatelessWidget {
pinColor = Colors.green[400]; pinColor = Colors.green[400];
// await Future.delayed(Duration(milliseconds: 50)); // await Future.delayed(Duration(milliseconds: 50));
if (action == "mywallets") { if (action == "mywallets") {
Navigator.pushNamed(formKey.currentContext, '/mywallets'); currentChest.isCesium
? Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return CesiumWalletOptions(
cesiumWallet: currentChest);
}),
)
: Navigator.pushNamed(
formKey.currentContext, '/mywallets');
} else if (action == "pay") { } else if (action == "pay") {
resultPay = resultPay =
await _historyProvider.pay(context, _pin.toUpperCase()); await _historyProvider.pay(context, _pin.toUpperCase());
@ -212,6 +225,7 @@ class UnlockingWallet extends StatelessWidget {
} }
Future<bool> _paymentsResult(context) { Future<bool> _paymentsResult(context) {
if (resultPay != "Success") log.i(resultPay);
return showDialog<bool>( return showDialog<bool>(
context: context, context: context,
barrierDismissible: true, // user must tap button! barrierDismissible: true, // user must tap button!

View File

@ -3,11 +3,12 @@ import 'dart:ui';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:gecko/globals.dart'; import 'package:gecko/globals.dart';
import 'package:gecko/models/history.dart';
import 'package:gecko/models/my_wallets.dart'; import 'package:gecko/models/my_wallets.dart';
import 'package:gecko/models/queries.dart'; import 'package:gecko/models/queries.dart';
import 'package:gecko/models/wallet_data.dart'; import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/models/wallet_options.dart'; import 'package:gecko/models/wallet_options.dart';
import 'package:gecko/models/wallets_profiles.dart';
import 'package:gecko/screens/history.dart';
import 'package:graphql_flutter/graphql_flutter.dart'; import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
@ -24,10 +25,12 @@ class WalletOptions extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
WalletOptionsProvider _walletOptions = WalletOptionsProvider _walletOptions =
Provider.of<WalletOptionsProvider>(context); Provider.of<WalletOptionsProvider>(context, listen: false);
WalletsProfilesProvider _historyProvider =
Provider.of<WalletsProfilesProvider>(context, listen: false);
MyWalletsProvider _myWalletProvider = MyWalletsProvider _myWalletProvider =
Provider.of<MyWalletsProvider>(context); Provider.of<MyWalletsProvider>(context);
HistoryProvider _historyProvider = Provider.of<HistoryProvider>(context);
final int _currentChest = _myWalletProvider.getCurrentChest(); final int _currentChest = _myWalletProvider.getCurrentChest();
final String shortPubkey = final String shortPubkey =
@ -57,299 +60,340 @@ class WalletOptions extends StatelessWidget {
log.d("Wallet options: $currentChest:${wallet.number}"); log.d("Wallet options: $currentChest:${wallet.number}");
return WillPopScope( return WillPopScope(
onWillPop: () { onWillPop: () {
_walletOptions.isEditing = false; _walletOptions.isEditing = false;
_walletOptions.isBalanceBlur = true; _walletOptions.isBalanceBlur = true;
Navigator.popUntil( Navigator.popUntil(
context, context,
ModalRoute.withName('/mywallets'), ModalRoute.withName('/mywallets'),
); );
return Future<bool>.value(true); return Future<bool>.value(true);
}, },
child: Scaffold( child: Scaffold(
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
appBar: AppBar( appBar: AppBar(
toolbarHeight: 60 * ratio, toolbarHeight: 60 * ratio,
leading: IconButton( elevation: 0,
icon: const Icon(Icons.arrow_back, color: Colors.black), leading: IconButton(
onPressed: () { icon: const Icon(Icons.arrow_back, color: Colors.black),
_walletOptions.isEditing = false; onPressed: () {
_walletOptions.isBalanceBlur = true; _walletOptions.isEditing = false;
Navigator.popUntil( _walletOptions.isBalanceBlur = true;
context, Navigator.popUntil(
ModalRoute.withName('/mywallets'), context,
); ModalRoute.withName('/mywallets'),
}), );
title: SizedBox( }),
height: 22, title: SizedBox(
child: Text(_walletOptions.nameController.text), height: 22,
)), child: Consumer<WalletOptionsProvider>(
body: Builder( builder: (context, walletProvider, _) {
builder: (ctx) => SafeArea( return Text(_walletOptions.nameController.text);
child: Column(children: <Widget>[ }),
Container( ),
height: isTall ? 15 : 0, ),
color: yellowC, body: Builder(
), builder: (ctx) => SafeArea(
Container( child: Column(children: <Widget>[
decoration: BoxDecoration( Container(
gradient: LinearGradient( height: isTall ? 5 : 0,
begin: Alignment.topCenter, color: yellowC,
end: Alignment.bottomCenter, ),
colors: [ Consumer<WalletOptionsProvider>(
yellowC, builder: (context, walletProvider, _) {
const Color(0xfffafafa), return Container(
], decoration: BoxDecoration(
)), gradient: LinearGradient(
child: Row(children: <Widget>[ begin: Alignment.topCenter,
const SizedBox(width: 25), end: Alignment.bottomCenter,
InkWell( colors: [
onTap: () async { yellowC,
File newAvatar = const Color(0xfffafafa),
await _walletOptions.changeAvatar(); ],
if (newAvatar != null) { )),
wallet.imageFile = newAvatar; child: Row(children: <Widget>[
} const SizedBox(width: 25),
_walletOptions.reloadBuild(); InkWell(
}, onTap: () async {
child: wallet.imageFile == null File newAvatar = await walletProvider.changeAvatar();
? Image.asset( if (newAvatar != null) {
'assets/avatars/${wallet.imageName}', wallet.imageFile = newAvatar;
width: 110, }
) walletProvider.reloadBuild();
: Image.file( },
wallet.imageFile, child: wallet.imageFile == null
width: 110, ? Image.asset(
)), 'assets/avatars/${wallet.imageName}',
InkWell( width: 110,
onTap: () async {
File newAvatar =
await _walletOptions.changeAvatar();
if (newAvatar != null) {
wallet.imageFile = newAvatar;
}
_walletOptions.reloadBuild();
},
child: Column(children: <Widget>[
Image.asset(
'assets/walletOptions/camera.png',
),
const SizedBox(height: 100)
])),
Column(children: <Widget>[
Row(children: <Widget>[
Column(children: <Widget>[
SizedBox(
width: 260,
child: TextField(
key: const Key('walletName'),
autofocus: false,
focusNode: _walletOptions.walletNameFocus,
enabled: _walletOptions.isEditing,
controller: _walletOptions.nameController,
maxLines: _nbrLinesName,
textAlign: TextAlign.center,
decoration: const InputDecoration(
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
disabledBorder: InputBorder.none,
contentPadding: EdgeInsets.all(15.0),
),
style: TextStyle(
fontSize: isTall ? 27 : 23,
color: Colors.black,
fontWeight: FontWeight.w400,
fontFamily: 'Monospace')),
),
SizedBox(height: isTall ? 5 : 0),
Query(
options: QueryOptions(
document: gql(getBalance),
variables: {
'pubkey': _walletOptions.pubkey.text,
},
// pollInterval: Duration(seconds: 1),
),
builder: (QueryResult result,
{VoidCallback refetch, FetchMore fetchMore}) {
if (result.hasException) {
return Text(result.exception.toString());
}
if (result.isLoading) {
return const Text('Loading');
}
// List repositories = result.data['viewer']['repositories']['nodes'];
String wBalanceUD;
if (result.data['balance'] == null) {
wBalanceUD = '0.0';
} else {
int wBalanceG1 =
result.data['balance']['amount'];
int currentUD =
result.data['currentUd']['amount'];
double wBalanceUDBrut =
wBalanceG1 / currentUD; // .toString();
wBalanceUD = double.parse(
(wBalanceUDBrut).toStringAsFixed(2))
.toString();
}
return Row(children: <Widget>[
ImageFiltered(
imageFilter: ImageFilter.blur(
sigmaX: _walletOptions.isBalanceBlur
? 6
: 0,
sigmaY: _walletOptions.isBalanceBlur
? 5
: 0),
child: Text(wBalanceUD,
style: TextStyle(
fontSize: isTall ? 20 : 18,
color: Colors.black)),
),
Text(' DU',
style: TextStyle(
fontSize: isTall ? 20 : 18,
color: Colors.black))
]);
// Text(
// '$wBalanceUD DU',
// style: TextStyle(
// fontSize: 20, color: Colors.black),
// );
},
),
const SizedBox(height: 5),
InkWell(
key: const Key('displayBalance'),
onTap: () {
_walletOptions.bluringBalance();
},
child: Image.asset(
_walletOptions.isBalanceBlur
? 'assets/walletOptions/icon_oeuil.png'
: 'assets/walletOptions/icon_oeuil_close.png',
)),
]),
const SizedBox(width: 0),
Column(children: <Widget>[
InkWell(
key: const Key('renameWallet'),
onTap: () async {
_isNewNameValid =
_walletOptions.editWalletName(wallet.id(),
isCesium: false);
await Future.delayed(
const Duration(milliseconds: 30));
_walletOptions.walletNameFocus.requestFocus();
},
child: ClipRRect(
child: Image.asset(
_walletOptions.isEditing
? 'assets/walletOptions/android-checkmark.png'
: 'assets/walletOptions/edit.png',
width: 20,
height: 20),
)),
const SizedBox(
height: 60,
) )
]) : Image.file(
wallet.imageFile,
width: 110,
),
),
InkWell(
onTap: () async {
File newAvatar = await walletProvider.changeAvatar();
if (newAvatar != null) {
wallet.imageFile = newAvatar;
}
walletProvider.reloadBuild();
},
child: Column(children: <Widget>[
Image.asset(
'assets/walletOptions/camera.png',
height: 40,
),
const SizedBox(height: 80)
])),
Column(children: <Widget>[
Row(children: <Widget>[
Column(children: <Widget>[
SizedBox(
width: 260,
child: TextField(
key: const Key('walletName'),
autofocus: false,
focusNode: walletProvider.walletNameFocus,
enabled: walletProvider.isEditing,
controller: walletProvider.nameController,
maxLines: _nbrLinesName,
textAlign: TextAlign.center,
decoration: const InputDecoration(
border: InputBorder.none,
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
disabledBorder: InputBorder.none,
contentPadding: EdgeInsets.all(15.0),
),
style: TextStyle(
fontSize: isTall ? 27 : 23,
color: Colors.black,
fontWeight: FontWeight.w400,
fontFamily: 'Monospace')),
),
SizedBox(height: isTall ? 5 : 0),
Query(
options: QueryOptions(
document: gql(getBalance),
variables: {
'pubkey': walletProvider.pubkey.text,
},
// pollInterval: Duration(seconds: 1),
),
builder: (QueryResult result,
{VoidCallback refetch, FetchMore fetchMore}) {
if (result.hasException) {
return Text(result.exception.toString());
}
if (result.isLoading) {
return const Text('Loading');
}
// List repositories = result.data['viewer']['repositories']['nodes'];
String wBalanceUD;
if (result.data['balance'] == null) {
wBalanceUD = '0.0';
} else if (result.hasException) {
wBalanceUD = '?';
} else {
int wBalanceG1 =
result.data['balance']['amount'];
int currentUD =
result.data['currentUd']['amount'];
double wBalanceUDBrut =
wBalanceG1 / currentUD; // .toString();
wBalanceUD = double.parse(
(wBalanceUDBrut).toStringAsFixed(2))
.toString();
}
return Row(children: <Widget>[
ImageFiltered(
imageFilter: ImageFilter.blur(
sigmaX:
walletProvider.isBalanceBlur ? 6 : 0,
sigmaY:
walletProvider.isBalanceBlur ? 5 : 0),
child: Text(
wBalanceUD,
style: TextStyle(
fontSize: isTall ? 20 : 18,
color: Colors.black),
),
),
Text(' DU',
style: TextStyle(
fontSize: isTall ? 20 : 18,
color: Colors.black))
]);
// Text(
// '$wBalanceUD DU',
// style: TextStyle(
// fontSize: 20, color: Colors.black),
// );
},
),
const SizedBox(height: 5),
InkWell(
key: const Key('displayBalance'),
onTap: () {
walletProvider.bluringBalance();
},
child: Image.asset(
walletProvider.isBalanceBlur
? 'assets/walletOptions/icon_oeuil.png'
: 'assets/walletOptions/icon_oeuil_close.png',
height: 35,
),
),
]), ]),
const SizedBox(width: 0),
Column(children: <Widget>[
InkWell(
key: const Key('renameWallet'),
onTap: () async {
_isNewNameValid = walletProvider.editWalletName(
wallet.id(),
isCesium: false);
await Future.delayed(
const Duration(milliseconds: 30));
walletProvider.walletNameFocus.requestFocus();
},
child: ClipRRect(
child: Image.asset(
walletProvider.isEditing
? 'assets/walletOptions/android-checkmark.png'
: 'assets/walletOptions/edit.png',
width: 20,
height: 20),
)),
const SizedBox(
height: 60,
)
])
]), ]),
])), ]),
SizedBox(height: 4 * ratio), ]),
FutureBuilder( );
future: _walletOptions }),
.generateQRcode(_walletOptions.pubkey.text), SizedBox(height: 4 * ratio),
builder: (context, snapshot) { FutureBuilder(
return snapshot.data != null future:
? Image.memory(snapshot.data, _walletOptions.generateQRcode(_walletOptions.pubkey.text),
height: isTall ? 300 : 270) builder: (context, snapshot) {
: const Text('-', style: TextStyle(fontSize: 20)); return snapshot.data != null
}), ? Image.memory(snapshot.data, height: isTall ? 300 : 270)
SizedBox(height: 15 * ratio), : const Text('-', style: TextStyle(fontSize: 20));
GestureDetector( },
),
SizedBox(height: 15 * ratio),
Consumer<WalletOptionsProvider>(
builder: (context, walletProvider, _) {
return Column(children: [
GestureDetector(
key: const Key('copyPubkey'), key: const Key('copyPubkey'),
onTap: () { onTap: () {
Clipboard.setData( Clipboard.setData(
ClipboardData(text: _walletOptions.pubkey.text)); ClipboardData(text: walletProvider.pubkey.text));
_walletOptions.snackCopyKey(ctx); walletProvider.snackCopyKey(ctx);
}, },
child: SizedBox( child: SizedBox(
height: 50, height: 50,
child: Row(children: <Widget>[ child: Row(children: <Widget>[
const SizedBox(width: 30), const SizedBox(width: 30),
Image.asset( Image.asset(
'assets/walletOptions/key.png', 'assets/walletOptions/key.png',
height: 45,
),
const SizedBox(width: 20),
Text("${shortPubkey.split(':')[0]}:",
style: const TextStyle(
fontSize: 22,
fontWeight: FontWeight.w800,
fontFamily: 'Monospace',
color: Colors.black)),
Text(shortPubkey.split(':')[1],
style: const TextStyle(
fontSize: 22,
fontWeight: FontWeight.w800,
fontFamily: 'Monospace')),
const SizedBox(width: 15),
SizedBox(
height: 40,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
elevation: 1,
primary: orangeC, // background
onPrimary: Colors.black, // foreground
),
onPressed: () {
Clipboard.setData(ClipboardData(
text: walletProvider.pubkey.text));
walletProvider.snackCopyKey(ctx);
},
child: Row(children: <Widget>[
Image.asset(
'assets/walletOptions/copy-white.png',
height: 25,
),
const SizedBox(width: 7),
Text(
'Copier',
style: TextStyle(
fontSize: 15, color: Colors.grey[50]),
)
]),
), ),
const SizedBox(width: 20), ),
Text("${shortPubkey.split(':')[0]}:", ]),
style: const TextStyle( ),
fontSize: 22, ),
fontWeight: FontWeight.w800, SizedBox(height: 10 * ratio),
fontFamily: 'Monospace', InkWell(
color: Colors.black)),
Text(shortPubkey.split(':')[1],
style: const TextStyle(
fontSize: 22,
fontWeight: FontWeight.w800,
fontFamily: 'Monospace')),
const SizedBox(width: 15),
SizedBox(
height: 40,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
elevation: 1,
primary: orangeC, // background
onPrimary: Colors.black, // foreground
),
onPressed: () {
Clipboard.setData(ClipboardData(
text: _walletOptions.pubkey.text));
_walletOptions.snackCopyKey(ctx);
},
child: Row(children: <Widget>[
Image.asset(
'assets/walletOptions/copy-white.png',
),
const SizedBox(width: 7),
Text('Copier',
style: TextStyle(
fontSize: 15,
color: Colors.grey[50]))
]))),
]))),
SizedBox(height: 10 * ratio),
InkWell(
key: const Key('displayHistory'), key: const Key('displayHistory'),
onTap: () { onTap: () {
_historyProvider.isPubkey(ctx, _walletOptions.pubkey.text, _historyProvider.nPage = 1;
goHistory: true); Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return HistoryScreen(
pubkey: walletProvider.pubkey.text,
avatar: wallet.imageFile == null
? Image.asset(
'assets/avatars/${wallet.imageName}',
width: 110,
)
: Image.file(
wallet.imageFile,
width: 110,
));
}),
);
}, },
child: SizedBox( child: SizedBox(
height: 50, height: 50,
child: Row(children: <Widget>[ child: Row(children: <Widget>[
const SizedBox(width: 30), const SizedBox(width: 30),
Image.asset( Image.asset(
'assets/walletOptions/clock.png', 'assets/walletOptions/clock.png',
), height: 45,
const SizedBox(width: 22), ),
const Text('Historique des transactions', const SizedBox(width: 22),
style: const Text('Historique des transactions',
TextStyle(fontSize: 20, color: Colors.black)), style:
]))), TextStyle(fontSize: 20, color: Colors.black)),
SizedBox(height: 12 * ratio), ]),
InkWell( ),
),
SizedBox(height: 12 * ratio),
InkWell(
key: const Key('setDefaultWallet'), key: const Key('setDefaultWallet'),
onTap: !_walletOptions.isDefaultWallet onTap: !walletProvider.isDefaultWallet
? () { ? () {
defaultWallet = wallet; defaultWallet = wallet;
chestBox.get(currentChest).defaultWallet = chestBox.get(currentChest).defaultWallet =
@ -359,33 +403,37 @@ class WalletOptions extends StatelessWidget {
} }
: null, : null,
child: SizedBox( child: SizedBox(
height: 50, height: 50,
child: Row(children: <Widget>[ child: Row(children: <Widget>[
const SizedBox(width: 31), const SizedBox(width: 31),
CircleAvatar( CircleAvatar(
backgroundColor: Colors.grey[ backgroundColor: Colors
_walletOptions.isDefaultWallet ? 300 : 500], .grey[walletProvider.isDefaultWallet ? 300 : 500],
child: Image.asset( child: Image.asset(
'assets/walletOptions/android-checkmark.png', 'assets/walletOptions/android-checkmark.png',
)), height: 25,
const SizedBox(width: 22), ),
Text( ),
_walletOptions.isDefaultWallet const SizedBox(width: 22),
? 'Ce portefeuille est celui par defaut' Text(
: 'Définir comme portefeuille par défaut', walletProvider.isDefaultWallet
style: TextStyle( ? 'Ce portefeuille est celui par defaut'
fontSize: 20, : 'Définir comme portefeuille par défaut',
color: _walletOptions.isDefaultWallet style: TextStyle(
? Colors.grey[500] fontSize: 20,
: Colors.black)), color: walletProvider.isDefaultWallet
]))), ? Colors.grey[500]
SizedBox(height: 17 * ratio), : Colors.black)),
if (!_walletOptions.isDefaultWallet) ]),
InkWell( ),
),
SizedBox(height: 17 * ratio),
if (!walletProvider.isDefaultWallet)
InkWell(
key: const Key('deleteWallet'), key: const Key('deleteWallet'),
onTap: !_walletOptions.isDefaultWallet onTap: !walletProvider.isDefaultWallet
? () async { ? () async {
await _walletOptions.deleteWallet( await walletProvider.deleteWallet(
context, wallet); context, wallet);
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
_myWalletProvider.listWallets = _myWalletProvider.listWallets =
@ -396,18 +444,23 @@ class WalletOptions extends StatelessWidget {
} }
: null, : null,
child: Row(children: <Widget>[ child: Row(children: <Widget>[
const SizedBox(width: 33), const SizedBox(width: 30),
Image.asset( Image.asset(
'assets/walletOptions/trash.png', 'assets/walletOptions/trash.png',
height: 45,
), ),
const SizedBox(width: 24), const SizedBox(width: 19),
const Text('Supprimer ce portefeuille', const Text('Supprimer ce portefeuille',
style: TextStyle( style: TextStyle(
fontSize: 20, color: Color(0xffD80000))), fontSize: 20, color: Color(0xffD80000))),
])), ]),
]), ),
), ]);
}),
]),
), ),
)); ),
),
);
} }
} }

View File

@ -7,11 +7,9 @@ import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/models/wallet_options.dart'; import 'package:gecko/models/wallet_options.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:gecko/screens/common_elements.dart'; import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/myWallets/cesium_wallet_options.dart';
import 'package:gecko/screens/myWallets/chest_options.dart'; import 'package:gecko/screens/myWallets/chest_options.dart';
import 'package:gecko/screens/myWallets/choose_chest.dart'; import 'package:gecko/screens/myWallets/choose_chest.dart';
import 'package:gecko/screens/myWallets/wallet_options.dart'; import 'package:gecko/screens/myWallets/wallet_options.dart';
import 'package:gecko/screens/onBoarding/0_no_keychain_found.dart';
import 'package:graphql_flutter/graphql_flutter.dart'; import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -28,13 +26,8 @@ class WalletsHome extends StatelessWidget {
final int _currentChestNumber = myWalletProvider.getCurrentChest(); final int _currentChestNumber = myWalletProvider.getCurrentChest();
final ChestData _currentChest = chestBox.get(_currentChestNumber); final ChestData _currentChest = chestBox.get(_currentChestNumber);
bool isWalletsExists; myWalletProvider.listWallets =
myWalletProvider.readAllWallets(_currentChestNumber);
if (!_currentChest.isCesium) {
myWalletProvider.listWallets =
myWalletProvider.readAllWallets(_currentChestNumber);
}
isWalletsExists = myWalletProvider.checkIfWalletExist();
return WillPopScope( return WillPopScope(
onWillPop: () { onWillPop: () {
@ -61,12 +54,7 @@ class WalletsHome extends StatelessWidget {
backgroundColor: const Color(0xffFFD58D), backgroundColor: const Color(0xffFFD58D),
), ),
body: SafeArea( body: SafeArea(
child: !isWalletsExists child: myWalletsTiles(context),
? const NoKeyChainScreen()
: _currentChest.isCesium
? cesiumWalletOptions(
context, _currentChest, myWalletProvider)
: myWalletsTiles(context),
), ),
), ),
); );

View File

@ -0,0 +1,485 @@
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/cesium_plus.dart';
import 'package:gecko/models/home.dart';
import 'package:gecko/models/my_wallets.dart';
import 'package:gecko/models/queries.dart';
import 'package:gecko/models/wallets_profiles.dart';
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
import 'package:gecko/screens/wallet_view.dart';
import 'dart:ui';
import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:provider/provider.dart';
import 'package:flutter_svg/flutter_svg.dart';
// ignore: must_be_immutable
class OldHistoryScreen extends StatelessWidget with ChangeNotifier {
final TextEditingController _outputPubkey = TextEditingController();
ScrollController scrollController = ScrollController();
final nRepositories = 20;
// HistoryProvider _historyProvider;
final _formKey = GlobalKey<FormState>();
final FocusNode _pubkeyFocus = FocusNode();
final double avatarsSize = 80;
FetchMore fetchMore;
FetchMoreOptions opts;
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
OldHistoryScreen({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
WalletsProfilesProvider _historyProvider =
Provider.of<WalletsProfilesProvider>(context);
HomeProvider _homeProvider = Provider.of<HomeProvider>(context);
_outputPubkey.text = _historyProvider.pubkey;
log.i('Build pubkey : ' + _historyProvider.pubkey);
WidgetsBinding.instance.addPostFrameCallback((_) {});
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
toolbarHeight: 60 * ratio,
title: _homeProvider.appBarExplorer,
actions: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: IconButton(
icon: _homeProvider.searchIcon,
color: Colors.grey[850],
onPressed: () {
if (_homeProvider.searchIcon.icon == Icons.search) {
_homeProvider.searchIcon = Icon(
Icons.close,
color: Colors.grey[850],
);
_homeProvider.appBarExplorer = TextField(
autofocus: true,
controller: _homeProvider.searchQuery,
onChanged: (text) {
log.d("Clé tappé: $text");
if (_historyProvider.isPubkey(text)) {
_homeProvider.currentIndex = 0;
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return WalletViewScreen(pubkey: text);
}),
);
}
},
style: TextStyle(
color: Colors.grey[850],
),
decoration: InputDecoration(
prefixIcon:
Icon(Icons.search, color: Colors.grey[850]),
hintText: "Rechercher ...",
hintStyle: TextStyle(color: Colors.grey[850])),
);
_homeProvider.handleSearchStart();
} else {
_homeProvider.handleSearchEnd();
}
}))
],
backgroundColor: const Color(0xffFFD58D),
),
floatingActionButton: SizedBox(
height: 80.0,
width: 80.0,
child: FittedBox(
child: FloatingActionButton(
heroTag: "buttonScan",
onPressed: () async {
await _historyProvider.scan(context);
},
child: SizedBox(
height: 40.0,
width: 40.0,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 3),
child: Image.asset('assets/qrcode-scan.png'))),
backgroundColor:
floattingYellow, //smoothYellow, //Color.fromARGB(500, 204, 255, 255),
),
),
),
body: Column(children: <Widget>[
const SizedBox(height: 0),
if (_historyProvider.pubkey != '')
historyQuery(context, _historyProvider),
]));
}
Widget historyQuery(context, WalletsProfilesProvider _historyProvider) {
_pubkeyFocus.unfocus();
// HistoryProvider _historyProvider = Provider.of<HistoryProvider>(context);
CesiumPlusProvider _cesiumPlusProvider =
Provider.of<CesiumPlusProvider>(context);
bool _isFirstExec = true;
return Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Query(
options: QueryOptions(
document: gql(getHistory),
variables: <String, dynamic>{
'pubkey': _historyProvider.pubkey,
'number': nRepositories,
'cursor': null
},
),
builder: (QueryResult result, {fetchMore, refetch}) {
if (result.isLoading && result.data == null) {
return const Center(
child: CircularProgressIndicator(),
);
}
if (result.hasException) {
log.e('Error GVA: ' + result.exception.toString());
return Column(children: const <Widget>[
SizedBox(height: 50),
Text(
"Aucun noeud GVA valide n'a pu être trouvé.\nVeuillez réessayer ultérieurement.",
style: TextStyle(fontSize: 17.0),
)
]);
}
if (result.data == null && result.exception.toString() == null) {
return const Text('Aucune donnée à afficher.');
}
num balance;
if (result.data['balance'] == null) {
balance = 0.0;
} else {
balance = _historyProvider
.removeDecimalZero(result.data['balance']['amount'] / 100);
}
opts = _historyProvider.checkQueryResult(
result, opts, _outputPubkey.text);
// _historyProvider.transBC = null;
// Build history list
return NotificationListener(
child: Builder(
builder: (context) => Expanded(
child: ListView(
key: const Key('listTransactions'),
controller: scrollController,
children: <Widget>[
const SizedBox(height: 20),
if (_historyProvider.pubkey != '')
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
if (_isFirstExec)
Container(
padding: const EdgeInsets.fromLTRB(
20, 0, 30, 0),
child: FutureBuilder(
future:
_cesiumPlusProvider.getAvatar(
_historyProvider.pubkey,
55),
builder: (BuildContext context,
AsyncSnapshot<Image> _avatar) {
if (_avatar.connectionState !=
ConnectionState.done ||
_avatar.hasError) {
return Stack(children: [
_cesiumPlusProvider
.defaultAvatar(55),
Positioned(
top: 8,
right: 0,
width: 12,
height: 12,
child:
CircularProgressIndicator(
strokeWidth: 1,
color: orangeC,
),
),
]);
}
if (_avatar.hasData) {
return ClipOval(
child: _avatar.data,
);
}
return _cesiumPlusProvider
.defaultAvatar(55);
}),
),
GestureDetector(
key: const Key('copyPubkey'),
onTap: () {
Clipboard.setData(ClipboardData(
text: _historyProvider.pubkey));
_historyProvider.snackCopyKey(context);
},
child: Text(
_historyProvider.getShortPubkey(
_historyProvider.pubkey),
style: const TextStyle(
fontSize: 22,
fontWeight: FontWeight.w800,
fontFamily: 'Monospace')),
),
Container(
padding: const EdgeInsets.fromLTRB(
30, 0, 5, 0), // .only(right: 15),
child: Card(
child: Column(
children: <Widget>[
SvgPicture.string(
_historyProvider
.generateIdenticon(
_historyProvider
.pubkey),
fit: BoxFit.contain,
height: 64,
width: 64,
),
],
),
)),
const SizedBox(width: 0)
]),
if (_isFirstExec)
Row(
mainAxisAlignment:
MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
padding:
const EdgeInsets.fromLTRB(0, 0, 0, 0),
// padding: const EdgeInsets.,
child: FutureBuilder(
future: _cesiumPlusProvider
.getName(_historyProvider.pubkey),
initialData: '...',
builder: (context, snapshot) {
return Text(snapshot.data ?? '-',
style: const TextStyle(
fontSize: 20));
}),
)
]),
const SizedBox(height: 18),
if (_isFirstExec)
Container(
padding:
const EdgeInsets.fromLTRB(0, 0, 0, 0),
child: Text(balance.toString() + ' Ğ1',
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 18.0))),
const SizedBox(height: 20),
ElevatedButton(
key: const Key('switchPayHistory'),
style: ElevatedButton.styleFrom(
elevation: 1,
primary: Colors.grey[50], // background
onPrimary: Colors.black, // foreground
),
onPressed: () {
_historyProvider.switchProfileView();
},
child: Text(
_historyProvider.historySwitchButtun,
style: TextStyle(
fontSize: 15, color: orangeC))),
// const Divider(
// color: Colors.grey,
// height: 5,
// thickness: 0.5,
// indent: 0,
// endIndent: 0,
// ),
_historyProvider.isHistoryScreen
? historyView(context, result)
: payView(context, _historyProvider),
],
))),
onNotification: (t) {
if (t is ScrollEndNotification &&
scrollController.position.pixels >=
scrollController.position.maxScrollExtent * 0.7) {
fetchMore(opts);
}
return true;
});
},
),
],
));
}
Widget payView(context, WalletsProfilesProvider _historyProvider) {
MyWalletsProvider _myWalletProvider = MyWalletsProvider();
WalletData defaultWallet =
_myWalletProvider.getDefaultWallet(configBox.get('currentChest'));
return Stack(
clipBehavior: Clip.hardEdge,
children: <Widget>[
Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const SizedBox(height: 20),
const Text('Commentaire:', style: TextStyle(fontSize: 20.0)),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
controller: _historyProvider.payComment,
maxLines: 2,
textAlign: TextAlign.center,
decoration: const InputDecoration(),
style: const TextStyle(
fontSize: 22,
color: Colors.black,
fontWeight: FontWeight.bold))),
const SizedBox(height: 20),
const Text('Montant (DU/Ğ1):', style: TextStyle(fontSize: 20.0)),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
style: const TextStyle(fontSize: 22),
controller: _historyProvider.payAmount,
textAlign: TextAlign.center,
maxLines: 1,
keyboardType: TextInputType.number,
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(
vertical: 25.0, horizontal: 10.0),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.0)),
),
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.allow(RegExp(r'(^\d*\.?\d*)'))
],
),
),
Padding(
padding: const EdgeInsets.only(top: 15),
child: OutlinedButton(
style: OutlinedButton.styleFrom(
side: BorderSide(width: 2, color: orangeC)),
onPressed: () {
// if (_formKey.currentState.validate()) {
// _formKey.currentState.save();
// }
// _historyProvider.pay(payAmount.text, payComment.text);
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return UnlockingWallet(
wallet: defaultWallet, action: "pay");
}),
);
},
child: Padding(
padding: const EdgeInsets.all(12),
child: Text(
"PAYER",
style: TextStyle(fontSize: 25, color: Colors.grey[850]),
),
),
),
)
],
),
),
],
);
}
Widget historyView(context, result) {
WalletsProfilesProvider _historyProvider =
Provider.of<WalletsProfilesProvider>(context);
HomeProvider _homeProvider =
Provider.of<HomeProvider>(context, listen: false);
int keyID = 0;
return _historyProvider.transBC == null
? const Text('Aucune transaction à afficher.')
: Column(children: <Widget>[
for (var repository in _historyProvider.transBC)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 5.0),
child: ListTile(
key: Key('transaction${keyID++}'),
contentPadding: const EdgeInsets.all(5.0),
leading: Text(repository[1].toString(),
style: TextStyle(
fontSize: 12,
color: Colors.grey[800],
fontWeight: FontWeight.w700),
textAlign: TextAlign.center),
title: Text(repository[3],
style: const TextStyle(
fontSize: 15.0, fontFamily: 'Monospace'),
textAlign: TextAlign.center),
subtitle: Text(repository[6] != '' ? repository[6] : '-',
style: const TextStyle(fontSize: 12.0),
textAlign: TextAlign.center),
trailing: Text("${repository[4]} Ğ1",
style: const TextStyle(fontSize: 14.0),
textAlign: TextAlign.justify),
dense: true,
isThreeLine: false,
onTap: () {
if (_historyProvider.isPubkey(repository[2])) {
_homeProvider.currentIndex = 0;
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return WalletViewScreen(pubkey: repository[2]);
}),
);
}
Navigator.pop(context);
}),
),
if (result.isLoading &&
_historyProvider.pageInfo['hasPreviousPage'])
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[
CircularProgressIndicator(),
],
),
// if (_historyProvider.isTheEnd) // What I did before ...
if (!_historyProvider.pageInfo['hasPreviousPage'])
Column(
children: const <Widget>[
SizedBox(height: 15),
Text("Début de l'historique.",
textAlign: TextAlign.center,
style: TextStyle(fontSize: 20)),
SizedBox(height: 15)
],
)
]);
}
}

View File

@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:gecko/globals.dart'; import 'package:gecko/globals.dart';
import 'package:gecko/screens/common_elements.dart'; import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/myWallets/import_wallet.dart'; import 'package:gecko/screens/myWallets/import_cesium_wallet.dart';
import 'package:gecko/screens/onBoarding/1.dart'; import 'package:gecko/screens/onBoarding/1.dart';
class NoKeyChainScreen extends StatelessWidget { class NoKeyChainScreen extends StatelessWidget {

View File

@ -46,13 +46,10 @@ class OnboardingStepFiveteen extends StatelessWidget {
onPrimary: Colors.white, // foreground onPrimary: Colors.white, // foreground
), ),
onPressed: () { onPressed: () {
Navigator.popUntil( Navigator.pushNamedAndRemoveUntil(
context,
ModalRoute.withName('/'),
);
Navigator.pushNamed(
context, context,
'/mywallets', '/mywallets',
ModalRoute.withName('/'),
); );
}, },
child: const Text("Accéder à mes portefeuilles", child: const Text("Accéder à mes portefeuilles",

View File

@ -51,6 +51,7 @@ class OnboardingStepNine extends StatelessWidget {
}, },
child: Image.asset( child: Image.asset(
'assets/printer.png', 'assets/printer.png',
height: 35,
), ),
), ),
Expanded( Expanded(
@ -133,55 +134,63 @@ Widget sentanceArray(BuildContext context) {
builder: (context, formatedArray) { builder: (context, formatedArray) {
// print(formatedArray.data); // print(formatedArray.data);
return Container( return Container(
padding: const EdgeInsets.symmetric(horizontal: 12), padding: const EdgeInsets.symmetric(horizontal: 12),
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
border: Border.all(color: Colors.black), border: Border.all(color: Colors.black),
color: Colors.grey[300], color: Colors.grey[300],
borderRadius: const BorderRadius.all( borderRadius: const BorderRadius.all(
Radius.circular(10), Radius.circular(10),
)), )),
// color: Colors.grey[300], // color: Colors.grey[300],
padding: const EdgeInsets.all(20), padding: const EdgeInsets.all(20),
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max, mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[ children: <Widget>[
Row(children: <Widget>[ Row(children: <Widget>[
arrayCell(formatedArray.data[0]), arrayCell(formatedArray.data[0]),
arrayCell(formatedArray.data[1]), arrayCell(formatedArray.data[1]),
arrayCell(formatedArray.data[2]), arrayCell(formatedArray.data[2]),
arrayCell(formatedArray.data[3]), arrayCell(formatedArray.data[3]),
]), ]),
const SizedBox(height: 15), const SizedBox(height: 15),
Row(children: <Widget>[ Row(children: <Widget>[
arrayCell(formatedArray.data[4]), arrayCell(formatedArray.data[4]),
arrayCell(formatedArray.data[5]), arrayCell(formatedArray.data[5]),
arrayCell(formatedArray.data[6]), arrayCell(formatedArray.data[6]),
arrayCell(formatedArray.data[7]), arrayCell(formatedArray.data[7]),
]), ]),
const SizedBox(height: 15), const SizedBox(height: 15),
Row(children: <Widget>[ Row(children: <Widget>[
arrayCell(formatedArray.data[8]), arrayCell(formatedArray.data[8]),
arrayCell(formatedArray.data[9]), arrayCell(formatedArray.data[9]),
arrayCell(formatedArray.data[10]), arrayCell(formatedArray.data[10]),
arrayCell(formatedArray.data[11]), arrayCell(formatedArray.data[11]),
]), ]),
]))); ]),
),
);
}); });
} }
Widget arrayCell(dataWord) { Widget arrayCell(dataWord) {
return SizedBox( return SizedBox(
width: 102, width: 102,
child: Column(children: <Widget>[ child: Column(children: <Widget>[
Text(dataWord.split(':')[0], style: const TextStyle(fontSize: 14)), Text(
const SizedBox(height: 2), dataWord.split(':')[0],
Text(dataWord.split(':')[1], style: const TextStyle(fontSize: 14),
key: Key('word${dataWord.split(':')[0]}'), ),
style: const TextStyle(fontSize: 19, color: Colors.black)), const SizedBox(height: 2),
])); Text(
dataWord.split(':')[1],
key: Key('word${dataWord.split(':')[0]}'),
style: const TextStyle(fontSize: 19, color: Colors.black),
),
]),
);
} }
// ignore: must_be_immutable // ignore: must_be_immutable

109
lib/screens/search.dart Normal file
View File

@ -0,0 +1,109 @@
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:flutter/material.dart';
import 'package:gecko/models/search.dart';
import 'package:gecko/screens/search_result.dart';
import 'package:provider/provider.dart';
// import 'package:gecko/models/home.dart';
// import 'package:provider/provider.dart';
class SearchScreen extends StatelessWidget {
const SearchScreen({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
SearchProvider _searchProvider = Provider.of<SearchProvider>(context);
return WillPopScope(
onWillPop: () {
_searchProvider.searchController.text = '';
return Future<bool>.value(true);
},
child: Scaffold(
appBar: AppBar(
toolbarHeight: 60 * ratio,
title: const SizedBox(
height: 22,
child: Text('Rechercher'),
),
leading: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.black),
onPressed: () {
_searchProvider.searchController.text = '';
Navigator.of(context).pop();
}),
),
body: SafeArea(
child: Column(children: <Widget>[
SizedBox(height: isTall ? 200 : 100),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 17),
child: TextField(
controller: _searchProvider.searchController,
autofocus: true,
maxLines: 1,
textAlign: TextAlign.left,
onChanged: (v) => _searchProvider.rebuildWidget(),
decoration: InputDecoration(
filled: true,
fillColor: Colors.white,
prefixIconConstraints: const BoxConstraints(
minHeight: 32,
),
prefixIcon: const Padding(
padding: EdgeInsets.symmetric(horizontal: 17),
child: Image(
image: AssetImage('assets/loupe-noire.png'),
height: 35),
),
border: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.grey[500], width: 2),
borderRadius: BorderRadius.circular(8)),
focusedBorder: OutlineInputBorder(
borderSide:
BorderSide(color: Colors.grey[500], width: 2.5),
borderRadius: BorderRadius.circular(8),
),
contentPadding: const EdgeInsets.all(20),
),
style: const TextStyle(
fontSize: 20,
color: Colors.black,
fontWeight: FontWeight.w400,
),
),
),
const Spacer(flex: 1),
SizedBox(
width: 410,
height: 70,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 4,
primary: orangeC, // background
onPrimary: Colors.white, // foreground
),
onPressed: _searchProvider.searchController.text.length >= 2
? () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return const SearchResultScreen();
}),
);
}
: null,
child: const Text(
'Rechercher',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.w600),
),
),
),
const Spacer(flex: 1),
]),
),
));
}
}

View File

@ -0,0 +1,184 @@
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:flutter/material.dart';
import 'package:gecko/models/cesium_plus.dart';
import 'package:gecko/models/g1_wallets_list.dart';
import 'package:gecko/models/wallets_profiles.dart';
import 'package:gecko/models/search.dart';
import 'package:gecko/screens/wallet_view.dart';
import 'package:provider/provider.dart';
class SearchResultScreen extends StatelessWidget {
const SearchResultScreen({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
SearchProvider _searchProvider =
Provider.of<SearchProvider>(context, listen: false);
CesiumPlusProvider _cesiumPlusProvider =
Provider.of<CesiumPlusProvider>(context, listen: false);
WalletsProfilesProvider _walletsProfilesClass =
Provider.of<WalletsProfilesProvider>(context, listen: false);
int keyID = 0;
double _avatarSize = 55;
return Scaffold(
appBar: AppBar(
toolbarHeight: 60 * ratio,
title: const SizedBox(
height: 22,
child: Text('Résultats de votre recherche'),
),
),
body: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child:
Column(crossAxisAlignment: CrossAxisAlignment.start, children: <
Widget>[
const SizedBox(height: 30),
RichText(
text: TextSpan(
style: TextStyle(
fontSize: 18,
color: Colors.grey[700],
),
children: <TextSpan>[
const TextSpan(
text: "Résultats pour ",
),
TextSpan(
text: '"${_searchProvider.searchController.text}"',
style: const TextStyle(fontStyle: FontStyle.italic),
),
],
),
),
const SizedBox(height: 40),
const Text(
'Dans la blockchain Ğ1',
style: TextStyle(fontSize: 20),
),
const SizedBox(height: 20),
FutureBuilder(
future: _searchProvider.searchBlockchain(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Expanded(
child: ListView(children: <Widget>[
for (G1WalletsList g1Wallet in snapshot.data)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 5),
child: ListTile(
key: Key('searchResult${keyID++}'),
horizontalTitleGap: 40,
contentPadding: const EdgeInsets.all(5),
leading: g1WalletsBox
.get(g1Wallet.pubkey)
?.avatar !=
null
? ClipOval(
child: g1WalletsBox
.get(g1Wallet.pubkey)
.avatar)
: FutureBuilder(
future: _cesiumPlusProvider.getAvatar(
g1Wallet.pubkey, _avatarSize),
builder: (BuildContext context,
AsyncSnapshot<Image> _avatar) {
if (_avatar.connectionState !=
ConnectionState.done ||
_avatar.hasError) {
return Stack(children: [
_cesiumPlusProvider
.defaultAvatar(_avatarSize),
Positioned(
top: 8,
right: 0,
width: 12,
height: 12,
child: CircularProgressIndicator(
strokeWidth: 1,
color: orangeC,
),
),
]);
}
if (_avatar.hasData) {
g1WalletsBox
.get(g1Wallet.pubkey)
.avatar = _avatar.data;
return ClipOval(child: _avatar.data);
} else {
g1WalletsBox
.get(g1Wallet.pubkey)
.avatar =
_cesiumPlusProvider
.defaultAvatar(_avatarSize);
return _cesiumPlusProvider
.defaultAvatar(_avatarSize);
}
}),
title: Row(children: <Widget>[
Text(
_walletsProfilesClass
.getShortPubkey(g1Wallet.pubkey),
style: const TextStyle(
fontSize: 18,
fontFamily: 'Monospace',
fontWeight: FontWeight.w500),
textAlign: TextAlign.center),
]),
subtitle: Row(children: <Widget>[
Text(g1Wallet?.id?.username ?? '',
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w500),
textAlign: TextAlign.center),
]),
dense: false,
isThreeLine: false,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
_walletsProfilesClass.pubkey =
g1Wallet.pubkey;
return WalletViewScreen(
pubkey: g1Wallet.pubkey,
username: g1WalletsBox
.get(g1Wallet.pubkey)
?.id
?.username,
avatar: g1WalletsBox
.get(g1Wallet.pubkey)
?.avatar,
);
}),
);
}),
),
]),
);
}
return Center(
heightFactor: 5,
child: CircularProgressIndicator(
strokeWidth: 3,
backgroundColor: yellowC,
color: orangeC,
),
);
},
),
// Text(
// _searchProvider.searchResult.toString(),
// )
]),
),
),
);
}
}

View File

@ -1,13 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:dubp/dubp.dart'; import 'package:dubp/dubp.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:gecko/models/home.dart';
import 'package:gecko/models/my_wallets.dart'; import 'package:gecko/models/my_wallets.dart';
import 'package:gecko/screens/myWallets/generate_wallets.dart'; import 'package:gecko/screens/myWallets/generate_wallets.dart';
import 'dart:io'; import 'dart:io';
import 'package:gecko/screens/myWallets/import_wallet.dart'; import 'package:gecko/screens/myWallets/import_cesium_wallet.dart';
import 'package:gecko/globals.dart'; import 'package:gecko/globals.dart';
import 'package:provider/provider.dart';
// ignore: must_be_immutable // ignore: must_be_immutable
class SettingsScreen extends StatelessWidget { class SettingsScreen extends StatelessWidget {
@ -29,7 +27,6 @@ class SettingsScreen extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
HomeProvider _homeProvider = Provider.of<HomeProvider>(context);
// getAppDirectory(); // getAppDirectory();
return Scaffold( return Scaffold(
@ -94,9 +91,7 @@ class SettingsScreen extends StatelessWidget {
), ),
onPressed: () async => { onPressed: () async => {
log.i('Suppression de tous les wallets'), log.i('Suppression de tous les wallets'),
await _myWallets await _myWallets.deleteAllWallet(context)
.deleteAllWallet(context)
.then((v) => _homeProvider.rebuildWidget())
}, },
child: const Text("EFFACER TOUS MES PORTEFEUILLES", child: const Text("EFFACER TOUS MES PORTEFEUILLES",
style: TextStyle(fontSize: 20)))))), style: TextStyle(fontSize: 20)))))),

View File

@ -1,6 +1,5 @@
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:gecko/globals.dart'; import 'package:gecko/globals.dart';
import 'package:gecko/screens/home.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
// import 'package:gecko/models/home.dart'; // import 'package:gecko/models/home.dart';
// import 'package:provider/provider.dart'; // import 'package:provider/provider.dart';
@ -22,26 +21,6 @@ class TemplateScreen extends StatelessWidget {
height: 22, height: 22,
child: Text('Template screen'), child: Text('Template screen'),
)), )),
floatingActionButton: SizedBox(
height: 80.0,
width: 80.0,
child: FittedBox(
child: FloatingActionButton(
heroTag: "tplButton",
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return const HomeScreen();
}),
),
child: SizedBox(
height: 40.0,
width: 40.0,
child: Icon(Icons.home, color: Colors.grey[850]),
),
backgroundColor:
floattingYellow, //smoothYellow, //Color.fromARGB(500, 204, 255, 255),
))),
body: SafeArea( body: SafeArea(
child: Column(children: <Widget>[ child: Column(children: <Widget>[
const SizedBox(height: 20), const SizedBox(height: 20),
@ -58,30 +37,6 @@ class TemplateScreen extends StatelessWidget {
color: Colors.black, color: Colors.black,
fontWeight: FontWeight.w400)), fontWeight: FontWeight.w400)),
const SizedBox(height: 20), const SizedBox(height: 20),
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: yellowC, // background
onPrimary: Colors.black, // foreground
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return const HomeScreen();
}),
);
},
child: const Text('Retour Accueil',
style: TextStyle(fontSize: 20))),
const SizedBox(height: 20),
GestureDetector(
onTap: () {
Navigator.popUntil(
context,
ModalRoute.withName('/'),
);
},
child: const Icon(Icons.home))
]), ]),
)); ));
} }

View File

@ -0,0 +1,502 @@
import 'dart:ui';
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:flutter/material.dart';
import 'package:gecko/models/cesium_plus.dart';
import 'package:gecko/models/my_wallets.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/models/wallets_profiles.dart';
import 'package:gecko/models/queries.dart';
import 'package:gecko/screens/avatar_fullscreen.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/history.dart';
import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:provider/provider.dart';
class WalletViewScreen extends StatelessWidget {
const WalletViewScreen(
{@required this.pubkey, this.username, this.avatar, Key key})
: super(key: key);
final String pubkey;
final String username;
final Image avatar;
final double buttonSize = 100;
final double buttonFontSize = 18;
@override
Widget build(BuildContext context) {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
WalletsProfilesProvider _historyProvider =
Provider.of<WalletsProfilesProvider>(context, listen: false);
CesiumPlusProvider _cesiumPlusProvider =
Provider.of<CesiumPlusProvider>(context, listen: false);
return Scaffold(
resizeToAvoidBottomInset: true,
appBar: AppBar(
elevation: 0,
toolbarHeight: 60 * ratio,
title: const SizedBox(
height: 22,
child: Text('Voir un portefeuille'),
),
),
body: SafeArea(
child: Column(children: <Widget>[
headerProfileView(context, _historyProvider, _cesiumPlusProvider),
SizedBox(height: isTall ? 120 : 70),
Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [
Column(children: <Widget>[
SizedBox(
height: buttonSize,
child: ClipOval(
child: Material(
color: const Color(0xffFFD58D), // button color
child: InkWell(
key: const Key('viewHistory'),
splashColor: orangeC, // inkwell color
child: const Padding(
padding: EdgeInsets.all(13),
child: Image(
image: AssetImage(
'assets/walletOptions/clock.png'),
height: 90)),
onTap: () {
_historyProvider.nPage = 1;
Navigator.push(
context,
FaderTransition(
page: HistoryScreen(
pubkey: pubkey,
username: username ??
g1WalletsBox.get(pubkey)?.username,
avatar: avatar ??
g1WalletsBox.get(pubkey)?.avatar,
),
isFast: false),
);
}),
),
),
),
const SizedBox(height: 9),
Text(
"Voir\nl'historique",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: buttonFontSize, fontWeight: FontWeight.w500),
),
]),
Column(children: <Widget>[
SizedBox(
height: buttonSize,
child: ClipOval(
child: Material(
color: const Color(0xffFFD58D), // button color
child: InkWell(
key: const Key('copyKey'),
splashColor: orangeC, // inkwell color
child: const Padding(
padding: EdgeInsets.all(20),
child: Image(
image: AssetImage('assets/copy_key.png'),
height: 90)),
onTap: () {
Clipboard.setData(ClipboardData(text: pubkey));
_historyProvider.snackCopyKey(context);
}),
),
),
),
const SizedBox(height: 9),
Text(
"Copier\nla clef",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: buttonFontSize, fontWeight: FontWeight.w500),
),
]),
]),
// FutureBuilder(
// future: _walletOptions.generateQRcode(_historyProvider.pubkey),
// builder: (context, snapshot) {
// return snapshot.data != null
// ? GestureDetector(
// key: const Key('openQrcode'),
// onTap: () {
// Navigator.push(
// context,
// MaterialPageRoute(builder: (context) {
// return AvatarFullscreen(
// Image.memory(snapshot.data),
// title: 'QrCode du profil',
// color: Colors.white,
// );
// }),
// );
// },
// child: Image.memory(snapshot.data, height: 60 * ratio),
// )
// : const Text('-', style: TextStyle(fontSize: 20));
// },
// ),
const Spacer(),
Container(
height: buttonSize,
decoration: BoxDecoration(
color: const Color(0xff7c94b6),
borderRadius: const BorderRadius.all(Radius.circular(100)),
border: Border.all(
color: const Color(0xFF6c4204),
width: 4,
),
),
child: ClipOval(
child: Material(
color: orangeC, // button color
child: InkWell(
key: const Key('pay'),
splashColor: yellowC, // inkwell color
child: const Padding(
padding: EdgeInsets.all(14),
child: Image(
image: AssetImage('assets/vector_white.png'),
)),
onTap: () {
paymentPopup(context, _historyProvider);
}),
),
),
),
const SizedBox(height: 9),
Text(
"Faire un\nvirement",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: buttonFontSize, fontWeight: FontWeight.w500),
),
SizedBox(height: isTall ? 120 : 70)
]),
));
}
void paymentPopup(
BuildContext context, WalletsProfilesProvider _walletViewProvider) {
// WalletsProfilesProvider _walletViewProvider =
// Provider.of<WalletsProfilesProvider>(context);
const double shapeSize = 20;
MyWalletsProvider _myWalletProvider = MyWalletsProvider();
WalletData defaultWallet =
_myWalletProvider.getDefaultWallet(configBox.get('currentChest'));
showModalBottomSheet<void>(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topRight: Radius.circular(shapeSize),
topLeft: Radius.circular(shapeSize),
),
),
isScrollControlled: true,
context: context,
builder: (BuildContext context) {
return Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child: Container(
height: 400,
decoration: const ShapeDecoration(
color: Color(0xffffeed1),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topRight: Radius.circular(shapeSize),
topLeft: Radius.circular(shapeSize),
),
),
),
child: Padding(
padding: const EdgeInsets.all(24),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const Text(
'Effectuer un virement',
style: TextStyle(
fontSize: 26, fontWeight: FontWeight.w700),
),
const SizedBox(height: 20),
Text(
'Saisissez dans le champ ci-dessous le montant à virer de ... vers ...',
style: TextStyle(
fontSize: 19,
fontWeight: FontWeight.w500,
color: Colors.grey[600]),
),
const Spacer(),
Center(
child: Column(children: <Widget>[
TextField(
controller: _walletViewProvider.payAmount,
autofocus: true,
maxLines: 1,
textAlign: TextAlign.center,
keyboardType: TextInputType.number,
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.allow(
RegExp(r'^\d+\.?\d{0,2}')),
],
// onChanged: (v) => _searchProvider.rebuildWidget(),
decoration: InputDecoration(
hintText: '0.00',
suffix: const Text('DU/Ğ1'),
filled: true,
fillColor: Colors.transparent,
// border: OutlineInputBorder(
// borderSide:
// BorderSide(color: Colors.grey[500], width: 2),
// borderRadius: BorderRadius.circular(8)),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.grey[500], width: 2),
borderRadius: BorderRadius.circular(8),
),
contentPadding: const EdgeInsets.all(20),
),
style: const TextStyle(
fontSize: 40,
color: Colors.black,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 40),
// const Spacer(),
SizedBox(
width: double.infinity,
height: 60,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
elevation: 4,
primary: orangeC, // background
onPrimary: Colors.white, // foreground
),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return UnlockingWallet(
wallet: defaultWallet, action: "pay");
},
),
);
},
child: const Text(
'Effectuer le virement',
style: TextStyle(
fontSize: 20, fontWeight: FontWeight.w600),
),
),
),
const SizedBox(height: 20),
]),
),
]),
),
),
);
}).then((value) => _walletViewProvider.payAmount.text = '');
}
Widget headerProfileView(
BuildContext context,
WalletsProfilesProvider _historyProvider,
CesiumPlusProvider _cesiumPlusProvider) {
const double _avatarSize = 140;
return Column(children: <Widget>[
Container(
height: 10,
color: yellowC,
),
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
yellowC,
const Color(0xFFE7811A),
],
)),
child: Padding(
padding: const EdgeInsets.only(left: 30, right: 40),
child: Row(children: <Widget>[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(children: [
GestureDetector(
key: const Key('copyPubkey'),
onTap: () {
Clipboard.setData(ClipboardData(text: pubkey));
_historyProvider.snackCopyKey(context);
},
child: Text(
_historyProvider.getShortPubkey(pubkey),
style: const TextStyle(
fontSize: 30,
fontWeight: FontWeight.w800,
),
),
),
]),
const SizedBox(height: 10),
if (username == null &&
g1WalletsBox.get(pubkey)?.username == null)
Query(
options: QueryOptions(
document: gql(getId),
variables: {
'pubkey': pubkey,
},
),
builder: (QueryResult result,
{VoidCallback refetch, FetchMore fetchMore}) {
if (result.isLoading || result.hasException) {
return const Text('...');
} else if (result.data['idty'] == null ||
result.data['idty']['username'] == null) {
g1WalletsBox.get(pubkey)?.username = '';
return const Text('');
} else {
g1WalletsBox.get(pubkey)?.username =
result?.data['idty']['username'] ?? '';
return SizedBox(
width: 230,
child: Text(
result?.data['idty']['username'] ?? '',
style: const TextStyle(
fontSize: 27,
color: Color(0xff814C00),
),
),
);
}
},
),
if (username == null &&
g1WalletsBox.get(pubkey)?.username != null)
SizedBox(
width: 230,
child: Text(
g1WalletsBox.get(pubkey)?.username,
style: const TextStyle(
fontSize: 27,
color: Color(0xff814C00),
),
),
),
if (username != null)
SizedBox(
width: 230,
child: Text(
username,
style: const TextStyle(
fontSize: 27,
color: Color(0xff814C00),
),
),
),
const SizedBox(height: 25),
FutureBuilder(
future: _cesiumPlusProvider.getName(pubkey),
initialData: '...',
builder: (context, snapshot) {
return SizedBox(
width: 230,
child: Text(
snapshot.data ?? '-',
style: const TextStyle(
fontSize: 18, color: Colors.black),
),
);
}),
const SizedBox(height: 30),
]),
const Spacer(),
Column(children: <Widget>[
if (avatar == null)
FutureBuilder(
future: _cesiumPlusProvider.getAvatar(pubkey, _avatarSize),
builder:
(BuildContext context, AsyncSnapshot<Image> _avatar) {
if (_avatar.connectionState != ConnectionState.done) {
return Stack(children: [
ClipOval(
child:
_cesiumPlusProvider.defaultAvatar(_avatarSize),
),
Positioned(
top: 15,
right: 45,
width: 51,
height: 51,
child: CircularProgressIndicator(
strokeWidth: 5,
color: orangeC,
),
),
]);
}
if (_avatar.hasData) {
return GestureDetector(
key: const Key('openAvatar'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return AvatarFullscreen(_avatar.data);
}),
);
},
child: ClipOval(
child: Image(
image: _avatar.data.image,
height: _avatarSize,
fit: BoxFit.cover,
),
),
);
}
return ClipOval(
child: _cesiumPlusProvider.defaultAvatar(_avatarSize),
);
}),
if (avatar != null)
GestureDetector(
key: const Key('openAvatar'),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return AvatarFullscreen(avatar);
}),
);
},
child: ClipOval(
child: Image(
image: avatar.image,
height: _avatarSize,
fit: BoxFit.cover,
),
),
),
const SizedBox(height: 25),
]),
]),
),
),
]);
}
}

View File

@ -267,6 +267,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.5.6" version: "0.5.6"
dio:
dependency: "direct main"
description:
name: dio
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.4"
dubp: dubp:
dependency: "direct main" dependency: "direct main"
description: description:
@ -544,6 +551,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "2.4.1" version: "2.4.1"
infinite_scroll_pagination:
dependency: "direct main"
description:
name: infinite_scroll_pagination
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.0"
integration_test: integration_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
@ -878,6 +892,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.0" version: "1.1.0"
pull_to_refresh:
dependency: "direct main"
description:
name: pull_to_refresh
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
qr: qr:
dependency: transitive dependency: transitive
description: description:
@ -1002,6 +1023,13 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.99" version: "0.0.99"
sliver_tools:
dependency: transitive
description:
name: sliver_tools
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.5"
source_gen: source_gen:
dependency: transitive dependency: transitive
description: description:

View File

@ -5,13 +5,16 @@ description: Pay with G1.
# pub.dev using `pub publish`. This is preferred for private packages. # pub.dev using `pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 0.0.2+11 version: 0.0.3+13
environment: environment:
sdk: ">=2.7.0 <3.0.0" sdk: ">=2.7.0 <3.0.0"
dependencies: dependencies:
assorted_layout_widgets: ^5.2.1
bubble: ^1.2.1 bubble: ^1.2.1
carousel_slider: ^4.0.0
confirm_dialog: ^1.0.0
crypto: ^3.0.1 crypto: ^3.0.1
dubp: dubp:
path: packages/dubp_rs path: packages/dubp_rs
@ -21,14 +24,16 @@ dependencies:
flutter_driver: flutter_driver:
sdk: flutter sdk: flutter
flutter_launcher_icons: ^0.9.2 flutter_launcher_icons: ^0.9.2
flutter_lints: ^1.0.4
flutter_logs: ^2.1.4 flutter_logs: ^2.1.4
flutter_svg: ^0.22.0 flutter_svg: ^0.22.0
graphql_flutter: ^5.0.0 graphql_flutter: ^5.0.0
hive: ^2.0.4 hive: ^2.0.4
hive_flutter: ^1.1.0 hive_flutter: ^1.1.0
http: ^0.13.0 http: ^0.13.4
image_gallery_saver: ^1.6.9 image_gallery_saver: ^1.6.9
image_picker: ^0.8.4 image_picker: ^0.8.4
infinite_scroll_pagination: ^3.1.0
intl: ^0.17.0 intl: ^0.17.0
jdenticon_dart: ^2.0.0 jdenticon_dart: ^2.0.0
logger: ^1.1.0 logger: ^1.1.0
@ -38,7 +43,7 @@ dependencies:
permission_handler: 8.1.6 permission_handler: 8.1.6
pin_code_fields: ^7.3.0 pin_code_fields: ^7.3.0
printing: ^5.6.0 printing: ^5.6.0
provider: ^6.0.0 provider: ^6.0.1
qrscan: ^0.3.2 qrscan: ^0.3.2
responsive_builder: ^0.4.1 responsive_builder: ^0.4.1
responsive_framework: ^0.1.4 responsive_framework: ^0.1.4
@ -48,15 +53,11 @@ dependencies:
super_tooltip: ^1.0.1 super_tooltip: ^1.0.1
sync_http: ^0.3.0 sync_http: ^0.3.0
test: ^1.17.10 test: ^1.17.10
# test_api: ^0.4.7
# test: ^1.19.3
truncate: ^3.0.1 truncate: ^3.0.1
unorm_dart: ^0.2.0 unorm_dart: ^0.2.0
xml: ^5.3.0 xml: ^5.3.0
assorted_layout_widgets: ^5.2.1 pull_to_refresh: ^2.0.0
carousel_slider: ^4.0.0 dio: ^4.0.4
flutter_lints: ^1.0.4
confirm_dialog: ^1.0.0
flutter_icons: flutter_icons:
android: "ic_launcher" android: "ic_launcher"
@ -65,12 +66,12 @@ flutter_icons:
cupertino_icons: ^1.0.0 cupertino_icons: ^1.0.0
dev_dependencies: dev_dependencies:
build_runner: ^2.1.2
flutter_test: flutter_test:
sdk: flutter sdk: flutter
hive_generator: ^1.1.1
integration_test: integration_test:
sdk: flutter sdk: flutter
hive_generator: ^1.1.1
build_runner: ^2.1.2
# The following section is specific to Flutter. # The following section is specific to Flutter.
flutter: flutter:
@ -80,6 +81,7 @@ flutter:
- images/ - images/
- config/gva_endpoints.json - config/gva_endpoints.json
- assets/ - assets/
- assets/home/
- assets/customs/ - assets/customs/
- assets/avatars/ - assets/avatars/
- assets/chests/ - assets/chests/

View File

@ -20,8 +20,8 @@ if [[ $1 == "bundle" ]]; then
flutter build appbundle --release --target-platform android-arm,android-arm64 --build-name $VERSION --build-number $BUILD flutter build appbundle --release --target-platform android-arm,android-arm64 --build-name $VERSION --build-number $BUILD
else else
# flutter build apk --release --split-per-abi --target-platform android-arm,android-arm64 --build-name $VERSION --build-number $BUILD # flutter build apk --release --split-per-abi --target-platform android-arm,android-arm64 --build-name $VERSION --build-number $BUILD
# flutter build apk --release --split-per-abi --build-name $VERSION --build-number $BUILD flutter build apk --release --split-per-abi --build-name $VERSION --build-number $BUILD
flutter build apk --release --build-name $VERSION --build-number $BUILD # flutter build apk --release --build-name $VERSION --build-number $BUILD
fi fi
if [[ -d $HOME/Téléchargements ]]; then if [[ -d $HOME/Téléchargements ]]; then

View File

@ -217,8 +217,9 @@ void main() {
{timeout = Timeout.none}) async { {timeout = Timeout.none}) async {
expect(await getText('step9'), expect(await getText('step9'),
"Super !\n\nJe vais maintenant créer votre code secret. \n\nVotre code secret chiffre votre trousseau de clefs, ce qui le rend inutilisable par dautres, par exemple si vous perdez votre téléphone ou si on vous le vole."); "Super !\n\nJe vais maintenant créer votre code secret. \n\nVotre code secret chiffre votre trousseau de clefs, ce qui le rend inutilisable par dautres, par exemple si vous perdez votre téléphone ou si on vous le vole.");
await sleep(800);
await tapOn('goStep10'); await tapOn('goStep10');
await sleep(50);
await tapOn('goStep11'); await tapOn('goStep11');
while (await getText('generatedPin') == '') { while (await getText('generatedPin') == '') {