UX: global improvements

This commit is contained in:
poka 2022-12-10 06:09:05 +01:00
parent 3ba04470f9
commit 26cc024b87
16 changed files with 317 additions and 293 deletions

BIN
assets/party.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -203,5 +203,7 @@
"sent": "Sent",
"createIdentity": "Create a new \nidentity",
"memberAccountOf": "Account of {}",
"pasteAddress": "Paste address from\nclipboard"
"pasteAddress": "Paste address from\nclipboard",
"historyStart" :"Beginning of history",
"blockchainStart": "Beginning of the ĞDev"
}

View File

@ -204,5 +204,7 @@
"sent": "Sent",
"createIdentity": "Create a new \nidentity",
"memberAccountOf": "Account of {}",
"pasteAddress": "Paste address from\nclipboard"
"pasteAddress": "Paste address from\nclipboard",
"historyStart" :"Beginning of history",
"blockchainStart": "Comienzo de la ĞDev"
}

View File

@ -204,5 +204,7 @@
"sent": "Envoyés",
"createIdentity": "Créer sa nouvelle\nidentité",
"memberAccountOf": "Compte de {}",
"pasteAddress": "Coller l'adresse depuis\nle presse-papier"
"pasteAddress": "Coller l'adresse depuis\nle presse-papier",
"historyStart" :"Début de l'historique",
"blockchainStart": "Début de la ĞDev"
}

View File

@ -57,17 +57,17 @@ late DateTime startBlockchainTime;
late int currentUdIndex;
final Map<int, String> monthsInYear = {
1: "month1".tr(),
2: "month2".tr(),
3: "month3".tr(),
4: "month4".tr(),
5: "month5".tr(),
6: "month6".tr(),
7: "month7".tr(),
8: "month8".tr(),
9: "month9".tr(),
10: "month10".tr(),
11: "month11".tr(),
12: "month12".tr()
};
final Map<int, String> monthsInYear = {
1: "month1".tr(),
2: "month2".tr(),
3: "month3".tr(),
4: "month4".tr(),
5: "month5".tr(),
6: "month6".tr(),
7: "month7".tr(),
8: "month8".tr(),
9: "month9".tr(),
10: "month10".tr(),
11: "month11".tr(),
12: "month12".tr()
};

View File

@ -264,9 +264,9 @@ Map computeHistoryView(repository, lastDateDelimiter, isDouble) {
bool isDelimiter = true;
if ({4, 10, 11, 12}.contains(date.month)) {
dateForm = "${date.day} ${monthsInYear[date.month]!.substring(0, 3)}.";
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)}.";
dateForm = "${date.day} ${monthsInYear[date.month]!.substring(0, 4)}";
} else {
dateForm = "${date.day} ${monthsInYear[date.month]}";
}

View File

@ -1,6 +1,7 @@
import 'dart:math';
import 'package:durt/durt.dart' as durt;
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
@ -88,8 +89,7 @@ class GenerateWalletsProvider with ChangeNotifier {
log.i("Is $expectedWord equal to input $normInputWord ?");
if (expectedWord == normInputWord ||
inputWord == 'triche' ||
inputWord == '3.14') {
(kDebugMode && inputWord == 'triche')) {
log.d('Word is OK');
isAskedWordValid = true;
askedWordColor = Colors.green[600];

View File

@ -3,43 +3,22 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/queries_indexer.dart';
import 'package:gecko/models/widgets_keys.dart';
import 'package:gecko/providers/duniter_indexer.dart';
import 'package:flutter/material.dart';
import 'package:gecko/widgets/bottom_app_bar.dart';
import 'package:gecko/widgets/header_profile.dart';
import 'package:gecko/widgets/transaction_tile.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:provider/provider.dart';
import 'package:gecko/widgets/history_query.dart';
class ActivityScreen extends StatefulWidget with ChangeNotifier {
class ActivityScreen extends StatelessWidget with ChangeNotifier {
ActivityScreen({required this.address, required this.avatar, this.username})
: super(key: keyActivityScreen);
final String address;
final String? username;
final Image avatar;
@override
State<ActivityScreen> createState() => _ActivityScreenState();
}
class _ActivityScreenState extends State<ActivityScreen> {
// @override
// void initState() {
// super.initState();
// }
final ScrollController scrollController = ScrollController();
final double avatarsSize = 80;
FetchMore? fetchMore;
FetchMoreOptions? opts;
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
elevation: 0,
toolbarHeight: 60 * ratio,
@ -50,212 +29,8 @@ class _ActivityScreenState extends State<ActivityScreen> {
),
bottomNavigationBar: const GeckoBottomAppBar(),
body: Column(children: <Widget>[
HeaderProfile(address: widget.address, username: widget.username),
historyQuery(context),
HeaderProfile(address: address, username: username),
HistoryQuery(address: address),
]));
}
Widget historyQuery(context) {
final duniterIndexer = Provider.of<DuniterIndexer>(context, listen: false);
int nPage = 1;
int nRepositories = 20;
if (indexerEndpoint == '') {
return Column(children: <Widget>[
const SizedBox(height: 50),
Text(
"noNetworkNoHistory".tr(),
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 18),
)
]);
}
final httpLink = HttpLink(
'$indexerEndpoint/v1beta1/relay',
);
final client = ValueNotifier(
GraphQLClient(
cache: GraphQLCache(),
link: httpLink,
),
);
return GraphQLProvider(
client: client,
child: Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Query(
options: QueryOptions(
document: gql(getHistoryByAddressQ),
variables: <String, dynamic>{
'address': widget.address,
'number': 20,
'cursor': null
},
),
builder: (QueryResult result, {fetchMore, refetch}) {
if (result.isLoading && result.data == null) {
return const Center(
child: CircularProgressIndicator(
color: orangeC,
),
);
}
if (result.hasException) {
log.e('Error Indexer: ${result.exception}');
return Column(children: <Widget>[
const SizedBox(height: 50),
Text(
"noNetworkNoHistory".tr(),
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 18),
)
]);
} else if (result
.data?['transaction_connection']?['edges'].isEmpty) {
return Column(children: <Widget>[
const SizedBox(height: 50),
Text(
"noDataToDisplay".tr(),
style: const TextStyle(fontSize: 18),
)
]);
}
if (result.isNotLoading) {
if (duniterIndexer.fetchMoreCursor == null) nPage = 1;
// log.d('nPage: $nPage');
if (nPage <= 3) {
nRepositories = 20;
} else if (nPage <= 6) {
nRepositories = 40;
} else if (nPage <= 12) {
nRepositories = 80;
} else {
nRepositories = 120;
}
nPage++;
opts = duniterIndexer.mergeQueryResult(
result, opts, widget.address, nRepositories);
}
// Build history list
return NotificationListener(
child: Builder(
builder: (context) => Expanded(
child: ListView(
key: keyListTransactions,
controller: scrollController,
children: <Widget>[historyView(context, result)],
),
),
),
onNotification: (dynamic t) {
if (t is ScrollEndNotification &&
scrollController.position.pixels >=
scrollController.position.maxScrollExtent * 0.7 &&
duniterIndexer.pageInfo!['hasNextPage'] &&
result.isNotLoading) {
fetchMore!(opts!);
}
return true;
});
},
),
],
)),
);
}
Widget historyView(context, result) {
final duniterIndexer = Provider.of<DuniterIndexer>(context, listen: false);
int keyID = 0;
const double avatarSize = 200;
String? lastDateDelimiter;
bool? isDouble;
bool isMigrationPassed = false;
return duniterIndexer.transBC == null
? Column(children: <Widget>[
const SizedBox(height: 50),
Text(
"noTransactionToDisplay".tr(),
style: const TextStyle(fontSize: 18),
)
])
: Column(children: <Widget>[
Column(
children: duniterIndexer.transBC!.map((repository) {
final answer =
computeHistoryView(repository, lastDateDelimiter, isDouble);
isDouble = lastDateDelimiter == answer['dateDelimiter'] ||
answer['dateDelimiter'] == '';
lastDateDelimiter = answer['dateDelimiter'];
bool isMigrationTime = false;
if (answer['isMigrationTime'] && !isMigrationPassed) {
isMigrationPassed = true;
isMigrationTime = true;
}
return Column(children: <Widget>[
if (isMigrationTime)
const Padding(
padding: EdgeInsets.symmetric(vertical: 30),
child: Text(
'Début de la ĞDev',
style: TextStyle(
fontSize: 25,
color: Colors.blueAccent,
fontWeight: FontWeight.w500),
),
),
if (!isDouble!)
Padding(
padding: const EdgeInsets.symmetric(vertical: 30),
child: Text(
answer['dateDelimiter'],
style: const TextStyle(
fontSize: 23,
color: orangeC,
fontWeight: FontWeight.w300),
),
),
TransactionTile(
widget: widget,
keyID: keyID,
avatarSize: avatarSize,
repository: repository,
dateForm: answer['dateForm'],
finalAmount: answer['finalAmount'],
duniterIndexer: duniterIndexer,
context: context),
]);
}).toList()),
if (result.isLoading && duniterIndexer.pageInfo!['hasPreviousPage'])
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[
CircularProgressIndicator(),
],
),
if (!duniterIndexer.pageInfo!['hasNextPage'])
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

@ -11,7 +11,6 @@ import 'package:gecko/providers/chest_provider.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/myWallets/change_pin.dart';
import 'package:gecko/screens/myWallets/custom_derivations.dart';
import 'package:gecko/screens/myWallets/show_seed.dart';
import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
@ -106,26 +105,27 @@ class ChestOptions extends StatelessWidget {
Consumer<SubstrateSdk>(builder: (context, sub, _) {
return InkWell(
key: keyChangePin,
onTap: sub.nodeConnected
? () async {
// await _chestProvider.changePin(context, cesiumWallet);
String? pinResult = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return ChangePinScreen(
walletName: currentChest.name,
walletProvider: walletProvider,
);
},
),
);
onTap: null,
// sub.nodeConnected
// ? () async {
// // await _chestProvider.changePin(context, cesiumWallet);
// String? pinResult = await Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) {
// return ChangePinScreen(
// walletName: currentChest.name,
// walletProvider: walletProvider,
// );
// },
// ),
// );
if (pinResult != null) {
walletProvider.pinCode = pinResult;
}
}
: null,
// if (pinResult != null) {
// walletProvider.pinCode = pinResult;
// }
// }
// : null,
child: SizedBox(
height: 50,
child: Row(children: <Widget>[
@ -140,7 +140,7 @@ class ChestOptions extends StatelessWidget {
style: TextStyle(
fontSize: 20,
color: sub.nodeConnected
? Colors.black
? Colors.grey[500]
: Colors.grey[500]),
),
])),

View File

@ -14,7 +14,6 @@ import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/providers/wallet_options.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:gecko/screens/myWallets/chest_options.dart';
import 'package:gecko/screens/myWallets/choose_chest.dart';
import 'package:gecko/screens/myWallets/import_g1_v1.dart';
import 'package:gecko/screens/myWallets/unlocking_wallet.dart';
import 'package:gecko/screens/myWallets/wallet_options.dart';
@ -183,22 +182,23 @@ class WalletsHome extends StatelessWidget {
const SizedBox(height: 20),
InkWell(
key: keyChangeChest,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) {
return const ChooseChest();
}),
);
},
onTap: null,
// () {
// Navigator.push(
// context,
// MaterialPageRoute(builder: (context) {
// return const ChooseChest();
// }),
// );
// },
child: SizedBox(
width: 400,
height: 60,
child: Center(
child: Text('changeChest'.tr(),
style: const TextStyle(
style: TextStyle(
fontSize: 22,
color: orangeC,
color: Colors.grey[500],
fontWeight: FontWeight.w500))),
),
),

View File

@ -72,6 +72,12 @@ class OnboardingStepNine extends StatelessWidget {
),
],
),
const SizedBox(height: 30),
Text(
'Pendant la phase de test de Ğecko,\nles codes secrets\nsont systématiquement AAAAA.'
.tr(),
style: TextStyle(color: Colors.grey[700], fontSize: 15),
textAlign: TextAlign.center),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,

View File

@ -0,0 +1,233 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/queries_indexer.dart';
import 'package:gecko/models/widgets_keys.dart';
import 'package:gecko/providers/duniter_indexer.dart';
import 'package:gecko/widgets/transaction_tile.dart';
import 'package:graphql_flutter/graphql_flutter.dart';
import 'package:provider/provider.dart';
class HistoryQuery extends StatelessWidget {
const HistoryQuery({Key? key, required this.address}) : super(key: key);
final String address;
@override
Widget build(BuildContext context) {
final duniterIndexer = Provider.of<DuniterIndexer>(context, listen: false);
final ScrollController scrollController = ScrollController();
FetchMoreOptions? opts;
int nPage = 1;
int nRepositories = 20;
if (indexerEndpoint == '') {
return Column(children: <Widget>[
const SizedBox(height: 50),
Text(
"noNetworkNoHistory".tr(),
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 18),
)
]);
}
final httpLink = HttpLink(
'$indexerEndpoint/v1beta1/relay',
);
final client = ValueNotifier(
GraphQLClient(
cache: GraphQLCache(),
link: httpLink,
),
);
return GraphQLProvider(
client: client,
child: Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Query(
options: QueryOptions(
document: gql(getHistoryByAddressQ),
variables: <String, dynamic>{
'address': address,
'number': 20,
'cursor': null
},
),
builder: (QueryResult result, {fetchMore, refetch}) {
if (result.isLoading && result.data == null) {
return const Center(
child: CircularProgressIndicator(
color: orangeC,
),
);
}
if (result.hasException) {
log.e('Error Indexer: ${result.exception}');
return Column(children: <Widget>[
const SizedBox(height: 50),
Text(
"noNetworkNoHistory".tr(),
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 18),
)
]);
} else if (result
.data?['transaction_connection']?['edges'].isEmpty) {
return Column(children: <Widget>[
const SizedBox(height: 50),
Text(
"noDataToDisplay".tr(),
style: const TextStyle(fontSize: 18),
)
]);
}
if (result.isNotLoading) {
if (duniterIndexer.fetchMoreCursor == null) nPage = 1;
// log.d('nPage: $nPage');
if (nPage <= 3) {
nRepositories = 20;
} else if (nPage <= 6) {
nRepositories = 40;
} else if (nPage <= 12) {
nRepositories = 80;
} else {
nRepositories = 120;
}
nPage++;
opts = duniterIndexer.mergeQueryResult(
result, opts, address, nRepositories);
}
// Build history list
return NotificationListener(
child: Builder(
builder: (context) => Expanded(
child: ListView(
key: keyListTransactions,
controller: scrollController,
children: <Widget>[historyView(context, result)],
),
),
),
onNotification: (dynamic t) {
if (t is ScrollEndNotification &&
scrollController.position.pixels >=
scrollController.position.maxScrollExtent * 0.7 &&
duniterIndexer.pageInfo!['hasNextPage'] &&
result.isNotLoading) {
fetchMore!(opts!);
}
return true;
});
},
),
],
)),
);
}
Widget historyView(context, result) {
final duniterIndexer = Provider.of<DuniterIndexer>(context, listen: false);
int keyID = 0;
const double avatarSize = 200;
String? lastDateDelimiter;
bool? isDouble;
bool isMigrationPassed = false;
return duniterIndexer.transBC == null
? Column(children: <Widget>[
const SizedBox(height: 50),
Text(
"noTransactionToDisplay".tr(),
style: const TextStyle(fontSize: 18),
)
])
: Column(children: <Widget>[
Column(
children: duniterIndexer.transBC!.map((repository) {
final answer =
computeHistoryView(repository, lastDateDelimiter, isDouble);
isDouble = lastDateDelimiter == answer['dateDelimiter'] ||
answer['dateDelimiter'] == '';
lastDateDelimiter = answer['dateDelimiter'];
bool isMigrationTime = false;
if (answer['isMigrationTime'] && !isMigrationPassed) {
isMigrationPassed = true;
isMigrationTime = true;
}
return Column(children: <Widget>[
if (isMigrationTime)
Padding(
padding: const EdgeInsets.symmetric(vertical: 30),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Image(
image: AssetImage('assets/party.png'), height: 40),
const SizedBox(width: 40),
Text(
'blockchainStart'.tr(),
style: const TextStyle(
fontSize: 25,
color: Colors.blueAccent,
fontWeight: FontWeight.w500),
),
const SizedBox(width: 40),
const Image(
image: AssetImage('assets/party.png'), height: 40),
],
),
),
if (!isDouble!)
Padding(
padding: const EdgeInsets.symmetric(vertical: 30),
child: Text(
answer['dateDelimiter'],
style: const TextStyle(
fontSize: 23,
color: orangeC,
fontWeight: FontWeight.w300),
),
),
TransactionTile(
keyID: keyID,
avatarSize: avatarSize,
repository: repository,
dateForm: answer['dateForm'],
finalAmount: answer['finalAmount'],
duniterIndexer: duniterIndexer,
context: context),
]);
}).toList()),
if (result.isLoading && duniterIndexer.pageInfo!['hasPreviousPage'])
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[
CircularProgressIndicator(),
],
),
if (!duniterIndexer.pageInfo!['hasNextPage'])
Column(
children: <Widget>[
const SizedBox(height: 15),
Text("historyStart".tr(),
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 20)),
const SizedBox(height: 15)
],
)
]);
}
}

View File

@ -115,6 +115,7 @@ class SearchIdentityQuery extends StatelessWidget {
dense: false,
isThreeLine: false,
onTap: () {
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(builder: (context) {

View File

@ -93,6 +93,7 @@ class SearchResult extends StatelessWidget {
dense: false,
isThreeLine: false,
onTap: () {
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(builder: (context) {

View File

@ -3,14 +3,12 @@ import 'package:gecko/models/widgets_keys.dart';
import 'package:gecko/providers/cesium_plus.dart';
import 'package:gecko/providers/duniter_indexer.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/screens/activity.dart';
import 'package:gecko/screens/wallet_view.dart';
import 'package:gecko/widgets/page_route_no_transition.dart';
class TransactionTile extends StatelessWidget {
const TransactionTile({
Key? key,
required this.widget,
required this.keyID,
required this.avatarSize,
required this.repository,
@ -20,7 +18,6 @@ class TransactionTile extends StatelessWidget {
required this.context,
}) : super(key: key);
final ActivityScreen widget;
final int keyID;
final double avatarSize;
final List repository;
@ -49,7 +46,7 @@ class TransactionTile extends StatelessWidget {
subtitle: RichText(
text: TextSpan(
style: TextStyle(
fontSize: 16,
fontSize: 17,
color: Colors.grey[700],
),
children: <TextSpan>[
@ -60,22 +57,27 @@ class TransactionTile extends StatelessWidget {
TextSpan(
text: ' · ',
style: TextStyle(
fontSize: 20,
fontSize: 25,
color: Colors.grey[550],
),
),
TextSpan(
text: repository[2],
style: TextStyle(
fontStyle: FontStyle.italic,
color: Colors.grey[600],
),
fontStyle: FontStyle.italic,
color: Colors.grey[600],
fontSize: 19),
),
],
),
),
trailing: Text(finalAmount,
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w500),
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w500,
color: repository[4] == 'RECEIVED'
? Colors.green[700]
: Colors.blue[700]),
textAlign: TextAlign.justify),
dense: false,
isThreeLine: false,
@ -85,7 +87,7 @@ class TransactionTile extends StatelessWidget {
PageNoTransit(builder: (context) {
return WalletViewScreen(
address: repository[1],
username: widget.username ?? '',
username: repository[2] ?? '',
);
}),
);

View File

@ -5,7 +5,7 @@ description: Pay with G1.
# 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
version: 0.0.15+48
version: 0.0.15+50
environment:
sdk: '>=2.12.0 <3.0.0'