From 82fb5427407f7d2567f2056473ba68a7e6fa5d22 Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 7 Jun 2024 10:30:35 -0600 Subject: [PATCH] allow clearing of spark cache on desktop --- .../more_features/more_features_dialog.dart | 327 ++++++++++++------ 1 file changed, 215 insertions(+), 112 deletions(-) diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart index 1ab2a6781..f88279263 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/more_features/more_features_dialog.dart @@ -8,12 +8,11 @@ * */ -import 'dart:convert'; - import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import '../../../../../db/sqlite/firo_cache.dart'; import '../../../../../providers/db/main_db_provider.dart'; import '../../../../../providers/global/prefs_provider.dart'; import '../../../../../providers/global/wallets_provider.dart'; @@ -23,10 +22,13 @@ import '../../../../../utilities/text_styles.dart'; import '../../../../../wallets/crypto_currency/coins/banano.dart'; import '../../../../../wallets/crypto_currency/coins/firo.dart'; import '../../../../../wallets/isar/models/wallet_info.dart'; +import '../../../../../wallets/isar/providers/wallet_info_provider.dart'; import '../../../../../wallets/wallet/wallet_mixin_interfaces/cash_fusion_interface.dart'; import '../../../../../wallets/wallet/wallet_mixin_interfaces/coin_control_interface.dart'; +import '../../../../../wallets/wallet/wallet_mixin_interfaces/lelantus_interface.dart'; import '../../../../../wallets/wallet/wallet_mixin_interfaces/ordinals_interface.dart'; import '../../../../../wallets/wallet/wallet_mixin_interfaces/paynym_interface.dart'; +import '../../../../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart'; import '../../../../../widgets/custom_buttons/draggable_switch_button.dart'; import '../../../../../widgets/desktop/desktop_dialog.dart'; import '../../../../../widgets/desktop/desktop_dialog_close_button.dart'; @@ -59,9 +61,26 @@ class MoreFeaturesDialog extends ConsumerStatefulWidget { } class _MoreFeaturesDialogState extends ConsumerState { - bool _enableLelantusScanning = false; bool _isUpdatingLelantusScanning = false; // Mutex. + Future _switchToggled(bool newValue) async { + if (_isUpdatingLelantusScanning) return; + _isUpdatingLelantusScanning = true; // Lock mutex. + + try { + // Toggle enableLelantusScanning in wallet info. + await ref.read(pWalletInfo(widget.walletId)).updateOtherData( + newEntries: { + WalletInfoKeys.enableLelantusScanning: newValue, + }, + isar: ref.read(mainDBProvider).isar, + ); + } finally { + // ensure _isUpdatingLelantusScanning is set to false no matter what + _isUpdatingLelantusScanning = false; + } + } + @override Widget build(BuildContext context) { final wallet = ref.watch( @@ -70,14 +89,6 @@ class _MoreFeaturesDialogState extends ConsumerState { ), ); - // Parse otherDataJsonString to get the enableLelantusScanning value. - if (wallet.info.otherDataJsonString != null) { - final otherDataJson = json.decode(wallet.info.otherDataJsonString!); - _enableLelantusScanning = - otherDataJson[WalletInfoKeys.enableLelantusScanning] as bool? ?? - false; - } - final coinControlPrefEnabled = ref.watch( prefsChangeNotifierProvider.select( (value) => value.enableCoinControl, @@ -108,7 +119,7 @@ class _MoreFeaturesDialogState extends ConsumerState { label: "Anonymize funds", detail: "Anonymize funds", iconAsset: Assets.svg.recycle, - onPressed: () => widget.onAnonymizeAllPressed?.call(), + onPressed: () async => widget.onAnonymizeAllPressed?.call(), ), // TODO: [prio=med] // if (manager.hasWhirlpoolSupport) @@ -123,93 +134,68 @@ class _MoreFeaturesDialogState extends ConsumerState { label: "Coin control", detail: "Control, freeze, and utilize outputs at your discretion", iconAsset: Assets.svg.coinControl.gamePad, - onPressed: () => widget.onCoinControlPressed?.call(), + onPressed: () async => widget.onCoinControlPressed?.call(), ), if (wallet is PaynymInterface) _MoreFeaturesItem( label: "PayNym", detail: "Increased address privacy using BIP47", iconAsset: Assets.svg.robotHead, - onPressed: () => widget.onPaynymPressed?.call(), + onPressed: () async => widget.onPaynymPressed?.call(), ), if (wallet is OrdinalsInterface) _MoreFeaturesItem( label: "Ordinals", detail: "View and control your ordinals in Stack", iconAsset: Assets.svg.ordinal, - onPressed: () => widget.onOrdinalsPressed?.call(), + onPressed: () async => widget.onOrdinalsPressed?.call(), ), if (wallet.info.coin is Banano) _MoreFeaturesItem( label: "MonKey", detail: "Generate Banano MonKey", iconAsset: Assets.svg.monkey, - onPressed: () => widget.onMonkeyPressed?.call(), + onPressed: () async => widget.onMonkeyPressed?.call(), ), if (wallet is CashFusionInterface) _MoreFeaturesItem( label: "Fusion", detail: "Decentralized mixing protocol", iconAsset: Assets.svg.cashFusion, - onPressed: () => widget.onFusionPressed?.call(), + onPressed: () async => widget.onFusionPressed?.call(), ), - if (wallet.info.coin is Firo) - Padding( - padding: const EdgeInsets.symmetric( - vertical: 6, - horizontal: 32, - ), - child: RoundedContainer( - color: Colors.transparent, - borderColor: Theme.of(context) - .extension()! - .textFieldDefaultBG, - child: Row( - children: [ - SizedBox(width: 3), - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: _enableLelantusScanning, - onValueChanged: (newValue) async { - if (_isUpdatingLelantusScanning) return; - _isUpdatingLelantusScanning = true; // Lock mutex. - - // Toggle enableLelantusScanning in wallet info. - await wallet.info.updateOtherData( - newEntries: { - WalletInfoKeys.enableLelantusScanning: - !_enableLelantusScanning, - }, - isar: ref.read(mainDBProvider).isar, - ); - - setState(() { - _enableLelantusScanning = !_enableLelantusScanning; - _isUpdatingLelantusScanning = false; // Free mutex. - }); - }, + if (wallet is SparkInterface) + const _MoreFeaturesClearSparkCacheItem(), + if (wallet is LelantusInterface) + _MoreFeaturesItemBase( + child: Row( + children: [ + const SizedBox(width: 3), + SizedBox( + height: 20, + width: 40, + child: DraggableSwitchButton( + isOn: ref.watch( + pWalletInfo(widget.walletId) + .select((value) => value.otherData), + )[WalletInfoKeys.enableLelantusScanning] as bool? ?? + false, + onValueChanged: _switchToggled, + ), + ), + const SizedBox( + width: 16, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Scan for Lelantus transactions", + style: STextStyles.w600_20(context), ), - ), - const SizedBox( - width: 16, - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Scan for Lelantus transactions", - style: STextStyles.w600_20(context), - ), - // Text( - // detail, - // style: STextStyles.desktopTextExtraExtraSmall(context), - // ), - ], - ), - ], - ), + ], + ), + ], ), ), const SizedBox( @@ -221,7 +207,7 @@ class _MoreFeaturesDialogState extends ConsumerState { } } -class _MoreFeaturesItem extends StatelessWidget { +class _MoreFeaturesItem extends StatefulWidget { const _MoreFeaturesItem({ super.key, required this.label, @@ -236,6 +222,78 @@ class _MoreFeaturesItem extends StatelessWidget { final String label; final String detail; final String iconAsset; + final Future Function()? onPressed; + + @override + State<_MoreFeaturesItem> createState() => _MoreFeaturesItemState(); +} + +class _MoreFeaturesItemState extends State<_MoreFeaturesItem> { + bool _onPressedLock = false; + + @override + Widget build(BuildContext context) { + return _MoreFeaturesItemBase( + onPressed: () async { + if (_onPressedLock) { + return; + } + _onPressedLock = true; + try { + await widget.onPressed?.call(); + } finally { + _onPressedLock = false; + } + }, + child: Row( + children: [ + RoundedContainer( + padding: const EdgeInsets.all(0), + color: Theme.of(context).extension()!.settingsIconBack, + width: _MoreFeaturesItem.iconSizeBG, + height: _MoreFeaturesItem.iconSizeBG, + radiusMultiplier: _MoreFeaturesItem.iconSizeBG, + child: Center( + child: SvgPicture.asset( + widget.iconAsset, + width: _MoreFeaturesItem.iconSize, + height: _MoreFeaturesItem.iconSize, + color: Theme.of(context) + .extension()! + .settingsIconIcon, + ), + ), + ), + const SizedBox( + width: 16, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + widget.label, + style: STextStyles.w600_20(context), + ), + Text( + widget.detail, + style: STextStyles.desktopTextExtraExtraSmall(context), + ), + ], + ), + ], + ), + ); + } +} + +class _MoreFeaturesItemBase extends StatelessWidget { + const _MoreFeaturesItemBase({ + super.key, + required this.child, + this.onPressed, + }); + + final Widget child; final VoidCallback? onPressed; @override @@ -250,44 +308,89 @@ class _MoreFeaturesItem extends StatelessWidget { borderColor: Theme.of(context).extension()!.textFieldDefaultBG, onPressed: onPressed, - child: Row( - children: [ - RoundedContainer( - padding: const EdgeInsets.all(0), - color: - Theme.of(context).extension()!.settingsIconBack, - width: iconSizeBG, - height: iconSizeBG, - radiusMultiplier: iconSizeBG, - child: Center( - child: SvgPicture.asset( - iconAsset, - width: iconSize, - height: iconSize, - color: Theme.of(context) - .extension()! - .settingsIconIcon, - ), - ), - ), - const SizedBox( - width: 16, - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - label, - style: STextStyles.w600_20(context), - ), - Text( - detail, - style: STextStyles.desktopTextExtraExtraSmall(context), - ), - ], - ), - ], - ), + child: child, + ), + ); + } +} + +class _MoreFeaturesClearSparkCacheItem extends StatefulWidget { + const _MoreFeaturesClearSparkCacheItem({ + super.key, + }); + + static const double iconSizeBG = 46; + static const double iconSize = 24; + + @override + State<_MoreFeaturesClearSparkCacheItem> createState() => + _MoreFeaturesClearSparkCacheItemState(); +} + +class _MoreFeaturesClearSparkCacheItemState + extends State<_MoreFeaturesClearSparkCacheItem> { + bool _onPressedLock = false; + + static const label = "Reset Spark electrumx cache"; + + @override + Widget build(BuildContext context) { + return _MoreFeaturesItemBase( + onPressed: () async { + if (_onPressedLock) { + return; + } + _onPressedLock = true; + try { + await FiroCacheCoordinator.clearSharedCache(); + setState(() { + // trigger rebuild for cache size display + }); + } finally { + _onPressedLock = false; + } + }, + child: Row( + children: [ + RoundedContainer( + padding: const EdgeInsets.all(0), + color: Theme.of(context).extension()!.settingsIconBack, + width: _MoreFeaturesItem.iconSizeBG, + height: _MoreFeaturesItem.iconSizeBG, + radiusMultiplier: _MoreFeaturesItem.iconSizeBG, + child: Center( + child: SvgPicture.asset( + Assets.svg.x, + width: _MoreFeaturesItem.iconSize, + height: _MoreFeaturesItem.iconSize, + color: Theme.of(context) + .extension()! + .settingsIconIcon, + ), + ), + ), + const SizedBox( + width: 16, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + label, + style: STextStyles.w600_20(context), + ), + FutureBuilder( + future: FiroCacheCoordinator.getSparkCacheSize(), + builder: (_, snapshot) { + return Text( + snapshot.data ?? "", + style: STextStyles.desktopTextExtraExtraSmall(context), + ); + }, + ), + ], + ), + ], ), ); }