diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart index 778a522a8..e8a79f0d6 100644 --- a/cw_bitcoin/lib/bitcoin_wallet.dart +++ b/cw_bitcoin/lib/bitcoin_wallet.dart @@ -36,6 +36,12 @@ part 'bitcoin_wallet.g.dart'; class BitcoinWallet = BitcoinWalletBase with _$BitcoinWallet; abstract class BitcoinWalletBase extends ElectrumWallet with Store { + @observable + bool silentPaymentsIntroDisplay; + + @observable + bool silentPaymentsCardDisplay; + @observable bool nodeSupportsSilentPayments = false; @@ -70,8 +76,12 @@ abstract class BitcoinWalletBase extends ElectrumWallet super.passphrase, super.initialUnspentCoins, bool? alwaysScan, + bool? silentPaymentsIntroDisplay, + bool? silentPaymentsCardDisplay, Map? walletAddressesSnapshot, }) : _alwaysScan = alwaysScan ?? false, + silentPaymentsIntroDisplay = silentPaymentsIntroDisplay ?? true, + silentPaymentsCardDisplay = silentPaymentsCardDisplay ?? true, super( currency: network == BitcoinNetwork.testnet ? CryptoCurrency.tbtc : CryptoCurrency.btc, ) { @@ -324,6 +334,8 @@ abstract class BitcoinWalletBase extends ElectrumWallet encryptionFileUtils: encryptionFileUtils, network: network, alwaysScan: snp?.alwaysScan, + silentPaymentsIntroDisplay: snp?.silentPaymentsIntroDisplay, + silentPaymentsCardDisplay: snp?.silentPaymentsCardDisplay, initialUnspentCoins: snp?.unspentCoins, walletAddressesSnapshot: snp?.walletAddressesSnapshot, hdWallets: hdWallets, @@ -1482,6 +1494,8 @@ abstract class BitcoinWalletBase extends ElectrumWallet String toJSON() { final json = jsonDecode(super.toJSON()); json['alwaysScan'] = _alwaysScan; + json['silentPaymentsIntroDisplay'] = silentPaymentsIntroDisplay; + json['silentPaymentsCardDisplay'] = silentPaymentsCardDisplay; return jsonEncode(json); } } diff --git a/cw_bitcoin/lib/bitcoin_wallet_snapshot.dart b/cw_bitcoin/lib/bitcoin_wallet_snapshot.dart index b722ac74c..5d76c23d7 100644 --- a/cw_bitcoin/lib/bitcoin_wallet_snapshot.dart +++ b/cw_bitcoin/lib/bitcoin_wallet_snapshot.dart @@ -15,6 +15,8 @@ class BitcoinWalletSnapshot extends ElectrumWalletSnapshot { required super.xpub, required super.balance, required this.alwaysScan, + required this.silentPaymentsIntroDisplay, + required this.silentPaymentsCardDisplay, required super.unspentCoins, required super.walletAddressesSnapshot, super.passphrase, @@ -23,6 +25,8 @@ class BitcoinWalletSnapshot extends ElectrumWalletSnapshot { }) : super(); bool alwaysScan; + bool silentPaymentsIntroDisplay; + bool silentPaymentsCardDisplay; static Future load( EncryptionFileUtils encryptionFileUtils, @@ -45,6 +49,8 @@ class BitcoinWalletSnapshot extends ElectrumWalletSnapshot { ); final alwaysScan = data['alwaysScan'] as bool? ?? false; + final silentPaymentsIntroDisplay = data['silentPaymentsIntroDisplay'] as bool? ?? true; + final silentPaymentsCardDisplay = data['silentPaymentsCardDisplay'] as bool? ?? true; final walletAddressesSnapshot = data['walletAddresses'] as Map? ?? BitcoinWalletAddressesBase.fromSnapshot(data); @@ -61,6 +67,8 @@ class BitcoinWalletSnapshot extends ElectrumWalletSnapshot { derivationPath: electrumWalletSnapshot.derivationPath, unspentCoins: electrumWalletSnapshot.unspentCoins, alwaysScan: alwaysScan, + silentPaymentsIntroDisplay: silentPaymentsIntroDisplay, + silentPaymentsCardDisplay: silentPaymentsCardDisplay, walletAddressesSnapshot: walletAddressesSnapshot, ); } diff --git a/lib/bitcoin/cw_bitcoin.dart b/lib/bitcoin/cw_bitcoin.dart index 74d17ac7a..a713f3139 100644 --- a/lib/bitcoin/cw_bitcoin.dart +++ b/lib/bitcoin/cw_bitcoin.dart @@ -770,4 +770,26 @@ class CWBitcoin extends Bitcoin { return null; } } + + bool getSilentPaymentsIntroDisplay(Object wallet) { + final bitcoinWallet = wallet as BitcoinWallet; + return bitcoinWallet.silentPaymentsIntroDisplay; + } + + void setSilentPaymentsIntroDisplay(Object wallet, bool val) { + final bitcoinWallet = wallet as BitcoinWallet; + bitcoinWallet.silentPaymentsIntroDisplay = val; + bitcoinWallet.save(); + } + + bool getSilentPaymentsCardDisplay(Object wallet) { + final bitcoinWallet = wallet as BitcoinWallet; + return bitcoinWallet.silentPaymentsCardDisplay; + } + + void setSilentPaymentsCardDisplay(Object wallet, bool val) { + final bitcoinWallet = wallet as BitcoinWallet; + bitcoinWallet.silentPaymentsCardDisplay = val; + bitcoinWallet.save(); + } } diff --git a/lib/src/screens/dashboard/pages/balance/crypto_balance_widget.dart b/lib/src/screens/dashboard/pages/balance/crypto_balance_widget.dart index 73890907d..28fd8774a 100644 --- a/lib/src/screens/dashboard/pages/balance/crypto_balance_widget.dart +++ b/lib/src/screens/dashboard/pages/balance/crypto_balance_widget.dart @@ -208,6 +208,44 @@ class CryptoBalanceWidget extends StatelessWidget { "\n\nPlease restart your wallet and if it doesn't help contact our support.", )) ], + if (dashboardViewModel.showSilentPaymentsEnable) ...[ + SizedBox(height: 16), + Padding( + padding: const EdgeInsets.fromLTRB(16, 0, 16, 8), + child: InfoCard( + title: S.of(context).silent_payments, + description: S.of(context).silent_payments_description, + leftButtonTitle: S.of(context).litecoin_mweb_dismiss, + rightButtonTitle: S.of(context).enable, + icon: Icon( + Icons.lock, + color: + Theme.of(context).extension()!.pageTitleTextColor, + size: 50, + ), + leftButtonAction: () => _dismissSilentPayments(context), + rightButtonAction: () => _enableSilentPayments(context), + hintWidget: GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () => launchUrl( + Uri.parse("https://docs.cakewallet.com/cryptos/bitcoin#silent-payments"), + mode: LaunchMode.externalApplication, + ), + child: Text( + S.of(context).learn_more, + style: TextStyle( + fontSize: 12, + fontFamily: 'Lato', + fontWeight: FontWeight.w400, + color: Theme.of(context).extension()!.labelTextColor, + height: 1, + ), + softWrap: true, + ), + ), + ), + ), + ], if (dashboardViewModel.showSilentPaymentsCard) ...[ SizedBox(height: 16), Padding( @@ -353,7 +391,8 @@ class CryptoBalanceWidget extends StatelessWidget { leftButtonTitle: S.of(context).litecoin_mweb_dismiss, rightButtonTitle: S.of(context).learn_more, leftButtonAction: () => dashboardViewModel.dismissDecredInfoCard(), - rightButtonAction: () => launchUrl(Uri.parse("https://docs.cakewallet.com/cryptos/decred/#spv-sync")), + rightButtonAction: () => launchUrl( + Uri.parse("https://docs.cakewallet.com/cryptos/decred/#spv-sync")), ), ), ], @@ -395,4 +434,22 @@ class CryptoBalanceWidget extends StatelessWidget { )); dashboardViewModel.dismissMweb(); } + + Future _enableSilentPayments(BuildContext context) async { + dashboardViewModel.setSilentPaymentsEnabled(); + } + + Future _dismissSilentPayments(BuildContext context) async { + await showPopUp( + context: context, + builder: (BuildContext context) => AlertWithOneAction( + alertTitle: S.of(context).alert_notice, + alertContent: S.of(context).silent_payments_enable_later, + buttonText: S.of(context).understand, + buttonAction: () { + Navigator.of(context).pop(); + }, + )); + dashboardViewModel.dismissSilentPayments(); + } } diff --git a/lib/src/screens/dashboard/widgets/info_card.dart b/lib/src/screens/dashboard/widgets/info_card.dart index 1bf8a11bf..a4c2a60f8 100644 --- a/lib/src/screens/dashboard/widgets/info_card.dart +++ b/lib/src/screens/dashboard/widgets/info_card.dart @@ -7,7 +7,8 @@ class InfoCard extends StatelessWidget { final String rightButtonTitle; final String title; final String description; - final String image; + final String? image; + final Icon? icon; final Function() leftButtonAction; final Function() rightButtonAction; @@ -22,7 +23,8 @@ class InfoCard extends StatelessWidget { required this.rightButtonTitle, required this.leftButtonAction, required this.rightButtonAction, - required this.image, + this.image, + this.icon, this.hintWidget, }) : super(key: key); @@ -72,17 +74,18 @@ class InfoCard extends StatelessWidget { ], ), onTap: () => {}, - icon: Container( - decoration: BoxDecoration( - color: Colors.white, - shape: BoxShape.circle, - ), - child: CakeImageWidget( - imageUrl: image, - height: 40, - width: 40, - ), - ), + icon: icon ?? + Container( + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle, + ), + child: CakeImageWidget( + imageUrl: image!, + height: 40, + width: 40, + ), + ), ); } } diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart index 100208464..af83d7598 100644 --- a/lib/view_model/dashboard/dashboard_view_model.dart +++ b/lib/view_model/dashboard/dashboard_view_model.dart @@ -489,8 +489,43 @@ abstract class DashboardViewModelBase with Store { @computed bool get hasSilentPayments => wallet.type == WalletType.bitcoin && !wallet.isHardwareWallet; + @observable + bool? silentPaymentsEnabled; + @computed - bool get showSilentPaymentsCard => hasSilentPayments && settingsStore.silentPaymentsCardDisplay; + bool get showSilentPaymentsEnable => + hasSilentPayments && + silentPaymentsEnabled == null && + bitcoin!.getSilentPaymentsIntroDisplay(wallet) && + bitcoin!.getSilentPaymentsCardDisplay(wallet); + + @computed + bool get showSilentPaymentsCard => + hasSilentPayments && + !showSilentPaymentsEnable && + bitcoin!.getSilentPaymentsCardDisplay(wallet); + + @action + void setSilentPaymentsEnabled() { + if (!hasSilentPayments) { + return; + } + + silentPaymentsEnabled = true; + bitcoin!.setSilentPaymentsIntroDisplay(wallet, false); + bitcoin!.setSilentPaymentsCardDisplay(wallet, true); + } + + @action + void dismissSilentPayments() { + if (!hasSilentPayments) { + return; + } + + silentPaymentsEnabled = false; + bitcoin!.setSilentPaymentsIntroDisplay(wallet, false); + bitcoin!.setSilentPaymentsCardDisplay(wallet, false); + } final KeyService keyService; final SharedPreferences sharedPreferences; diff --git a/tool/configure.dart b/tool/configure.dart index 48f2af596..dee821580 100644 --- a/tool/configure.dart +++ b/tool/configure.dart @@ -295,6 +295,10 @@ abstract class Bitcoin { bool getMwebEnabled(Object wallet); String? getUnusedMwebAddress(Object wallet); String? getUnusedSegwitAddress(Object wallet); + bool getSilentPaymentsIntroDisplay(Object wallet); + void setSilentPaymentsIntroDisplay(Object wallet, bool val); + bool getSilentPaymentsCardDisplay(Object wallet); + void setSilentPaymentsCardDisplay(Object wallet, bool val); } """;