allow clearing of spark cache on desktop

This commit is contained in:
julian 2024-06-07 10:30:35 -06:00
parent 6e3d96cdfa
commit 82fb542740

View file

@ -8,12 +8,11 @@
* *
*/ */
import 'dart:convert';
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/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import '../../../../../db/sqlite/firo_cache.dart';
import '../../../../../providers/db/main_db_provider.dart'; import '../../../../../providers/db/main_db_provider.dart';
import '../../../../../providers/global/prefs_provider.dart'; import '../../../../../providers/global/prefs_provider.dart';
import '../../../../../providers/global/wallets_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/banano.dart';
import '../../../../../wallets/crypto_currency/coins/firo.dart'; import '../../../../../wallets/crypto_currency/coins/firo.dart';
import '../../../../../wallets/isar/models/wallet_info.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/cash_fusion_interface.dart';
import '../../../../../wallets/wallet/wallet_mixin_interfaces/coin_control_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/ordinals_interface.dart';
import '../../../../../wallets/wallet/wallet_mixin_interfaces/paynym_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/custom_buttons/draggable_switch_button.dart';
import '../../../../../widgets/desktop/desktop_dialog.dart'; import '../../../../../widgets/desktop/desktop_dialog.dart';
import '../../../../../widgets/desktop/desktop_dialog_close_button.dart'; import '../../../../../widgets/desktop/desktop_dialog_close_button.dart';
@ -59,9 +61,26 @@ class MoreFeaturesDialog extends ConsumerStatefulWidget {
} }
class _MoreFeaturesDialogState extends ConsumerState<MoreFeaturesDialog> { class _MoreFeaturesDialogState extends ConsumerState<MoreFeaturesDialog> {
bool _enableLelantusScanning = false;
bool _isUpdatingLelantusScanning = false; // Mutex. bool _isUpdatingLelantusScanning = false; // Mutex.
Future<void> _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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final wallet = ref.watch( final wallet = ref.watch(
@ -70,14 +89,6 @@ class _MoreFeaturesDialogState extends ConsumerState<MoreFeaturesDialog> {
), ),
); );
// 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( final coinControlPrefEnabled = ref.watch(
prefsChangeNotifierProvider.select( prefsChangeNotifierProvider.select(
(value) => value.enableCoinControl, (value) => value.enableCoinControl,
@ -108,7 +119,7 @@ class _MoreFeaturesDialogState extends ConsumerState<MoreFeaturesDialog> {
label: "Anonymize funds", label: "Anonymize funds",
detail: "Anonymize funds", detail: "Anonymize funds",
iconAsset: Assets.svg.recycle, iconAsset: Assets.svg.recycle,
onPressed: () => widget.onAnonymizeAllPressed?.call(), onPressed: () async => widget.onAnonymizeAllPressed?.call(),
), ),
// TODO: [prio=med] // TODO: [prio=med]
// if (manager.hasWhirlpoolSupport) // if (manager.hasWhirlpoolSupport)
@ -123,93 +134,68 @@ class _MoreFeaturesDialogState extends ConsumerState<MoreFeaturesDialog> {
label: "Coin control", label: "Coin control",
detail: "Control, freeze, and utilize outputs at your discretion", detail: "Control, freeze, and utilize outputs at your discretion",
iconAsset: Assets.svg.coinControl.gamePad, iconAsset: Assets.svg.coinControl.gamePad,
onPressed: () => widget.onCoinControlPressed?.call(), onPressed: () async => widget.onCoinControlPressed?.call(),
), ),
if (wallet is PaynymInterface) if (wallet is PaynymInterface)
_MoreFeaturesItem( _MoreFeaturesItem(
label: "PayNym", label: "PayNym",
detail: "Increased address privacy using BIP47", detail: "Increased address privacy using BIP47",
iconAsset: Assets.svg.robotHead, iconAsset: Assets.svg.robotHead,
onPressed: () => widget.onPaynymPressed?.call(), onPressed: () async => widget.onPaynymPressed?.call(),
), ),
if (wallet is OrdinalsInterface) if (wallet is OrdinalsInterface)
_MoreFeaturesItem( _MoreFeaturesItem(
label: "Ordinals", label: "Ordinals",
detail: "View and control your ordinals in Stack", detail: "View and control your ordinals in Stack",
iconAsset: Assets.svg.ordinal, iconAsset: Assets.svg.ordinal,
onPressed: () => widget.onOrdinalsPressed?.call(), onPressed: () async => widget.onOrdinalsPressed?.call(),
), ),
if (wallet.info.coin is Banano) if (wallet.info.coin is Banano)
_MoreFeaturesItem( _MoreFeaturesItem(
label: "MonKey", label: "MonKey",
detail: "Generate Banano MonKey", detail: "Generate Banano MonKey",
iconAsset: Assets.svg.monkey, iconAsset: Assets.svg.monkey,
onPressed: () => widget.onMonkeyPressed?.call(), onPressed: () async => widget.onMonkeyPressed?.call(),
), ),
if (wallet is CashFusionInterface) if (wallet is CashFusionInterface)
_MoreFeaturesItem( _MoreFeaturesItem(
label: "Fusion", label: "Fusion",
detail: "Decentralized mixing protocol", detail: "Decentralized mixing protocol",
iconAsset: Assets.svg.cashFusion, iconAsset: Assets.svg.cashFusion,
onPressed: () => widget.onFusionPressed?.call(), onPressed: () async => widget.onFusionPressed?.call(),
), ),
if (wallet.info.coin is Firo) if (wallet is SparkInterface)
Padding( const _MoreFeaturesClearSparkCacheItem(),
padding: const EdgeInsets.symmetric( if (wallet is LelantusInterface)
vertical: 6, _MoreFeaturesItemBase(
horizontal: 32, child: Row(
), children: [
child: RoundedContainer( const SizedBox(width: 3),
color: Colors.transparent, SizedBox(
borderColor: Theme.of(context) height: 20,
.extension<StackColors>()! width: 40,
.textFieldDefaultBG, child: DraggableSwitchButton(
child: Row( isOn: ref.watch(
children: [ pWalletInfo(widget.walletId)
SizedBox(width: 3), .select((value) => value.otherData),
SizedBox( )[WalletInfoKeys.enableLelantusScanning] as bool? ??
height: 20, false,
width: 40, onValueChanged: _switchToggled,
child: DraggableSwitchButton( ),
isOn: _enableLelantusScanning, ),
onValueChanged: (newValue) async { const SizedBox(
if (_isUpdatingLelantusScanning) return; width: 16,
_isUpdatingLelantusScanning = true; // Lock mutex. ),
Column(
// Toggle enableLelantusScanning in wallet info. crossAxisAlignment: CrossAxisAlignment.start,
await wallet.info.updateOtherData( children: [
newEntries: { Text(
WalletInfoKeys.enableLelantusScanning: "Scan for Lelantus transactions",
!_enableLelantusScanning, style: STextStyles.w600_20(context),
},
isar: ref.read(mainDBProvider).isar,
);
setState(() {
_enableLelantusScanning = !_enableLelantusScanning;
_isUpdatingLelantusScanning = false; // Free mutex.
});
},
), ),
), ],
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( const SizedBox(
@ -221,7 +207,7 @@ class _MoreFeaturesDialogState extends ConsumerState<MoreFeaturesDialog> {
} }
} }
class _MoreFeaturesItem extends StatelessWidget { class _MoreFeaturesItem extends StatefulWidget {
const _MoreFeaturesItem({ const _MoreFeaturesItem({
super.key, super.key,
required this.label, required this.label,
@ -236,6 +222,78 @@ class _MoreFeaturesItem extends StatelessWidget {
final String label; final String label;
final String detail; final String detail;
final String iconAsset; final String iconAsset;
final Future<void> 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<StackColors>()!.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<StackColors>()!
.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; final VoidCallback? onPressed;
@override @override
@ -250,44 +308,89 @@ class _MoreFeaturesItem extends StatelessWidget {
borderColor: borderColor:
Theme.of(context).extension<StackColors>()!.textFieldDefaultBG, Theme.of(context).extension<StackColors>()!.textFieldDefaultBG,
onPressed: onPressed, onPressed: onPressed,
child: Row( child: child,
children: [ ),
RoundedContainer( );
padding: const EdgeInsets.all(0), }
color: }
Theme.of(context).extension<StackColors>()!.settingsIconBack,
width: iconSizeBG, class _MoreFeaturesClearSparkCacheItem extends StatefulWidget {
height: iconSizeBG, const _MoreFeaturesClearSparkCacheItem({
radiusMultiplier: iconSizeBG, super.key,
child: Center( });
child: SvgPicture.asset(
iconAsset, static const double iconSizeBG = 46;
width: iconSize, static const double iconSize = 24;
height: iconSize,
color: Theme.of(context) @override
.extension<StackColors>()! State<_MoreFeaturesClearSparkCacheItem> createState() =>
.settingsIconIcon, _MoreFeaturesClearSparkCacheItemState();
), }
),
), class _MoreFeaturesClearSparkCacheItemState
const SizedBox( extends State<_MoreFeaturesClearSparkCacheItem> {
width: 16, bool _onPressedLock = false;
),
Column( static const label = "Reset Spark electrumx cache";
crossAxisAlignment: CrossAxisAlignment.start,
children: [ @override
Text( Widget build(BuildContext context) {
label, return _MoreFeaturesItemBase(
style: STextStyles.w600_20(context), onPressed: () async {
), if (_onPressedLock) {
Text( return;
detail, }
style: STextStyles.desktopTextExtraExtraSmall(context), _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<StackColors>()!.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<StackColors>()!
.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),
);
},
),
],
),
],
), ),
); );
} }