feat: add enable sp card and make setting wallet specific

This commit is contained in:
Rafael Saes 2025-04-28 16:32:36 -03:00
parent ebe7e3e94f
commit fe7e419b42
7 changed files with 158 additions and 15 deletions

View file

@ -36,6 +36,12 @@ part 'bitcoin_wallet.g.dart';
class BitcoinWallet = BitcoinWalletBase with _$BitcoinWallet; class BitcoinWallet = BitcoinWalletBase with _$BitcoinWallet;
abstract class BitcoinWalletBase extends ElectrumWallet<BitcoinWalletAddresses> with Store { abstract class BitcoinWalletBase extends ElectrumWallet<BitcoinWalletAddresses> with Store {
@observable
bool silentPaymentsIntroDisplay;
@observable
bool silentPaymentsCardDisplay;
@observable @observable
bool nodeSupportsSilentPayments = false; bool nodeSupportsSilentPayments = false;
@ -70,8 +76,12 @@ abstract class BitcoinWalletBase extends ElectrumWallet<BitcoinWalletAddresses>
super.passphrase, super.passphrase,
super.initialUnspentCoins, super.initialUnspentCoins,
bool? alwaysScan, bool? alwaysScan,
bool? silentPaymentsIntroDisplay,
bool? silentPaymentsCardDisplay,
Map<String, dynamic>? walletAddressesSnapshot, Map<String, dynamic>? walletAddressesSnapshot,
}) : _alwaysScan = alwaysScan ?? false, }) : _alwaysScan = alwaysScan ?? false,
silentPaymentsIntroDisplay = silentPaymentsIntroDisplay ?? true,
silentPaymentsCardDisplay = silentPaymentsCardDisplay ?? true,
super( super(
currency: network == BitcoinNetwork.testnet ? CryptoCurrency.tbtc : CryptoCurrency.btc, currency: network == BitcoinNetwork.testnet ? CryptoCurrency.tbtc : CryptoCurrency.btc,
) { ) {
@ -324,6 +334,8 @@ abstract class BitcoinWalletBase extends ElectrumWallet<BitcoinWalletAddresses>
encryptionFileUtils: encryptionFileUtils, encryptionFileUtils: encryptionFileUtils,
network: network, network: network,
alwaysScan: snp?.alwaysScan, alwaysScan: snp?.alwaysScan,
silentPaymentsIntroDisplay: snp?.silentPaymentsIntroDisplay,
silentPaymentsCardDisplay: snp?.silentPaymentsCardDisplay,
initialUnspentCoins: snp?.unspentCoins, initialUnspentCoins: snp?.unspentCoins,
walletAddressesSnapshot: snp?.walletAddressesSnapshot, walletAddressesSnapshot: snp?.walletAddressesSnapshot,
hdWallets: hdWallets, hdWallets: hdWallets,
@ -1482,6 +1494,8 @@ abstract class BitcoinWalletBase extends ElectrumWallet<BitcoinWalletAddresses>
String toJSON() { String toJSON() {
final json = jsonDecode(super.toJSON()); final json = jsonDecode(super.toJSON());
json['alwaysScan'] = _alwaysScan; json['alwaysScan'] = _alwaysScan;
json['silentPaymentsIntroDisplay'] = silentPaymentsIntroDisplay;
json['silentPaymentsCardDisplay'] = silentPaymentsCardDisplay;
return jsonEncode(json); return jsonEncode(json);
} }
} }

View file

@ -15,6 +15,8 @@ class BitcoinWalletSnapshot extends ElectrumWalletSnapshot {
required super.xpub, required super.xpub,
required super.balance, required super.balance,
required this.alwaysScan, required this.alwaysScan,
required this.silentPaymentsIntroDisplay,
required this.silentPaymentsCardDisplay,
required super.unspentCoins, required super.unspentCoins,
required super.walletAddressesSnapshot, required super.walletAddressesSnapshot,
super.passphrase, super.passphrase,
@ -23,6 +25,8 @@ class BitcoinWalletSnapshot extends ElectrumWalletSnapshot {
}) : super(); }) : super();
bool alwaysScan; bool alwaysScan;
bool silentPaymentsIntroDisplay;
bool silentPaymentsCardDisplay;
static Future<BitcoinWalletSnapshot> load( static Future<BitcoinWalletSnapshot> load(
EncryptionFileUtils encryptionFileUtils, EncryptionFileUtils encryptionFileUtils,
@ -45,6 +49,8 @@ class BitcoinWalletSnapshot extends ElectrumWalletSnapshot {
); );
final alwaysScan = data['alwaysScan'] as bool? ?? false; 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<String, dynamic>? ?? final walletAddressesSnapshot = data['walletAddresses'] as Map<String, dynamic>? ??
BitcoinWalletAddressesBase.fromSnapshot(data); BitcoinWalletAddressesBase.fromSnapshot(data);
@ -61,6 +67,8 @@ class BitcoinWalletSnapshot extends ElectrumWalletSnapshot {
derivationPath: electrumWalletSnapshot.derivationPath, derivationPath: electrumWalletSnapshot.derivationPath,
unspentCoins: electrumWalletSnapshot.unspentCoins, unspentCoins: electrumWalletSnapshot.unspentCoins,
alwaysScan: alwaysScan, alwaysScan: alwaysScan,
silentPaymentsIntroDisplay: silentPaymentsIntroDisplay,
silentPaymentsCardDisplay: silentPaymentsCardDisplay,
walletAddressesSnapshot: walletAddressesSnapshot, walletAddressesSnapshot: walletAddressesSnapshot,
); );
} }

View file

@ -770,4 +770,26 @@ class CWBitcoin extends Bitcoin {
return null; 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();
}
} }

View file

@ -208,6 +208,44 @@ class CryptoBalanceWidget extends StatelessWidget {
"\n\nPlease restart your wallet and if it doesn't help contact our support.", "\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<DashboardPageTheme>()!.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<BalancePageTheme>()!.labelTextColor,
height: 1,
),
softWrap: true,
),
),
),
),
],
if (dashboardViewModel.showSilentPaymentsCard) ...[ if (dashboardViewModel.showSilentPaymentsCard) ...[
SizedBox(height: 16), SizedBox(height: 16),
Padding( Padding(
@ -353,7 +391,8 @@ class CryptoBalanceWidget extends StatelessWidget {
leftButtonTitle: S.of(context).litecoin_mweb_dismiss, leftButtonTitle: S.of(context).litecoin_mweb_dismiss,
rightButtonTitle: S.of(context).learn_more, rightButtonTitle: S.of(context).learn_more,
leftButtonAction: () => dashboardViewModel.dismissDecredInfoCard(), 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(); dashboardViewModel.dismissMweb();
} }
Future<void> _enableSilentPayments(BuildContext context) async {
dashboardViewModel.setSilentPaymentsEnabled();
}
Future<void> _dismissSilentPayments(BuildContext context) async {
await showPopUp<void>(
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();
}
} }

View file

@ -7,7 +7,8 @@ class InfoCard extends StatelessWidget {
final String rightButtonTitle; final String rightButtonTitle;
final String title; final String title;
final String description; final String description;
final String image; final String? image;
final Icon? icon;
final Function() leftButtonAction; final Function() leftButtonAction;
final Function() rightButtonAction; final Function() rightButtonAction;
@ -22,7 +23,8 @@ class InfoCard extends StatelessWidget {
required this.rightButtonTitle, required this.rightButtonTitle,
required this.leftButtonAction, required this.leftButtonAction,
required this.rightButtonAction, required this.rightButtonAction,
required this.image, this.image,
this.icon,
this.hintWidget, this.hintWidget,
}) : super(key: key); }) : super(key: key);
@ -72,17 +74,18 @@ class InfoCard extends StatelessWidget {
], ],
), ),
onTap: () => {}, onTap: () => {},
icon: Container( icon: icon ??
decoration: BoxDecoration( Container(
color: Colors.white, decoration: BoxDecoration(
shape: BoxShape.circle, color: Colors.white,
), shape: BoxShape.circle,
child: CakeImageWidget( ),
imageUrl: image, child: CakeImageWidget(
height: 40, imageUrl: image!,
width: 40, height: 40,
), width: 40,
), ),
),
); );
} }
} }

View file

@ -489,8 +489,43 @@ abstract class DashboardViewModelBase with Store {
@computed @computed
bool get hasSilentPayments => wallet.type == WalletType.bitcoin && !wallet.isHardwareWallet; bool get hasSilentPayments => wallet.type == WalletType.bitcoin && !wallet.isHardwareWallet;
@observable
bool? silentPaymentsEnabled;
@computed @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 KeyService keyService;
final SharedPreferences sharedPreferences; final SharedPreferences sharedPreferences;

View file

@ -295,6 +295,10 @@ abstract class Bitcoin {
bool getMwebEnabled(Object wallet); bool getMwebEnabled(Object wallet);
String? getUnusedMwebAddress(Object wallet); String? getUnusedMwebAddress(Object wallet);
String? getUnusedSegwitAddress(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);
} }
"""; """;