From d6c609fea46325caeb3ee5775ed8cf5ae977baf9 Mon Sep 17 00:00:00 2001 From: julian Date: Wed, 31 Jul 2024 16:03:47 -0600 Subject: [PATCH] ask before enabling toggle --- .../wallet_settings_wallet_settings_view.dart | 225 +++++++++--------- .../more_features/more_features_dialog.dart | 225 +++++++++--------- .../draggable_switch_button.dart | 2 + 3 files changed, 232 insertions(+), 220 deletions(-) diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart index c02319dcc..e8dc5138e 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart @@ -17,7 +17,6 @@ import '../../../../route_generator.dart'; import '../../../../themes/stack_colors.dart'; import '../../../../utilities/constants.dart'; import '../../../../utilities/text_styles.dart'; -import '../../../../utilities/util.dart'; import '../../../../wallets/isar/models/wallet_info.dart'; import '../../../../wallets/isar/providers/wallet_info_provider.dart'; import '../../../../wallets/wallet/wallet_mixin_interfaces/lelantus_interface.dart'; @@ -53,78 +52,83 @@ class WalletSettingsWalletSettingsView extends ConsumerStatefulWidget { class _WalletSettingsWalletSettingsViewState extends ConsumerState { - bool _switchReuseAddressToggledLock = false; // Mutex. - Future _switchReuseAddressToggled(bool newValue) async { - if (newValue) { - await showDialog( - context: context, - builder: (context) { - final isDesktop = Util.isDesktop; - return StackDialog( - title: "Warning!", - message: - "Reusing addresses reduces your privacy and security. Are you sure you want to reuse addresses by default?", - leftButton: TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - child: Text( - "Cancel", - style: STextStyles.itemSubtitle12(context), - ), - onPressed: () { - Navigator.of(context).pop(false); - }, - ), - rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - child: Text( - "Continue", - style: STextStyles.button(context), - ), - onPressed: () { - Navigator.of(context).pop(true); - }, - ), - ); - }, - ).then((confirmed) async { - if (_switchReuseAddressToggledLock) { - return; - } - _switchReuseAddressToggledLock = true; // Lock mutex. + late final DSBController _switchController; - try { - if (confirmed == true) { - await ref.read(pWalletInfo(widget.walletId)).updateOtherData( - newEntries: { - WalletInfoKeys.reuseAddress: true, - }, - isar: ref.read(mainDBProvider).isar, - ); - } else { - await ref.read(pWalletInfo(widget.walletId)).updateOtherData( - newEntries: { - WalletInfoKeys.reuseAddress: false, - }, - isar: ref.read(mainDBProvider).isar, - ); - } - } finally { - // ensure _switchReuseAddressToggledLock is set to false no matter what. - _switchReuseAddressToggledLock = false; - } - }); - } else { - await ref.read(pWalletInfo(widget.walletId)).updateOtherData( - newEntries: { - WalletInfoKeys.reuseAddress: false, - }, - isar: ref.read(mainDBProvider).isar, - ); + bool _switchReuseAddressToggledLock = false; // Mutex. + Future _switchReuseAddressToggled() async { + if (_switchReuseAddressToggledLock) { + return; } + _switchReuseAddressToggledLock = true; // Lock mutex. + + try { + if (_switchController.isOn?.call() != true) { + final canContinue = await showDialog( + context: context, + builder: (context) { + return StackDialog( + title: "Warning!", + message: + "Reusing addresses reduces your privacy and security. Are you sure you want to reuse addresses by default?", + leftButton: TextButton( + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle(context), + child: Text( + "Cancel", + style: STextStyles.itemSubtitle12(context), + ), + onPressed: () { + Navigator.of(context).pop(false); + }, + ), + rightButton: TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + child: Text( + "Continue", + style: STextStyles.button(context), + ), + onPressed: () { + Navigator.of(context).pop(true); + }, + ), + ); + }, + ); + + if (canContinue == true) { + await _updateAddressReuse(true); + } + } else { + await _updateAddressReuse(false); + } + } finally { + // ensure _switchReuseAddressToggledLock is set to false no matter what. + _switchReuseAddressToggledLock = false; + } + } + + Future _updateAddressReuse(bool shouldReuse) async { + await ref.read(pWalletInfo(widget.walletId)).updateOtherData( + newEntries: { + WalletInfoKeys.reuseAddress: shouldReuse, + }, + isar: ref.read(mainDBProvider).isar, + ); + + if (_switchController.isOn != null) { + if (_switchController.isOn!.call() != shouldReuse) { + _switchController.activate?.call(); + } + } + } + + @override + void initState() { + _switchController = DSBController(); + super.initState(); } @override @@ -186,7 +190,7 @@ class _WalletSettingsWalletSettingsViewState ), ), if (ref.watch(pWallets).getWallet(widget.walletId) - is RbfInterface) + is RbfInterface) const SizedBox( height: 8, ), @@ -231,48 +235,47 @@ class _WalletSettingsWalletSettingsViewState if (ref.watch(pWallets).getWallet(widget.walletId) is MultiAddressInterface) RoundedWhiteContainer( - child: Consumer( - builder: (_, ref, __) { - return RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: - MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: _switchReuseAddressToggled, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12.0, + vertical: 20, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Reuse receiving address", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, ), - ), - onPressed: null, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Reuse receiving address", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, + SizedBox( + height: 20, + width: 40, + child: IgnorePointer( + child: DraggableSwitchButton( + isOn: ref.watch( + pWalletInfo(widget.walletId).select( + (value) => value.otherData, + ), + )[WalletInfoKeys.reuseAddress] as bool? ?? + false, + controller: _switchController, ), - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: ref.watch( - pWalletInfo(widget.walletId).select( - (value) => value.otherData), - )[WalletInfoKeys.reuseAddress] - as bool? ?? - false, - onValueChanged: (newValue) { - _switchReuseAddressToggled(newValue); - }, - ), - ), - ], + ), ), - ), - ); - }, + ], + ), + ), ), ), if (ref.watch(pWallets).getWallet(widget.walletId) 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 0eef9750d..f849b7b09 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 @@ -20,7 +20,6 @@ import '../../../../../providers/global/wallets_provider.dart'; import '../../../../../themes/stack_colors.dart'; import '../../../../../utilities/assets.dart'; import '../../../../../utilities/text_styles.dart'; -import '../../../../../utilities/util.dart'; import '../../../../../wallets/crypto_currency/crypto_currency.dart'; import '../../../../../wallets/isar/models/wallet_info.dart'; import '../../../../../wallets/isar/providers/wallet_info_provider.dart'; @@ -106,117 +105,122 @@ class _MoreFeaturesDialogState extends ConsumerState { } } + late final DSBController _switchController; + bool _switchReuseAddressToggledLock = false; // Mutex. - Future _switchReuseAddressToggled(bool newValue) async { - if (newValue) { - await showDialog( - context: context, - builder: (context) { - final isDesktop = Util.isDesktop; - return DesktopDialog( - maxWidth: 576, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Padding( - padding: const EdgeInsets.only(left: 32), - child: Text( - "Warning!", - style: STextStyles.desktopH3(context), - ), - ), - const DesktopDialogCloseButton(), - ], - ), - Padding( - padding: const EdgeInsets.only( - top: 8, - left: 32, - right: 32, - bottom: 32, - ), - child: Column( - mainAxisSize: MainAxisSize.min, + Future _switchReuseAddressToggled() async { + if (_switchReuseAddressToggledLock) { + return; + } + _switchReuseAddressToggledLock = true; // Lock mutex. + + try { + if (_switchController.isOn?.call() != true) { + final canContinue = await showDialog( + context: context, + builder: (context) { + return DesktopDialog( + maxWidth: 576, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Reusing addresses reduces your privacy and security. Are you sure you want to reuse addresses by default?", - style: STextStyles.desktopTextSmall(context), - ), - const SizedBox( - height: 43, - ), - Row( - children: [ - Expanded( - child: SecondaryButton( - buttonHeight: ButtonHeight.l, - onPressed: () { - Navigator.of(context).pop(false); - }, - label: "Cancel", - ), - ), - const SizedBox( - width: 16, - ), - Expanded( - child: PrimaryButton( - buttonHeight: ButtonHeight.l, - onPressed: () { - Navigator.of(context).pop(true); - }, - label: "Continue", - ), - ), - ], + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "Warning!", + style: STextStyles.desktopH3(context), + ), ), + const DesktopDialogCloseButton(), ], ), - ), - ], - ), - ); - }, - ).then((confirmed) async { - if (_switchReuseAddressToggledLock) { - return; - } - _switchReuseAddressToggledLock = true; // Lock mutex. + Padding( + padding: const EdgeInsets.only( + top: 8, + left: 32, + right: 32, + bottom: 32, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + "Reusing addresses reduces your privacy and security. Are you sure you want to reuse addresses by default?", + style: STextStyles.desktopTextSmall(context), + ), + const SizedBox( + height: 43, + ), + Row( + children: [ + Expanded( + child: SecondaryButton( + buttonHeight: ButtonHeight.l, + onPressed: () { + Navigator.of(context).pop(false); + }, + label: "Cancel", + ), + ), + const SizedBox( + width: 16, + ), + Expanded( + child: PrimaryButton( + buttonHeight: ButtonHeight.l, + onPressed: () { + Navigator.of(context).pop(true); + }, + label: "Continue", + ), + ), + ], + ), + ], + ), + ), + ], + ), + ); + }, + ); - try { - if (confirmed == true) { - await ref.read(pWalletInfo(widget.walletId)).updateOtherData( - newEntries: { - WalletInfoKeys.reuseAddress: true, - }, - isar: ref.read(mainDBProvider).isar, - ); - } else { - await ref.read(pWalletInfo(widget.walletId)).updateOtherData( - newEntries: { - WalletInfoKeys.reuseAddress: false, - }, - isar: ref.read(mainDBProvider).isar, - ); - } - } finally { - // ensure _switchReuseAddressToggledLock is set to false no matter what. - _switchReuseAddressToggledLock = false; + if (canContinue == true) { + await _updateAddressReuse(true); } - }); - } else { - await ref.read(pWalletInfo(widget.walletId)).updateOtherData( - newEntries: { - WalletInfoKeys.reuseAddress: false, - }, - isar: ref.read(mainDBProvider).isar, - ); + } else { + await _updateAddressReuse(false); + } + } finally { + // ensure _switchReuseAddressToggledLock is set to false no matter what. + _switchReuseAddressToggledLock = false; } } + Future _updateAddressReuse(bool shouldReuse) async { + await ref.read(pWalletInfo(widget.walletId)).updateOtherData( + newEntries: { + WalletInfoKeys.reuseAddress: shouldReuse, + }, + isar: ref.read(mainDBProvider).isar, + ); + + if (_switchController.isOn != null) { + if (_switchController.isOn!.call() != shouldReuse) { + _switchController.activate?.call(); + } + } + } + + @override + void initState() { + _switchController = DSBController(); + super.initState(); + } + @override Widget build(BuildContext context) { final wallet = ref.watch( @@ -370,19 +374,22 @@ class _MoreFeaturesDialogState extends ConsumerState { ), // reuseAddress preference. _MoreFeaturesItemBase( + onPressed: _switchReuseAddressToggled, 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.reuseAddress] as bool? ?? - false, - onValueChanged: _switchReuseAddressToggled, + child: IgnorePointer( + child: DraggableSwitchButton( + isOn: ref.watch( + pWalletInfo(widget.walletId) + .select((value) => value.otherData), + )[WalletInfoKeys.reuseAddress] as bool? ?? + false, + controller: _switchController, + ), ), ), const SizedBox( diff --git a/lib/widgets/custom_buttons/draggable_switch_button.dart b/lib/widgets/custom_buttons/draggable_switch_button.dart index 47e706704..064746c6f 100644 --- a/lib/widgets/custom_buttons/draggable_switch_button.dart +++ b/lib/widgets/custom_buttons/draggable_switch_button.dart @@ -77,6 +77,7 @@ class DraggableSwitchButtonState extends State { _enabled = widget.enabled; valueListener = _isOn ? ValueNotifier(1.0) : ValueNotifier(0.0); + widget.controller?.isOn = () => _isOn; widget.controller?.activate = () { _isOn = !_isOn; // widget.onValueChanged?.call(_isOn); @@ -212,4 +213,5 @@ class DraggableSwitchButtonState extends State { class DSBController { VoidCallback? activate; + bool Function()? isOn; }