diff --git a/app/lib/screens/wallets/wallet_details.dart b/app/lib/screens/wallets/wallet_details.dart index 237232bc..437da3e3 100644 --- a/app/lib/screens/wallets/wallet_details.dart +++ b/app/lib/screens/wallets/wallet_details.dart @@ -7,8 +7,9 @@ import 'package:threebotlogin/screens/wallets/wallet_assets.dart'; import 'package:threebotlogin/screens/wallets/wallet_info.dart'; class WalletDetailsScreen extends ConsumerStatefulWidget { - const WalletDetailsScreen({super.key, required this.wallet}); + const WalletDetailsScreen({super.key, required this.wallet, this.initialTabIndex = 0}); final Wallet wallet; + final int initialTabIndex; @override ConsumerState createState() => @@ -16,7 +17,13 @@ class WalletDetailsScreen extends ConsumerStatefulWidget { } class _WalletDetailsScreenState extends ConsumerState { - int currentScreenIndex = 0; + late int currentScreenIndex; + + @override + void initState() { + super.initState(); + currentScreenIndex = widget.initialTabIndex; + } void _selectScreen(int index) { setState(() { diff --git a/app/lib/screens/wallets/wallet_screen.dart b/app/lib/screens/wallets/wallet_screen.dart index 879b4143..4660c90d 100644 --- a/app/lib/screens/wallets/wallet_screen.dart +++ b/app/lib/screens/wallets/wallet_screen.dart @@ -91,6 +91,7 @@ class _WalletScreenState extends ConsumerState { itemBuilder: (context, i) { final wallet = wallets[i]; return WalletCardWidget( + key: ValueKey(wallet.name), wallet: wallet, ); })); diff --git a/app/lib/widgets/wallets/wallet_card.dart b/app/lib/widgets/wallets/wallet_card.dart index c5f239fa..65109525 100644 --- a/app/lib/widgets/wallets/wallet_card.dart +++ b/app/lib/widgets/wallets/wallet_card.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_slidable/flutter_slidable.dart'; import 'package:threebotlogin/helpers/globals.dart'; import 'package:threebotlogin/helpers/kyc_helpers.dart'; import 'package:threebotlogin/helpers/logger.dart'; @@ -11,6 +12,7 @@ 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'; +import 'package:threebotlogin/widgets/wallets/warning_dialog.dart'; class WalletCardWidget extends ConsumerStatefulWidget { const WalletCardWidget({super.key, required this.wallet}); @@ -164,7 +166,8 @@ class _WalletCardWidgetState extends ConsumerState { ) ]; } - return Card( + + final card = Card( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(5), side: BorderSide(color: Theme.of(context).colorScheme.primary)), @@ -201,16 +204,16 @@ class _WalletCardWidgetState extends ConsumerState { const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( border: Border.all( - color: wallet!.verificationStatus == + color: (wallet?.verificationStatus ?? widget.wallet.verificationStatus) == VerificationState.VERIFIED ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.error, ), borderRadius: BorderRadius.circular(20), ), - child: Text(capitalize(wallet.verificationStatus.name), + child: Text(capitalize((wallet?.verificationStatus ?? widget.wallet.verificationStatus).name), style: Theme.of(context).textTheme.bodySmall!.copyWith( - color: wallet.verificationStatus == + color: (wallet?.verificationStatus ?? widget.wallet.verificationStatus) == VerificationState.VERIFIED ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.error, @@ -225,5 +228,96 @@ class _WalletCardWidgetState extends ConsumerState { ), ), ); + + final canDelete = widget.wallet.type == WalletType.IMPORTED; + final actions = []; + + if (canDelete) { + actions.add( + SlidableAction( + onPressed: (_) => _showDeleteConfirmationDialog(), + backgroundColor: Theme.of(context).colorScheme.error, + foregroundColor: Theme.of(context).colorScheme.onError, + icon: Icons.delete, + label: 'Delete', + ), + ); + } + + actions.add( + SlidableAction( + onPressed: (_) => _editWallet(), + backgroundColor: Theme.of(context).colorScheme.primaryContainer, + foregroundColor: Theme.of(context).colorScheme.onPrimaryContainer, + icon: Icons.edit, + label: 'Edit', + ), + ); + + return Slidable( + key: ValueKey(widget.wallet.name), + endActionPane: ActionPane( + motion: const DrawerMotion(), + extentRatio: canDelete ? 0.3 : 0.2, + children: actions, + ), + child: card, + ); + } + + void _showDeleteConfirmationDialog() { + showDialog( + context: context, + builder: (BuildContext context) => WarningDialogWidget( + title: 'Are you sure?', + description: 'If you confirm, your wallet will be removed from this device.', + onAgree: _deleteWallet, + ), + ); + } + + Future _deleteWallet() async { + if (context.mounted) { + Navigator.of(context).pop(); + } + + try { + await deleteWallet(widget.wallet.name); + await ref.read(walletsNotifier.notifier).removeWallet(widget.wallet.name); + if (mounted && context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: const Text('Wallet deleted'), + duration: const Duration(seconds: 2), + ), + ); + } + return true; + } catch (e) { + logger.e('Failed to delete wallet due to $e'); + if (mounted && context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + 'Failed to delete', + style: Theme.of(context).textTheme.bodyMedium!.copyWith( + color: Theme.of(context).colorScheme.errorContainer, + ), + ), + duration: const Duration(seconds: 3), + ), + ); + } + return false; + } + } + + void _editWallet() { + Navigator.of(context).push(MaterialPageRoute( + builder: (context) => WalletDetailsScreen( + wallet: widget.wallet, + initialTabIndex: 2, // Navigate to Info tab + ), + )); } } diff --git a/app/pubspec.lock b/app/pubspec.lock index 1a3731f1..3558ad73 100644 --- a/app/pubspec.lock +++ b/app/pubspec.lock @@ -703,6 +703,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.6.1" + flutter_slidable: + dependency: "direct main" + description: + name: flutter_slidable + sha256: a857de7ea701f276fd6a6c4c67ae885b60729a3449e42766bb0e655171042801 + url: "https://pub.dev" + source: hosted + version: "3.1.2" flutter_staggered_grid_view: dependency: transitive description: diff --git a/app/pubspec.yaml b/app/pubspec.yaml index 56e9e74c..f93d8760 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -88,6 +88,7 @@ dependencies: background_fetch: ^1.3.8 connectivity_plus: ^6.1.4 awesome_notifications: ^0.10.1 + flutter_slidable: ^3.1.1 dev_dependencies: flutter_test: sdk: flutter