desktop sync status styling and basic functionality

This commit is contained in:
julian 2022-10-27 12:47:30 -06:00
parent 8b136b003c
commit 7203f09eb0

View file

@ -1,13 +1,24 @@
import 'dart:async';
import 'package:event_bus/event_bus.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.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/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/receive/desktop_receive.dart';
import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/send/desktop_send.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/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/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/assets.dart';
import 'package:stackwallet/utilities/constants.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/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.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/desktop_scaffold.dart';
import 'package:stackwallet/widgets/desktop/secondary_button.dart'; import 'package:stackwallet/widgets/desktop/secondary_button.dart';
import 'package:stackwallet/widgets/rounded_white_container.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 { class DesktopWalletView extends ConsumerStatefulWidget {
const DesktopWalletView({ const DesktopWalletView({
Key? key, Key? key,
required this.walletId, required this.walletId,
this.eventBus,
}) : super(key: key); }) : super(key: key);
static const String routeName = "/desktopWalletView"; static const String routeName = "/desktopWalletView";
final String walletId; final String walletId;
final EventBus? eventBus;
@override @override
ConsumerState<DesktopWalletView> createState() => _DesktopWalletViewState(); ConsumerState<DesktopWalletView> createState() => _DesktopWalletViewState();
@ -33,15 +48,69 @@ class DesktopWalletView extends ConsumerStatefulWidget {
class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> { class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
late final String walletId; late final String walletId;
late final EventBus eventBus;
late final bool _shouldDisableAutoSyncOnLogOut;
final _cnLoadingService = ExchangeDataLoadingService();
Future<void> onBackPressed() async { Future<void> onBackPressed() async {
// TODO log out and close wallet before popping back await _logout();
if (mounted) {
Navigator.of(context).pop(); Navigator.of(context).pop();
} }
}
Future<void> _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 @override
void initState() { void initState() {
walletId = widget.walletId; 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(); super.initState();
} }
@ -95,13 +164,16 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
], ],
), ),
trailing: Row( trailing: Row(
children: const [ children: [
NetworkInfoButton(), NetworkInfoButton(
SizedBox( walletId: walletId,
eventBus: eventBus,
),
const SizedBox(
width: 32, width: 32,
), ),
WalletKeysButton(), const WalletKeysButton(),
SizedBox( const SizedBox(
width: 32, width: 32,
), ),
], ],
@ -132,37 +204,6 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
? WalletSyncStatus.syncing ? WalletSyncStatus.syncing
: WalletSyncStatus.synced, : 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<StackColors>()!
// .textSubtitle1,
// ),
// )
// ],
// ),
const Spacer(), const Spacer(),
SecondaryButton( SecondaryButton(
width: 180, width: 180,
@ -195,7 +236,7 @@ class _DesktopWalletViewState extends ConsumerState<DesktopWalletView> {
const SizedBox( const SizedBox(
width: 16, width: 16,
), ),
Expanded( const Expanded(
child: RecentDesktopTransactions(), child: RecentDesktopTransactions(),
), ),
], ],
@ -284,7 +325,6 @@ class _MyWalletState extends State<MyWallet> {
], ],
), ),
), ),
const Spacer(),
], ],
); );
} }
@ -461,30 +501,160 @@ class _RecentDesktopTransactionsState extends State<RecentDesktopTransactions> {
} }
} }
class NetworkInfoButton extends StatelessWidget { class NetworkInfoButton extends ConsumerStatefulWidget {
const NetworkInfoButton({Key? key}) : super(key: key); const NetworkInfoButton({
Key? key,
required this.walletId,
this.eventBus,
}) : super(key: key);
final String walletId;
final EventBus? eventBus;
@override
ConsumerState<NetworkInfoButton> createState() => _NetworkInfoButtonState();
}
class _NetworkInfoButtonState extends ConsumerState<NetworkInfoButton> {
late final String walletId;
late final EventBus eventBus;
late WalletSyncStatus _currentSyncStatus;
late NodeConnectionStatus _currentNodeStatus;
late StreamSubscription<dynamic> _syncStatusSubscription;
late StreamSubscription<dynamic> _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<WalletSyncStatusChangedEvent>().listen(
(event) async {
if (event.walletId == widget.walletId) {
setState(() {
_currentSyncStatus = event.newStatus;
});
}
},
);
_nodeStatusSubscription =
eventBus.on<NodeConnectionStatusChangedEvent>().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<StackColors>()!.accentColorRed,
width: size,
height: size,
);
case WalletSyncStatus.synced:
return SvgPicture.asset(
Assets.svg.radio,
color: Theme.of(context).extension<StackColors>()!.accentColorGreen,
width: size,
height: size,
);
case WalletSyncStatus.syncing:
return SvgPicture.asset(
Assets.svg.radioSyncing,
color: Theme.of(context).extension<StackColors>()!.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<StackColors>()!.accentColorRed;
break;
case WalletSyncStatus.synced:
label = "Synchronised";
color = Theme.of(context).extension<StackColors>()!.accentColorGreen;
break;
case WalletSyncStatus.syncing:
label = "Synchronising";
color = Theme.of(context).extension<StackColors>()!.accentColorYellow;
break;
}
return Text(
label,
style: STextStyles.desktopMenuItemSelected(context).copyWith(
color: color,
),
);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GestureDetector( return GestureDetector(
onTap: () {
Navigator.of(context).pushNamed(
WalletNetworkSettingsView.routeName,
arguments: Tuple3(
walletId,
_currentSyncStatus,
_currentNodeStatus,
),
);
},
child: Container( child: Container(
color: Colors.transparent, color: Colors.transparent,
child: Row( child: Row(
children: [ children: [
SvgPicture.asset( _buildNetworkIcon(_currentSyncStatus, context),
Assets.svg.network,
width: 24,
height: 24,
color:
Theme.of(context).extension<StackColors>()!.accentColorGreen,
),
const SizedBox( const SizedBox(
width: 6, width: 6,
), ),
Text( _buildText(_currentSyncStatus, context),
"Synchronised",
style: STextStyles.desktopMenuItemSelected(context),
)
], ],
), ),
), ),