Persitents profiles images; bugs fix; balances on wallets_home

This commit is contained in:
poka 2022-05-28 19:13:30 +02:00
parent df84eb7a48
commit f535bea932
15 changed files with 203 additions and 194 deletions

View File

@ -24,6 +24,7 @@ late Box<ChestData> chestBox;
late Box configBox;
late Box<G1WalletsList> g1WalletsBox;
// late Box keystoreBox;
late Directory imageDirectory;
// String cesiumPod = "https://g1.data.le-sou.org";
String cesiumPod = "https://g1.data.presles.fr";

View File

@ -1,4 +1,3 @@
import 'dart:io';
import 'package:hive_flutter/hive_flutter.dart';
part 'wallet_data.g.dart';
@ -23,10 +22,10 @@ class WalletData extends HiveObject {
int? derivation;
@HiveField(6)
String? imageName;
String? imageDefaultPath;
@HiveField(7)
File? imageFile;
String? imageCustomPath;
WalletData(
{this.version,
@ -35,8 +34,8 @@ class WalletData extends HiveObject {
this.number,
this.name,
this.derivation,
this.imageName,
this.imageFile});
this.imageDefaultPath,
this.imageCustomPath});
// representation of WalletData when debugging
@override
@ -46,7 +45,7 @@ class WalletData extends HiveObject {
// creates the ':'-separated string from the WalletData
String inLine() {
return "$chest:$number:$name:$derivation:$imageName";
return "$chest:$number:$name:$derivation:$imageDefaultPath";
}
// returns only the id part of the ':'-separated string

View File

@ -23,8 +23,8 @@ class WalletDataAdapter extends TypeAdapter<WalletData> {
number: fields[3] as int?,
name: fields[4] as String?,
derivation: fields[5] as int?,
imageName: fields[6] as String?,
imageFile: fields[7] as File?,
imageDefaultPath: fields[6] as String?,
imageCustomPath: fields[7] as String?,
);
}
@ -45,9 +45,9 @@ class WalletDataAdapter extends TypeAdapter<WalletData> {
..writeByte(5)
..write(obj.derivation)
..writeByte(6)
..write(obj.imageName)
..write(obj.imageDefaultPath)
..writeByte(7)
..write(obj.imageFile);
..write(obj.imageCustomPath);
}
@override

View File

@ -87,7 +87,7 @@ class GenerateWalletsProvider with ChangeNotifier {
number: 0,
name: _name,
derivation: 2,
imageName: '0.png');
imageDefaultPath: '0.png');
await walletBox.add(myWallet);
await configBox.put('currentChest', chestKey);

View File

@ -16,6 +16,7 @@ import 'package:hive_flutter/hive_flutter.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:path_provider/path_provider.dart' as pp;
import 'package:package_info_plus/package_info_plus.dart';
import 'package:path_provider/path_provider.dart';
import 'package:provider/provider.dart';
class HomeProvider with ChangeNotifier {
@ -47,6 +48,14 @@ class HomeProvider with ChangeNotifier {
} else {
await Hive.initFlutter();
}
// Init app folders
final documentDir = await getApplicationDocumentsDirectory();
imageDirectory = Directory('${documentDir.path}/images');
if (!await imageDirectory.exists()) {
await imageDirectory.create();
}
}
Future<String> getAppVersion() async {

View File

@ -4,6 +4,7 @@ import 'package:gecko/globals.dart';
import 'package:gecko/models/chest_data.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:provider/provider.dart';
class MyWalletsProvider with ChangeNotifier {
@ -11,6 +12,7 @@ class MyWalletsProvider with ChangeNotifier {
late String pinCode;
late String mnemonic;
int? pinLenght;
bool isNewDerivationLoading = false;
int? getCurrentChest() {
if (configBox.get('currentChest') == null) {
@ -71,7 +73,8 @@ class MyWalletsProvider with ChangeNotifier {
try {
log.w('DELETE ALL WALLETS ?');
final bool? _answer = await (_confirmDeletingAllWallets(context));
final bool? _answer = await (confirmPopop(
context, 'Êtes-vous sûr de vouloir oublier tous vos coffres ?'));
if (_answer!) {
await walletBox.clear();
await chestBox.clear();
@ -88,58 +91,13 @@ class MyWalletsProvider with ChangeNotifier {
}
}
Future<bool?> _confirmDeletingAllWallets(context) async {
return showDialog<bool>(
context: context,
barrierDismissible: true, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
backgroundColor: backgroundColor,
content: const Text(
'Êtes-vous sûr de vouloir oublier tous vos coffres ?',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18, fontWeight: FontWeight.w500),
),
actions: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextButton(
key: const Key('confirmDeletingAllWallets'),
child: const Text(
"Oui",
style: TextStyle(
fontSize: 20,
color: Color(0xffD80000),
),
),
onPressed: () {
Navigator.pop(context, true);
},
),
const SizedBox(width: 20),
TextButton(
child: const Text(
"Non",
style: TextStyle(fontSize: 20),
),
onPressed: () {
Navigator.pop(context, false);
},
),
const SizedBox(height: 120)
],
)
],
);
},
);
}
Future<void> generateNewDerivation(context, String _name) async {
isNewDerivationLoading = true;
notifyListeners();
int _newDerivationNbr;
int _newWalletNbr;
int? _chest = getCurrentChest();
List<WalletData> _walletConfig = readAllWallets(_chest);
if (_walletConfig.isEmpty) {
@ -168,10 +126,11 @@ class MyWalletsProvider with ChangeNotifier {
number: _newWalletNbr,
name: _name,
derivation: _newDerivationNbr,
imageName: '${_newWalletNbr % 4}.png');
imageDefaultPath: '${_newWalletNbr % 4}.png');
await walletBox.add(newWallet);
isNewDerivationLoading = false;
notifyListeners();
}

View File

@ -5,6 +5,7 @@ import 'package:gecko/globals.dart';
import 'package:gecko/providers/my_wallets.dart';
import 'package:gecko/models/wallet_data.dart';
import 'package:gecko/providers/substrate_sdk.dart';
import 'package:gecko/screens/common_elements.dart';
import 'package:image_picker/image_picker.dart';
import 'package:provider/provider.dart';
@ -57,7 +58,8 @@ class WalletOptionsProvider with ChangeNotifier {
}
Future<int> deleteWallet(context, WalletData wallet) async {
final bool? _answer = await (_confirmDeletingWallet(context, wallet.name));
final bool? _answer = await (confirmPopop(context,
'Êtes-vous sûr de vouloir oublier le portefeuille "${wallet.name}" ?'));
if (_answer!) {
await walletBox.delete(wallet.key);
@ -71,61 +73,40 @@ class WalletOptionsProvider with ChangeNotifier {
return 0;
}
Future<bool?> _confirmDeletingWallet(context, _walletName) async {
return showDialog<bool>(
context: context,
barrierDismissible: true, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: Text(
'Êtes-vous sûr de vouloir supprimer le portefeuille "$_walletName" ?'),
content: SingleChildScrollView(
child: ListBody(
children: const <Widget>[
Text('Vous pourrez restaurer ce portefeuille plus tard.'),
],
),
),
actions: <Widget>[
TextButton(
child: const Text("Non", key: Key('cancelDeleting')),
onPressed: () {
Navigator.pop(context, false);
},
),
TextButton(
child: const Text("Oui", key: Key('confirmDeleting')),
onPressed: () {
Navigator.pop(context, true);
},
),
],
);
},
);
}
void bluringBalance() {
isBalanceBlur = !isBalanceBlur;
notifyListeners();
}
Future changeAvatar() async {
File _image;
Future<String> changeAvatar() async {
// File _image;
final picker = ImagePicker();
XFile? pickedFile = await picker.pickImage(source: ImageSource.gallery);
if (pickedFile != null) {
_image = File(pickedFile.path);
////TODO: Store image on disk, store path in walletBox.imagePath
log.i(pickedFile.path);
return _image;
File imageFile = File(pickedFile.path);
if (!await imageDirectory.exists()) {
log.e("Image folder doesn't exist");
return '';
}
final newPath = "${imageDirectory.path}/${pickedFile.name}";
await imageFile.copy(newPath);
// final File newImage = File(newPath);
// await newImage.writeAsBytes(await pickedFile.readAsBytes());
// await pickedFile.saveTo(newPath);
// await Future.delayed(const Duration(milliseconds: 100));
log.i(newPath);
return newPath;
} else {
log.w('No image selected.');
return null;
return '';
}
}
@ -269,7 +250,8 @@ class WalletOptionsProvider with ChangeNotifier {
Map<String, String> balanceCache = {};
Widget balance(BuildContext context, String address, double size) {
Widget balance(BuildContext context, String address, double size,
[Color _color = Colors.black]) {
return Column(children: <Widget>[
Consumer<SubstrateSdk>(builder: (context, _sdk, _) {
return FutureBuilder(
@ -280,8 +262,7 @@ Widget balance(BuildContext context, String address, double size) {
if (balanceCache[address] != null) {
return Text(balanceCache[address]!,
style: TextStyle(
fontSize: isTall ? size : size * 0.9,
));
fontSize: isTall ? size : size * 0.9, color: _color));
} else {
return SizedBox(
height: 15,
@ -298,6 +279,7 @@ Widget balance(BuildContext context, String address, double size) {
balanceCache[address]!,
style: TextStyle(
fontSize: isTall ? size : size * 0.9,
color: _color,
),
);
});

View File

@ -192,6 +192,54 @@ class FaderTransition extends PageRouteBuilder {
);
}
Future<bool?> confirmPopop(BuildContext context, String title) async {
return showDialog<bool>(
context: context,
barrierDismissible: true, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
backgroundColor: backgroundColor,
content: Text(
title,
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
),
actions: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextButton(
key: const Key('confirmPopop'),
child: const Text(
"Oui",
style: TextStyle(
fontSize: 21,
color: Color(0xffD80000),
),
),
onPressed: () {
Navigator.pop(context, true);
},
),
const SizedBox(width: 20),
TextButton(
child: const Text(
"Non",
style: TextStyle(fontSize: 21),
),
onPressed: () {
Navigator.pop(context, false);
},
),
const SizedBox(height: 120)
],
)
],
);
},
);
}
// Widget geckoAppBar() {
// return AppBar(
// toolbarHeight: 60 * ratio,

View File

@ -152,14 +152,14 @@ class ChooseWalletScreen extends StatelessWidget {
const Color(0xFFE7E7A6),
],
)),
child: _repository.imageFile == null
child: _repository.imageCustomPath == null
? Image.asset(
'assets/avatars/${_repository.imageName}',
'assets/avatars/${_repository.imageDefaultPath}',
alignment: Alignment.bottomCenter,
scale: 0.5,
)
: Image.file(
_repository.imageFile!,
: Image.asset(
_repository.imageCustomPath!,
alignment: Alignment.bottomCenter,
scale: 0.5,
),

View File

@ -189,7 +189,7 @@ class UnlockingWallet extends StatelessWidget {
enableActiveFill: false,
errorAnimationController: errorController,
controller: _enterPin,
keyboardType: TextInputType.text,
keyboardType: TextInputType.visiblePassword,
boxShadows: const [
BoxShadow(
offset: Offset(0, 1),

View File

@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/chest_data.dart';
@ -42,6 +43,7 @@ class WalletOptions extends StatelessWidget {
onWillPop: () {
_walletOptions.isEditing = false;
_walletOptions.isBalanceBlur = false;
_myWalletProvider.rebuildWidget();
Navigator.pop(context);
return Future<bool>.value(true);
},
@ -55,13 +57,14 @@ class WalletOptions extends StatelessWidget {
onPressed: () {
_walletOptions.isEditing = false;
_walletOptions.isBalanceBlur = false;
_myWalletProvider.rebuildWidget();
Navigator.pop(context);
}),
title: SizedBox(
height: 22,
child: Consumer<WalletOptionsProvider>(
builder: (context, walletProvider, _) {
return Text(_walletOptions.nameController.text);
return Text(wallet.name!);
}),
),
),
@ -146,20 +149,31 @@ class WalletOptions extends StatelessWidget {
children: <Widget>[
InkWell(
onTap: () async {
wallet.imageFile = await (walletProvider.changeAvatar());
if (wallet.imageFile != null) {
final _newPath = await (walletProvider.changeAvatar());
if (_newPath != '') {
wallet.imageCustomPath = _newPath;
walletBox.put(wallet.key, wallet);
}
walletProvider.reloadBuild();
},
child: wallet.imageFile == null
child: wallet.imageCustomPath == null || wallet.imageCustomPath == ''
? Image.asset(
'assets/avatars/${wallet.imageName}',
'assets/avatars/${wallet.imageDefaultPath}',
width: 110,
)
: Image.file(
wallet.imageFile!,
width: 110,
: Container(
width: 120,
height: 120,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.transparent,
image: DecorationImage(
fit: BoxFit.contain,
image: FileImage(
File(wallet.imageCustomPath!),
),
),
),
),
),
Positioned(
@ -167,7 +181,7 @@ class WalletOptions extends StatelessWidget {
top: 0,
child: InkWell(
onTap: () async {
wallet.imageFile = await (walletProvider.changeAvatar());
wallet.imageCustomPath = await (walletProvider.changeAvatar());
walletProvider.reloadBuild();
},
child: Image.asset(
@ -182,12 +196,10 @@ class WalletOptions extends StatelessWidget {
Widget walletName(WalletOptionsProvider walletProvider,
WalletOptionsProvider _walletOptions) {
bool _isNewNameValid = false;
if (_isNewNameValid == false) {
WidgetsBinding.instance.addPostFrameCallback((_) {
_walletOptions.nameController.text = wallet.name!;
} else {
wallet.name = _walletOptions.nameController.text;
}
// _walletOptions.reloadBuild();
});
return SizedBox(
width: 260,
@ -219,8 +231,8 @@ class WalletOptions extends StatelessWidget {
child: InkWell(
key: const Key('renameWallet'),
onTap: () async {
_isNewNameValid =
walletProvider.editWalletName(wallet.id(), isCesium: false);
// _isNewNameValid =
walletProvider.editWalletName(wallet.id(), isCesium: false);
await Future.delayed(const Duration(milliseconds: 30));
walletProvider.walletNameFocus.requestFocus();
},
@ -309,13 +321,13 @@ class WalletOptions extends StatelessWidget {
MaterialPageRoute(builder: (context) {
return HistoryScreen(
pubkey: walletProvider.address.text,
avatar: wallet.imageFile == null
avatar: wallet.imageCustomPath == null
? Image.asset(
'assets/avatars/${wallet.imageName}',
'assets/avatars/${wallet.imageDefaultPath}',
width: 110,
)
: Image.file(
wallet.imageFile!,
: Image.asset(
wallet.imageCustomPath!,
width: 110,
));
}),

View File

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:flutter/services.dart';
import 'package:gecko/globals.dart';
import 'package:gecko/models/chest_data.dart';
@ -65,12 +67,6 @@ class WalletsHome extends StatelessWidget {
);
}
// Widget cesiumWalletOptions(BuildContext context) {
// return Column(children: const [
// Center(child: Text('This is a Cesium wallet')),
// ]);
// }
Widget chestOptions(
BuildContext context, MyWalletsProvider _myWalletProvider) {
return Column(children: [
@ -171,6 +167,7 @@ class WalletsHome extends StatelessWidget {
return CustomScrollView(slivers: <Widget>[
const SliverToBoxAdapter(child: SizedBox(height: 20)),
SliverGrid.count(
key: const Key('listWallets'),
crossAxisCount: nTule,
@ -227,19 +224,29 @@ class WalletsHome extends StatelessWidget {
child:
// SvgPicture.asset('assets/chopp-gecko2.png',
// semanticsLabel: 'Gecko', height: 48),
_repository.imageFile == null
_repository.imageCustomPath == null ||
_repository.imageCustomPath == ''
? Image.asset(
'assets/avatars/${_repository.imageName}',
'assets/avatars/${_repository.imageDefaultPath}',
alignment: Alignment.bottomCenter,
scale: 0.5,
)
: Image.file(
_repository.imageFile!,
alignment: Alignment.bottomCenter,
scale: 0.5,
: Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.transparent,
image: DecorationImage(
fit: BoxFit.contain,
image: FileImage(
File(
_repository.imageCustomPath!),
),
),
),
),
)),
// balanceBuilder(context, _walletOptions.pubkey.text),
balanceBuilder(context, _repository.address!,
_repository.id()[1] == defaultWallet!.id()[1]),
ListTile(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
@ -308,36 +315,24 @@ class WalletsHome extends StatelessWidget {
]);
}
Widget balanceBuilder(context, String _pubkey) {
return Query(
options: QueryOptions(
document: gql(getBalance),
variables: {
'pubkey': _pubkey,
},
// 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');
}
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 Text(wBalanceUD);
});
Widget balanceBuilder(context, String _address, bool isDefault) {
return Container(
width: double.infinity,
color: isDefault ? orangeC : yellowC,
child: SizedBox(
height: 25,
child: Column(children: [
const Spacer(),
// Text(
// '0.0 gd',
// textAlign: TextAlign.center,
// style: TextStyle(color: isDefault ? Colors.white : Colors.black),
// ),
balance(
context, _address, 15, isDefault ? Colors.white : Colors.black)
]),
),
);
}
Widget addNewDerivation(context) {
@ -355,21 +350,32 @@ class WalletsHome extends StatelessWidget {
child: InkWell(
key: const Key('addDerivation'),
onTap: () async {
await _myWalletProvider.generateNewDerivation(
context, _newDerivationName);
if (!_myWalletProvider.isNewDerivationLoading) {
await _myWalletProvider.generateNewDerivation(
context, _newDerivationName);
}
},
child: Container(
width: double.infinity,
height: double.infinity,
decoration: BoxDecoration(color: floattingYellow),
child: const Center(
child: Text(
'+',
style: TextStyle(
fontSize: 150,
fontWeight: FontWeight.w700,
color: Color(0xFFFCB437)),
)),
child: Center(
child: _myWalletProvider.isNewDerivationLoading
? SizedBox(
height: 60,
width: 60,
child: CircularProgressIndicator(
color: orangeC,
strokeWidth: 7,
),
)
: const Text(
'+',
style: TextStyle(
fontSize: 150,
fontWeight: FontWeight.w700,
color: Color(0xFFFCB437)),
)),
)),
),
])));

View File

@ -116,7 +116,7 @@ class OnboardingStepTen extends StatelessWidget {
enableActiveFill: false,
errorAnimationController: errorController,
controller: _enterPin,
keyboardType: TextInputType.text,
keyboardType: TextInputType.visiblePassword,
boxShadows: const [
BoxShadow(
offset: Offset(0, 1),

View File

@ -588,13 +588,6 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.3"
image_gallery_saver:
dependency: "direct main"
description:
name: image_gallery_saver
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.1"
image_picker:
dependency: "direct main"
description:

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.6+8
version: 0.0.7+1
environment:
sdk: '>=2.12.0 <3.0.0'
@ -36,7 +36,7 @@ dependencies:
hive: ^2.0.4
hive_flutter: ^1.1.0
http: ^0.13.4
image_gallery_saver: ^1.6.9
# image_gallery_saver: ^1.6.9
image_picker: ^0.8.4
infinite_scroll_pagination: ^3.1.0
intl: ^0.17.0