diff --git a/app/lib/providers/wallets_provider.dart b/app/lib/providers/wallets_provider.dart index d26989c2..0ca1a2c3 100644 --- a/app/lib/providers/wallets_provider.dart +++ b/app/lib/providers/wallets_provider.dart @@ -32,6 +32,22 @@ class WalletsNotifier extends StateNotifier> { }); } + Future addWallet(Wallet wallet) async { + await _mutex.protect(() async { + state = [...state, wallet]; + }); + } + + Future editWallet(String oldName, String newName) async { + await _mutex.protect(() async { + final wallet = state.where((w) => w.name == oldName).firstOrNull; + if (wallet != null) { + wallet.name = newName; + } + state = [...state]; + }); + } + void reloadBalances() async { if (!_reload) return await TFChainService.disconnect(); if (!_loading) { @@ -70,6 +86,10 @@ class WalletsNotifier extends StateNotifier> { _reload = true; } + void clear() { + _isListed = false; + } + Wallet? getUpdatedWallet(String name) { return state.where((w) => w.name == name).firstOrNull; } diff --git a/app/lib/screens/preference_screen.dart b/app/lib/screens/preference_screen.dart index 1a7b57c7..d61a7038 100644 --- a/app/lib/screens/preference_screen.dart +++ b/app/lib/screens/preference_screen.dart @@ -13,6 +13,7 @@ import 'package:threebotlogin/events/events.dart'; import 'package:threebotlogin/helpers/environment.dart'; import 'package:threebotlogin/helpers/globals.dart'; import 'package:threebotlogin/helpers/logger.dart'; +import 'package:threebotlogin/providers/wallets_provider.dart'; import 'package:threebotlogin/screens/authentication_screen.dart'; import 'package:threebotlogin/screens/change_pin_screen.dart'; @@ -324,6 +325,7 @@ class _PreferenceScreenState extends ConsumerState { bool result = false; if (deleted) { result = await clearData(); + ref.read(walletsNotifier.notifier).clear(); if (result) { Navigator.pop(context); await Navigator.pushReplacement( diff --git a/app/lib/screens/recover_screen.dart b/app/lib/screens/recover_screen.dart index 5cf1c07f..a451dfdb 100644 --- a/app/lib/screens/recover_screen.dart +++ b/app/lib/screens/recover_screen.dart @@ -57,7 +57,7 @@ class _RecoverScreenState extends State { } validateSeed(String seedPhrase, userInfoResult) async { - if (seedPhrase.isEmpty){ + if (seedPhrase.isEmpty) { throw ('Seed Phrase is required'); } try { diff --git a/app/lib/screens/wallets/bridge.dart b/app/lib/screens/wallets/bridge.dart index ef62ec2b..11f77c6a 100644 --- a/app/lib/screens/wallets/bridge.dart +++ b/app/lib/screens/wallets/bridge.dart @@ -13,17 +13,15 @@ import 'package:validators/validators.dart'; import 'package:threebotlogin/services/stellar_service.dart' as Stellar; import 'package:threebotlogin/services/tfchain_service.dart' as TFChain; -class WalletBridgeScreen extends StatefulWidget { - const WalletBridgeScreen( - {super.key, required this.wallet, required this.allWallets}); +class WalletBridgeScreen extends ConsumerStatefulWidget { + const WalletBridgeScreen({super.key, required this.wallet}); final Wallet wallet; - final List allWallets; @override - State createState() => _WalletBridgeScreenState(); + ConsumerState createState() => _WalletBridgeScreenState(); } -class _WalletBridgeScreenState extends State { +class _WalletBridgeScreenState extends ConsumerState { final fromController = TextEditingController(); final toController = TextEditingController(); final amountController = TextEditingController(); @@ -171,6 +169,7 @@ class _WalletBridgeScreenState extends State { @override Widget build(BuildContext context) { + List wallets = ref.read(walletsNotifier); final bool disableDeposit = widget.wallet.stellarBalance == '-1'; if (disableDeposit && !isWithdraw) { onTransactionChange(BridgeOperation.Withdraw); @@ -223,12 +222,12 @@ class _WalletBridgeScreenState extends State { : ChainType.TFChain, currentWalletAddress: fromController.text, wallets: isWithdraw - ? widget.allWallets + ? wallets .where((w) => double.parse(w.stellarBalance) >= 0) .toList() - : widget.allWallets, + : wallets, onSelectToAddress: _selectToAddress), )); }, diff --git a/app/lib/screens/wallets/send.dart b/app/lib/screens/wallets/send.dart index b6576178..b56e4657 100644 --- a/app/lib/screens/wallets/send.dart +++ b/app/lib/screens/wallets/send.dart @@ -17,17 +17,15 @@ import 'package:validators/validators.dart'; import 'package:threebotlogin/services/stellar_service.dart' as Stellar; import 'package:threebotlogin/services/tfchain_service.dart' as TFChain; -class WalletSendScreen extends StatefulWidget { - const WalletSendScreen( - {super.key, required this.wallet, required this.allWallets}); +class WalletSendScreen extends ConsumerStatefulWidget { + const WalletSendScreen({super.key, required this.wallet}); final Wallet wallet; - final List allWallets; @override - State createState() => _WalletSendScreenState(); + ConsumerState createState() => _WalletSendScreenState(); } -class _WalletSendScreenState extends State { +class _WalletSendScreenState extends ConsumerState { final fromController = TextEditingController(); final toController = TextEditingController(); final amountController = TextEditingController(); @@ -39,9 +37,12 @@ class _WalletSendScreenState extends State { bool reloadBalance = true; final FocusNode textFieldFocusNode = FocusNode(); List percentages = [25, 50, 75, 100]; + List wallets = []; + @override void initState() { fromController.text = widget.wallet.stellarAddress; + wallets = ref.read(walletsNotifier); _reloadBalances(); super.initState(); } @@ -127,8 +128,8 @@ class _WalletSendScreenState extends State { return false; } - final matchingWallets = widget.allWallets - .where((wallet) => wallet.stellarAddress == toAddress); + final matchingWallets = + wallets.where((wallet) => wallet.stellarAddress == toAddress); final Wallet? wallet = matchingWallets.isNotEmpty ? matchingWallets.first : null; if (wallet != null && wallet.stellarBalance == '-1') { @@ -268,13 +269,13 @@ class _WalletSendScreenState extends State { currentWalletAddress: fromController.text, wallets: chainType == ChainType.Stellar - ? widget.allWallets + ? wallets .where((w) => double.parse( w.stellarBalance) >= 0) .toList() - : widget.allWallets, + : wallets, onSelectToAddress: _selectToAddress), )); }, diff --git a/app/lib/screens/wallets/wallet_assets.dart b/app/lib/screens/wallets/wallet_assets.dart index 60603a47..068da3de 100644 --- a/app/lib/screens/wallets/wallet_assets.dart +++ b/app/lib/screens/wallets/wallet_assets.dart @@ -13,10 +13,8 @@ import 'package:threebotlogin/widgets/wallets/arrow_inward.dart'; import 'package:threebotlogin/widgets/wallets/balance_tile.dart'; class WalletAssetsWidget extends StatefulWidget { - const WalletAssetsWidget( - {super.key, required this.wallet, required this.allWallets}); + const WalletAssetsWidget({super.key, required this.wallet}); final Wallet wallet; - final List allWallets; @override State createState() => _WalletAssetsWidgetState(); @@ -103,7 +101,6 @@ class _WalletAssetsWidgetState extends State { Navigator.of(context).push(MaterialPageRoute( builder: (context) => WalletSendScreen( wallet: widget.wallet, - allWallets: widget.allWallets, ), )); }, @@ -163,7 +160,6 @@ class _WalletAssetsWidgetState extends State { Navigator.of(context).push(MaterialPageRoute( builder: (context) => WalletBridgeScreen( wallet: widget.wallet, - allWallets: widget.allWallets, ), )); }, diff --git a/app/lib/screens/wallets/wallet_details.dart b/app/lib/screens/wallets/wallet_details.dart index b3387517..237232bc 100644 --- a/app/lib/screens/wallets/wallet_details.dart +++ b/app/lib/screens/wallets/wallet_details.dart @@ -1,26 +1,21 @@ import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:threebotlogin/models/wallet.dart'; +import 'package:threebotlogin/providers/wallets_provider.dart'; import 'package:threebotlogin/screens/wallets/transactions.dart'; import 'package:threebotlogin/screens/wallets/wallet_assets.dart'; import 'package:threebotlogin/screens/wallets/wallet_info.dart'; -class WalletDetailsScreen extends StatefulWidget { - const WalletDetailsScreen( - {super.key, - required this.wallet, - required this.allWallets, - required this.onDeleteWallet, - required this.onEditWallet}); +class WalletDetailsScreen extends ConsumerStatefulWidget { + const WalletDetailsScreen({super.key, required this.wallet}); final Wallet wallet; - final List allWallets; - final void Function(String name) onDeleteWallet; - final void Function(String oldName, String newName) onEditWallet; @override - State createState() => _WalletDetailsScreenState(); + ConsumerState createState() => + _WalletDetailsScreenState(); } -class _WalletDetailsScreenState extends State { +class _WalletDetailsScreenState extends ConsumerState { int currentScreenIndex = 0; void _selectScreen(int index) { @@ -29,28 +24,18 @@ class _WalletDetailsScreenState extends State { }); } - void _onEditWallet(String oldName, String newName) { - widget.wallet.name = newName; - widget.onEditWallet(oldName, newName); - setState(() {}); - } - @override Widget build(BuildContext context) { Widget content; + ref.watch(walletsNotifier).firstWhere((w) => w.name == widget.wallet.name); if (currentScreenIndex == 1) { content = WalletTransactionsWidget( wallet: widget.wallet, ); } else if (currentScreenIndex == 2) { - content = WalletDetailsWidget( - wallet: widget.wallet, - onDeleteWallet: widget.onDeleteWallet, - onEditWallet: _onEditWallet, - ); + content = WalletDetailsWidget(wallet: widget.wallet); } else { content = WalletAssetsWidget( - allWallets: widget.allWallets, wallet: widget.wallet, ); } diff --git a/app/lib/screens/wallets/wallet_info.dart b/app/lib/screens/wallets/wallet_info.dart index 2e05f3bb..dd016d4b 100644 --- a/app/lib/screens/wallets/wallet_info.dart +++ b/app/lib/screens/wallets/wallet_info.dart @@ -1,26 +1,23 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:threebotlogin/helpers/logger.dart'; import 'package:threebotlogin/models/wallet.dart'; +import 'package:threebotlogin/providers/wallets_provider.dart'; import 'package:threebotlogin/services/wallet_service.dart'; import 'package:threebotlogin/widgets/kyc_widget.dart'; import 'package:threebotlogin/widgets/wallets/warning_dialog.dart'; -class WalletDetailsWidget extends StatefulWidget { - const WalletDetailsWidget( - {super.key, - required this.wallet, - required this.onDeleteWallet, - required this.onEditWallet}); +class WalletDetailsWidget extends ConsumerStatefulWidget { + const WalletDetailsWidget({super.key, required this.wallet}); final Wallet wallet; - final void Function(String name) onDeleteWallet; - final void Function(String oldName, String newName) onEditWallet; @override - State createState() => _WalletDetailsWidgetState(); + ConsumerState createState() => + _WalletDetailsWidgetState(); } -class _WalletDetailsWidgetState extends State { +class _WalletDetailsWidgetState extends ConsumerState { final stellarSecretController = TextEditingController(); final stellarAddressController = TextEditingController(); final tfchainSecretController = TextEditingController(); @@ -31,11 +28,18 @@ class _WalletDetailsWidgetState extends State { bool showTfchainSecret = false; bool showStellarSecret = false; bool edit = false; + late WalletsNotifier walletsRef; + + @override + void initState() { + super.initState(); + walletsRef = ref.read(walletsNotifier.notifier); + } Future _deleteWallet() async { try { await deleteWallet(walletNameController.text); - widget.onDeleteWallet(walletNameController.text); + await walletsRef.removeWallet(walletNameController.text); return true; } catch (e) { logger.e('Failed to delete wallet due to $e'); @@ -69,7 +73,7 @@ class _WalletDetailsWidgetState extends State { } try { await editWallet(walletName, newName); - widget.onEditWallet(walletName, newName); + await walletsRef.editWallet(walletName, newName); walletName = newName; widget.wallet.name = newName; } catch (e) { diff --git a/app/lib/screens/wallets/wallet_screen.dart b/app/lib/screens/wallets/wallet_screen.dart index 5f608cf4..e1c35f9c 100644 --- a/app/lib/screens/wallets/wallet_screen.dart +++ b/app/lib/screens/wallets/wallet_screen.dart @@ -25,19 +25,6 @@ class _WalletScreenState extends ConsumerState { List wallets = []; late WalletsNotifier walletRef; - onDeleteWallet(String name) { - walletRef.removeWallet(name); - } - - onEditWallet(String oldName, String newName) { - for (final w in wallets) { - if (w.name == oldName) { - w.name = newName; - } - } - setState(() {}); - } - @override void initState() { super.initState(); @@ -91,9 +78,6 @@ class _WalletScreenState extends ConsumerState { final wallet = wallets[i]; return WalletCardWidget( wallet: wallet, - allWallets: wallets, - onDeleteWallet: onDeleteWallet, - onEditWallet: onEditWallet, ); })); } @@ -155,7 +139,6 @@ class _WalletScreenState extends ConsumerState { constraints: const BoxConstraints(maxWidth: double.infinity), context: context, builder: (ctx) => NewWallet( - onAddWallet: _addWallet, wallets: wallets, )); } @@ -172,11 +155,6 @@ class _WalletScreenState extends ConsumerState { wallets.add(wallet); } - void _addWallet(Wallet wallet) { - wallets.add(wallet); - setState(() {}); - } - Future handleRefresh() async { try { loading = true; diff --git a/app/lib/widgets/wallets/add_wallet.dart b/app/lib/widgets/wallets/add_wallet.dart index 3410cc80..cf79d1b6 100644 --- a/app/lib/widgets/wallets/add_wallet.dart +++ b/app/lib/widgets/wallets/add_wallet.dart @@ -4,10 +4,12 @@ import 'package:bip39/bip39.dart'; import 'package:convert/convert.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:hashlib/hashlib.dart'; import 'package:threebotlogin/helpers/globals.dart'; import 'package:threebotlogin/helpers/logger.dart'; import 'package:threebotlogin/models/wallet.dart'; +import 'package:threebotlogin/providers/wallets_provider.dart'; import 'package:threebotlogin/services/stellar_service.dart'; import 'package:threebotlogin/services/wallet_service.dart'; import 'package:tfchain_client/src/utils.dart'; @@ -18,21 +20,20 @@ import 'package:stellar_client/stellar_client.dart' as Stellar; import 'package:bip39/bip39.dart'; import 'package:substrate_bip39/substrate_bip39.dart'; -class NewWallet extends StatefulWidget { - const NewWallet( - {super.key, required this.onAddWallet, required this.wallets}); - final void Function(Wallet addedWallet) onAddWallet; +class NewWallet extends ConsumerStatefulWidget { + const NewWallet({super.key, required this.wallets}); final List wallets; @override - State createState() { + ConsumerState createState() { return _NewWalletState(); } } -class _NewWalletState extends State { +class _NewWalletState extends ConsumerState { final _nameController = TextEditingController(); final _secretController = TextEditingController(); + late WalletsNotifier walletRef = ref.read(walletsNotifier.notifier); bool saveLoading = false; String? nameError; String? secretError; @@ -190,6 +191,7 @@ class _NewWalletState extends State { } try { await addWallet(walletName, walletSecret); + walletRef.addWallet(wallet); await _showDialog( 'Wallet Added!', 'Wallet $walletName has been added successfully', @@ -203,7 +205,6 @@ class _NewWalletState extends State { setState(() {}); return; } - widget.onAddWallet(wallet); saveLoading = false; setState(() {}); if (!context.mounted) return; diff --git a/app/lib/widgets/wallets/wallet_card.dart b/app/lib/widgets/wallets/wallet_card.dart index e3089d89..c45be8c4 100644 --- a/app/lib/widgets/wallets/wallet_card.dart +++ b/app/lib/widgets/wallets/wallet_card.dart @@ -1,32 +1,26 @@ import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:threebotlogin/helpers/globals.dart'; import 'package:threebotlogin/helpers/logger.dart'; import 'package:threebotlogin/helpers/transaction_helpers.dart'; import 'package:threebotlogin/models/wallet.dart'; +import 'package:threebotlogin/providers/wallets_provider.dart'; import 'package:threebotlogin/screens/wallets/wallet_details.dart'; import 'package:threebotlogin/services/stellar_service.dart' as StellarService; import 'package:threebotlogin/services/tfchain_service.dart' as TFChainService; import 'package:threebotlogin/services/wallet_service.dart'; -class WalletCardWidget extends StatefulWidget { - const WalletCardWidget( - {super.key, - required this.wallet, - required this.allWallets, - required this.onDeleteWallet, - required this.onEditWallet}); +class WalletCardWidget extends ConsumerStatefulWidget { + const WalletCardWidget({super.key, required this.wallet}); final Wallet wallet; - final List allWallets; - final void Function(String name) onDeleteWallet; - final void Function(String oldName, String newName) onEditWallet; @override - State createState() => _WalletCardWidgetState(); + ConsumerState createState() => _WalletCardWidgetState(); } -class _WalletCardWidgetState extends State { +class _WalletCardWidgetState extends ConsumerState { bool initialWalletLoading = false; - + List wallets = []; _initializeWallet() async { setState(() { initialWalletLoading = true; @@ -67,6 +61,7 @@ class _WalletCardWidgetState extends State { @override Widget build(BuildContext context) { List cardContent = []; + wallets = ref.watch(walletsNotifier); if (widget.wallet.type == WalletType.NATIVE && widget.wallet.stellarBalance == '-1') { cardContent = [ @@ -158,9 +153,6 @@ class _WalletCardWidgetState extends State { Navigator.of(context).push(MaterialPageRoute( builder: (context) => WalletDetailsScreen( wallet: widget.wallet, - allWallets: widget.allWallets, - onDeleteWallet: widget.onDeleteWallet, - onEditWallet: widget.onEditWallet, ), )); }, diff --git a/git_hooks/pre-commit b/git_hooks/pre-commit index c9136eed..77df122b 100755 --- a/git_hooks/pre-commit +++ b/git_hooks/pre-commit @@ -11,6 +11,15 @@ run_command() { echo "$result" } +# Ensure git hooks path is set only once +if ! git config --get core.hooksPath | grep -q "git_hooks"; then + echo "Setting git hooks path..." + git config core.hooksPath git_hooks + echo "Git hooks path set to 'git_hooks'." +else + echo "Git hooks path already set. Skipping..." +fi + # Change directory to app/lib and run dart format run_command "app/lib" "dart format ." "dart format"