From 7203f09eb036e7655e93e2aa6758c9a7dabe1b48 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 27 Oct 2022 12:47:30 -0600 Subject: [PATCH] desktop sync status styling and basic functionality --- .../wallet_view/desktop_wallet_view.dart | 276 ++++++++++++++---- 1 file changed, 223 insertions(+), 53 deletions(-) diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart index e411def59..2bcb9eeb4 100644 --- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart +++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart @@ -1,13 +1,24 @@ +import 'dart:async'; + +import 'package:event_bus/event_bus.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart'; import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_summary.dart'; import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/receive/desktop_receive.dart'; import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/send/desktop_send.dart'; +import 'package:stackwallet/providers/global/auto_swb_service_provider.dart'; import 'package:stackwallet/providers/providers.dart'; +import 'package:stackwallet/providers/ui/transaction_filter_provider.dart'; +import 'package:stackwallet/services/event_bus/events/global/node_connection_status_changed_event.dart'; import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart'; +import 'package:stackwallet/services/event_bus/global_event_bus.dart'; +import 'package:stackwallet/services/exchange/exchange_data_loading_service.dart'; import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/constants.dart'; +import 'package:stackwallet/utilities/enums/backup_frequency_type.dart'; +import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; @@ -16,16 +27,20 @@ import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart'; import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart'; import 'package:stackwallet/widgets/desktop/secondary_button.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; +import 'package:tuple/tuple.dart'; +/// [eventBus] should only be set during testing class DesktopWalletView extends ConsumerStatefulWidget { const DesktopWalletView({ Key? key, required this.walletId, + this.eventBus, }) : super(key: key); static const String routeName = "/desktopWalletView"; final String walletId; + final EventBus? eventBus; @override ConsumerState createState() => _DesktopWalletViewState(); @@ -33,15 +48,69 @@ class DesktopWalletView extends ConsumerStatefulWidget { class _DesktopWalletViewState extends ConsumerState { late final String walletId; + late final EventBus eventBus; + + late final bool _shouldDisableAutoSyncOnLogOut; + + final _cnLoadingService = ExchangeDataLoadingService(); Future onBackPressed() async { - // TODO log out and close wallet before popping back - Navigator.of(context).pop(); + await _logout(); + if (mounted) { + Navigator.of(context).pop(); + } + } + + Future _logout() async { + final managerProvider = + ref.read(walletsChangeNotifierProvider).getManagerProvider(walletId); + if (_shouldDisableAutoSyncOnLogOut) { + // disable auto sync if it was enabled only when loading wallet + ref.read(managerProvider).shouldAutoSync = false; + } + ref.read(managerProvider.notifier).isActiveWallet = false; + ref.read(transactionFilterProvider.state).state = null; + if (ref.read(prefsChangeNotifierProvider).isAutoBackupEnabled && + ref.read(prefsChangeNotifierProvider).backupFrequencyType == + BackupFrequencyType.afterClosingAWallet) { + unawaited(ref.read(autoSWBServiceProvider).doBackup()); + } + } + + void _loadCNData() { + // unawaited future + if (ref.read(prefsChangeNotifierProvider).externalCalls) { + _cnLoadingService.loadAll(ref, + coin: ref + .read(walletsChangeNotifierProvider) + .getManager(walletId) + .coin); + } else { + Logging.instance.log("User does not want to use external calls", + level: LogLevel.Info); + } } @override void initState() { walletId = widget.walletId; + final managerProvider = + ref.read(walletsChangeNotifierProvider).getManagerProvider(walletId); + + eventBus = + widget.eventBus != null ? widget.eventBus! : GlobalEventBus.instance; + + ref.read(managerProvider).isActiveWallet = true; + if (!ref.read(managerProvider).shouldAutoSync) { + // enable auto sync if it wasn't enabled when loading wallet + ref.read(managerProvider).shouldAutoSync = true; + _shouldDisableAutoSyncOnLogOut = true; + } else { + _shouldDisableAutoSyncOnLogOut = false; + } + + ref.read(managerProvider).refresh(); + super.initState(); } @@ -95,13 +164,16 @@ class _DesktopWalletViewState extends ConsumerState { ], ), trailing: Row( - children: const [ - NetworkInfoButton(), - SizedBox( + children: [ + NetworkInfoButton( + walletId: walletId, + eventBus: eventBus, + ), + const SizedBox( width: 32, ), - WalletKeysButton(), - SizedBox( + const WalletKeysButton(), + const SizedBox( width: 32, ), ], @@ -132,37 +204,6 @@ class _DesktopWalletViewState extends ConsumerState { ? WalletSyncStatus.syncing : WalletSyncStatus.synced, ), - // Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - // children: [ - // Row( - // children: [ - // Text( - // "TODO: balance", - // style: STextStyles.desktopH3(context), - // ), - // const SizedBox( - // width: 8, - // ), - // Container( - // color: Colors.red, - // width: 20, - // height: 20, - // ), - // ], - // ), - // Text( - // "todo: fiat balance", - // style: - // STextStyles.desktopTextExtraSmall(context).copyWith( - // color: Theme.of(context) - // .extension()! - // .textSubtitle1, - // ), - // ) - // ], - // ), const Spacer(), SecondaryButton( width: 180, @@ -195,7 +236,7 @@ class _DesktopWalletViewState extends ConsumerState { const SizedBox( width: 16, ), - Expanded( + const Expanded( child: RecentDesktopTransactions(), ), ], @@ -284,7 +325,6 @@ class _MyWalletState extends State { ], ), ), - const Spacer(), ], ); } @@ -461,30 +501,160 @@ class _RecentDesktopTransactionsState extends State { } } -class NetworkInfoButton extends StatelessWidget { - const NetworkInfoButton({Key? key}) : super(key: key); +class NetworkInfoButton extends ConsumerStatefulWidget { + const NetworkInfoButton({ + Key? key, + required this.walletId, + this.eventBus, + }) : super(key: key); + + final String walletId; + final EventBus? eventBus; + + @override + ConsumerState createState() => _NetworkInfoButtonState(); +} + +class _NetworkInfoButtonState extends ConsumerState { + late final String walletId; + late final EventBus eventBus; + + late WalletSyncStatus _currentSyncStatus; + late NodeConnectionStatus _currentNodeStatus; + + late StreamSubscription _syncStatusSubscription; + late StreamSubscription _nodeStatusSubscription; + + @override + void initState() { + walletId = widget.walletId; + final managerProvider = + ref.read(walletsChangeNotifierProvider).getManagerProvider(walletId); + + eventBus = + widget.eventBus != null ? widget.eventBus! : GlobalEventBus.instance; + + if (ref.read(managerProvider).isRefreshing) { + _currentSyncStatus = WalletSyncStatus.syncing; + _currentNodeStatus = NodeConnectionStatus.connected; + } else { + _currentSyncStatus = WalletSyncStatus.synced; + if (ref.read(managerProvider).isConnected) { + _currentNodeStatus = NodeConnectionStatus.connected; + } else { + _currentNodeStatus = NodeConnectionStatus.disconnected; + _currentSyncStatus = WalletSyncStatus.unableToSync; + } + } + + _syncStatusSubscription = + eventBus.on().listen( + (event) async { + if (event.walletId == widget.walletId) { + setState(() { + _currentSyncStatus = event.newStatus; + }); + } + }, + ); + + _nodeStatusSubscription = + eventBus.on().listen( + (event) async { + if (event.walletId == widget.walletId) { + setState(() { + _currentNodeStatus = event.newStatus; + }); + } + }, + ); + + super.initState(); + } + + @override + void dispose() { + _nodeStatusSubscription.cancel(); + _syncStatusSubscription.cancel(); + super.dispose(); + } + + Widget _buildNetworkIcon(WalletSyncStatus status, BuildContext context) { + const size = 24.0; + switch (status) { + case WalletSyncStatus.unableToSync: + return SvgPicture.asset( + Assets.svg.radioProblem, + color: Theme.of(context).extension()!.accentColorRed, + width: size, + height: size, + ); + case WalletSyncStatus.synced: + return SvgPicture.asset( + Assets.svg.radio, + color: Theme.of(context).extension()!.accentColorGreen, + width: size, + height: size, + ); + case WalletSyncStatus.syncing: + return SvgPicture.asset( + Assets.svg.radioSyncing, + color: Theme.of(context).extension()!.accentColorYellow, + width: size, + height: size, + ); + } + } + + Widget _buildText(WalletSyncStatus status, BuildContext context) { + String label; + Color color; + + switch (status) { + case WalletSyncStatus.unableToSync: + label = "Unable to sync"; + color = Theme.of(context).extension()!.accentColorRed; + break; + case WalletSyncStatus.synced: + label = "Synchronised"; + color = Theme.of(context).extension()!.accentColorGreen; + break; + case WalletSyncStatus.syncing: + label = "Synchronising"; + color = Theme.of(context).extension()!.accentColorYellow; + break; + } + + return Text( + label, + style: STextStyles.desktopMenuItemSelected(context).copyWith( + color: color, + ), + ); + } @override Widget build(BuildContext context) { return GestureDetector( + onTap: () { + Navigator.of(context).pushNamed( + WalletNetworkSettingsView.routeName, + arguments: Tuple3( + walletId, + _currentSyncStatus, + _currentNodeStatus, + ), + ); + }, child: Container( color: Colors.transparent, child: Row( children: [ - SvgPicture.asset( - Assets.svg.network, - width: 24, - height: 24, - color: - Theme.of(context).extension()!.accentColorGreen, - ), + _buildNetworkIcon(_currentSyncStatus, context), const SizedBox( width: 6, ), - Text( - "Synchronised", - style: STextStyles.desktopMenuItemSelected(context), - ) + _buildText(_currentSyncStatus, context), ], ), ),