mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-06-28 12:29:51 +00:00
CW-1076-payjoin-ux-enhancements (#2282)
* feat: Add Payjoin Unavailable bottom sheet * feat: Add Payjoin Info Card to Dashboard * feat: Open payjoin docs on learn more
This commit is contained in:
parent
1aac17676d
commit
939e5d9279
36 changed files with 480 additions and 149 deletions
|
@ -83,6 +83,7 @@ class PreferencesKey {
|
|||
static const lookupsENS = 'looks_up_ens';
|
||||
static const lookupsWellKnown = 'looks_up_well_known';
|
||||
static const usePayjoin = 'use_payjoin';
|
||||
static const showPayjoinCard = 'show_payjoin_card';
|
||||
static const showCameraConsent = 'show_camera_consent';
|
||||
static const showDecredInfoCard = 'show_decred_info_card';
|
||||
|
||||
|
|
|
@ -150,13 +150,13 @@ class AddressPage extends BasePage {
|
|||
Expanded(
|
||||
child: Observer(
|
||||
builder: (_) => QRWidget(
|
||||
formKey: _formKey,
|
||||
addressListViewModel: addressListViewModel,
|
||||
amountTextFieldFocusNode: _cryptoAmountFocus,
|
||||
amountController: _amountController,
|
||||
isLight: dashboardViewModel.settingsStore.currentTheme.type ==
|
||||
ThemeType.light,
|
||||
))),
|
||||
formKey: _formKey,
|
||||
addressListViewModel: addressListViewModel,
|
||||
amountTextFieldFocusNode: _cryptoAmountFocus,
|
||||
amountController: _amountController,
|
||||
currentTheme:
|
||||
dashboardViewModel.settingsStore.currentTheme,
|
||||
))),
|
||||
SizedBox(height: 16),
|
||||
Observer(builder: (_) {
|
||||
if (addressListViewModel.hasAddressList) {
|
||||
|
|
|
@ -325,6 +325,39 @@ class CryptoBalanceWidget extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
],
|
||||
if (dashboardViewModel.showPayjoinCard) ...[
|
||||
SizedBox(height: 10),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 0, 16, 8),
|
||||
child: InfoCard(
|
||||
title: "Payjoin",
|
||||
description: S.of(context).payjoin_card_content,
|
||||
hintWidget: GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () => launchUrl(
|
||||
Uri.parse("https://docs.cakewallet.com/cryptos/bitcoin/#payjoin"),
|
||||
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,
|
||||
),
|
||||
),
|
||||
image: 'assets/images/payjoin.png',
|
||||
leftButtonTitle: S.of(context).litecoin_mweb_dismiss,
|
||||
rightButtonTitle: S.of(context).enable,
|
||||
leftButtonAction: () => dashboardViewModel.dismissPayjoin(),
|
||||
rightButtonAction: () => _enablePayjoin(context),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
}),
|
||||
|
@ -363,6 +396,21 @@ class CryptoBalanceWidget extends StatelessWidget {
|
|||
}
|
||||
|
||||
return dashboardViewModel.setSilentPaymentsScanning(newValue);
|
||||
}
|
||||
|
||||
void _enablePayjoin(BuildContext context) {
|
||||
showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) => AlertWithOneAction(
|
||||
alertTitle: S.of(context).payjoin_enabling_popup_title,
|
||||
alertContent: S.of(context).payjoin_enabling_popup_content,
|
||||
buttonText: S.of(context).ok,
|
||||
buttonAction: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
));
|
||||
|
||||
dashboardViewModel.enablePayjoin();
|
||||
}
|
||||
|
||||
Future<void> _enableMweb(BuildContext context) async {
|
||||
|
|
|
@ -1,29 +1,14 @@
|
|||
import 'package:cake_wallet/src/screens/nano_accounts/nano_account_list_page.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/screens/receive/widgets/address_list.dart';
|
||||
import 'package:cake_wallet/src/screens/receive/widgets/qr_widget.dart';
|
||||
import 'package:cake_wallet/src/widgets/gradient_background.dart';
|
||||
import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
|
||||
import 'package:cake_wallet/themes/extensions/balance_page_theme.dart';
|
||||
import 'package:cake_wallet/themes/extensions/keyboard_theme.dart';
|
||||
import 'package:cake_wallet/themes/extensions/receive_page_theme.dart';
|
||||
import 'package:cake_wallet/src/widgets/gradient_background.dart';
|
||||
import 'package:cake_wallet/src/widgets/section_divider.dart';
|
||||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
import 'package:cake_wallet/utils/share_util.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/screens/monero_accounts/monero_account_list_page.dart';
|
||||
import 'package:cake_wallet/src/screens/receive/widgets/header_tile.dart';
|
||||
import 'package:cake_wallet/src/screens/receive/widgets/address_cell.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_address_list/wallet_account_list_header.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_header.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_item.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart';
|
||||
import 'package:cake_wallet/src/screens/receive/widgets/qr_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:keyboard_actions/keyboard_actions.dart';
|
||||
|
||||
class ReceivePage extends BasePage {
|
||||
|
@ -55,24 +40,23 @@ class ReceivePage extends BasePage {
|
|||
final FocusNode _cryptoAmountFocus;
|
||||
|
||||
@override
|
||||
Widget middle(BuildContext context) {
|
||||
return Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
Widget middle(BuildContext context) => Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontSize: 18.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontFamily: 'Lato',
|
||||
color: pageIconColor(context)),
|
||||
);
|
||||
}
|
||||
color: pageIconColor(context),
|
||||
),
|
||||
);
|
||||
|
||||
@override
|
||||
Widget Function(BuildContext, Widget) get rootWrapper =>
|
||||
(BuildContext context, Widget scaffold) => GradientBackground(scaffold: scaffold);
|
||||
(BuildContext context, Widget scaffold) =>
|
||||
GradientBackground(scaffold: scaffold);
|
||||
|
||||
@override
|
||||
Widget trailing(BuildContext context) {
|
||||
return Material(
|
||||
Widget trailing(BuildContext context) => Material(
|
||||
color: Colors.transparent,
|
||||
child: Semantics(
|
||||
label: S.of(context).share,
|
||||
|
@ -82,27 +66,25 @@ class ReceivePage extends BasePage {
|
|||
highlightColor: Colors.transparent,
|
||||
splashColor: Colors.transparent,
|
||||
iconSize: 25,
|
||||
onPressed: () {
|
||||
ShareUtil.share(
|
||||
text: addressListViewModel.uri.toString(),
|
||||
context: context,
|
||||
);
|
||||
},
|
||||
onPressed: () => ShareUtil.share(
|
||||
text: addressListViewModel.uri.toString(),
|
||||
context: context,
|
||||
),
|
||||
icon: Icon(
|
||||
Icons.share,
|
||||
size: 20,
|
||||
color: pageIconColor(context),
|
||||
),
|
||||
),
|
||||
));
|
||||
}
|
||||
),
|
||||
);
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
return KeyboardActions(
|
||||
Widget body(BuildContext context) => KeyboardActions(
|
||||
config: KeyboardActionsConfig(
|
||||
keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
|
||||
keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor,
|
||||
keyboardBarColor:
|
||||
Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor,
|
||||
nextFocus: false,
|
||||
actions: [
|
||||
KeyboardActionsItem(
|
||||
|
@ -121,23 +103,28 @@ class ReceivePage extends BasePage {
|
|||
heroTag: _heroTag,
|
||||
amountTextFieldFocusNode: _cryptoAmountFocus,
|
||||
amountController: _amountController,
|
||||
isLight: currentTheme.type == ThemeType.light,
|
||||
),
|
||||
currentTheme: currentTheme),
|
||||
),
|
||||
AddressList(addressListViewModel: addressListViewModel, currentTheme: currentTheme),
|
||||
AddressList(
|
||||
addressListViewModel: addressListViewModel,
|
||||
currentTheme: currentTheme),
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(24, 24, 24, 32),
|
||||
child: Text(
|
||||
addressListViewModel.isSilentPayments
|
||||
? S.of(context).silent_payments_disclaimer
|
||||
: S.of(context).electrum_address_disclaimer,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
color: Theme.of(context).extension<BalancePageTheme>()!.labelTextColor)),
|
||||
addressListViewModel.isSilentPayments
|
||||
? S.of(context).silent_payments_disclaimer
|
||||
: S.of(context).electrum_address_disclaimer,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
color: Theme.of(context)
|
||||
.extension<BalancePageTheme>()!
|
||||
.labelTextColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
));
|
||||
}
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,30 +1,32 @@
|
|||
import 'package:cake_wallet/entities/qr_view_data.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
|
||||
import 'package:cake_wallet/themes/extensions/picker_theme.dart';
|
||||
import 'package:cake_wallet/themes/extensions/qr_code_theme.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/exchange/widgets/currency_picker.dart';
|
||||
import 'package:cake_wallet/src/screens/receive/widgets/currency_input_field.dart';
|
||||
import 'package:cake_wallet/src/screens/receive/widgets/qr_image.dart';
|
||||
import 'package:cake_wallet/src/widgets/bottom_sheet/info_bottom_sheet_widget.dart';
|
||||
import 'package:cake_wallet/src/widgets/primary_button.dart';
|
||||
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
|
||||
import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart';
|
||||
import 'package:cake_wallet/themes/extensions/picker_theme.dart';
|
||||
import 'package:cake_wallet/themes/extensions/qr_code_theme.dart';
|
||||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
import 'package:cake_wallet/utils/address_formatter.dart';
|
||||
import 'package:cake_wallet/utils/brightness_util.dart';
|
||||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
||||
import 'package:cake_wallet/utils/show_bar.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/screens/receive/widgets/qr_image.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart';
|
||||
import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class QRWidget extends StatelessWidget {
|
||||
QRWidget({
|
||||
required this.addressListViewModel,
|
||||
required this.isLight,
|
||||
required this.currentTheme,
|
||||
this.qrVersion,
|
||||
this.heroTag,
|
||||
required this.amountController,
|
||||
|
@ -36,7 +38,7 @@ class QRWidget extends StatelessWidget {
|
|||
final TextEditingController amountController;
|
||||
final FocusNode? amountTextFieldFocusNode;
|
||||
final GlobalKey<FormState> formKey;
|
||||
final bool isLight;
|
||||
final ThemeBase currentTheme;
|
||||
final int? qrVersion;
|
||||
final String? heroTag;
|
||||
|
||||
|
@ -47,11 +49,14 @@ class QRWidget extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final copyImage = Image.asset('assets/images/copy_address.png',
|
||||
color: Theme.of(context).extension<QRCodeTheme>()!.qrWidgetCopyButtonColor);
|
||||
color: Theme.of(context)
|
||||
.extension<QRCodeTheme>()!
|
||||
.qrWidgetCopyButtonColor);
|
||||
|
||||
// This magic number for wider screen sets the text input focus at center of the inputfield
|
||||
final _width =
|
||||
responsiveLayoutUtil.shouldRenderMobileUI ? MediaQuery.of(context).size.width : 500;
|
||||
final _width = responsiveLayoutUtil.shouldRenderMobileUI
|
||||
? MediaQuery.of(context).size.width
|
||||
: 500;
|
||||
|
||||
return Center(
|
||||
child: SingleChildScrollView(
|
||||
|
@ -69,7 +74,9 @@ class QRWidget extends StatelessWidget {
|
|||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context).extension<DashboardPageTheme>()!.textColor),
|
||||
color: Theme.of(context)
|
||||
.extension<DashboardPageTheme>()!
|
||||
.textColor),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
|
@ -82,7 +89,8 @@ class QRWidget extends StatelessWidget {
|
|||
onTap: () {
|
||||
BrightnessUtil.changeBrightnessForFunction(
|
||||
() async {
|
||||
await Navigator.pushNamed(context, Routes.fullscreenQR,
|
||||
await Navigator.pushNamed(
|
||||
context, Routes.fullscreenQR,
|
||||
arguments: QrViewData(
|
||||
data: addressUri.toString(),
|
||||
heroTag: heroTag,
|
||||
|
@ -97,7 +105,8 @@ class QRWidget extends StatelessWidget {
|
|||
padding: EdgeInsets.zero,
|
||||
decoration: BoxDecoration(
|
||||
border: Border(top: BorderSide.none),
|
||||
borderRadius: BorderRadius.all(Radius.circular(5)),
|
||||
borderRadius:
|
||||
BorderRadius.all(Radius.circular(5)),
|
||||
color: Colors.white,
|
||||
),
|
||||
child: Column(
|
||||
|
@ -111,10 +120,64 @@ class QRWidget extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
),
|
||||
if (addressListViewModel.payjoinEndpoint.isNotEmpty &&
|
||||
!addressListViewModel.isSilentPayments) ...[
|
||||
if (addressListViewModel
|
||||
.isPayjoinUnavailable &&
|
||||
!addressListViewModel
|
||||
.isSilentPayments) ...[
|
||||
GestureDetector(
|
||||
onTap: () =>
|
||||
_onPayjoinInactivePressed(context),
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(
|
||||
top: 4,
|
||||
bottom: 4,
|
||||
right: 4,
|
||||
),
|
||||
child: Image.asset(
|
||||
'assets/images/payjoin.png',
|
||||
width: 20,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
S.of(context).payjoin_unavailable,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Color.fromARGB(
|
||||
255, 139, 137, 139),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(
|
||||
top: 4,
|
||||
bottom: 4,
|
||||
left: 4,
|
||||
),
|
||||
child: CircleAvatar(
|
||||
radius: 7,
|
||||
backgroundColor: Colors.black,
|
||||
child: Icon(
|
||||
Icons.question_mark,
|
||||
size: 10,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
if (addressListViewModel
|
||||
.payjoinEndpoint.isNotEmpty &&
|
||||
!addressListViewModel
|
||||
.isSilentPayments) ...[
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.center,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(
|
||||
|
@ -151,37 +214,43 @@ class QRWidget extends StatelessWidget {
|
|||
),
|
||||
],
|
||||
),
|
||||
Observer(builder: (_) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Form(
|
||||
key: formKey,
|
||||
child: CurrencyAmountTextField(
|
||||
selectedCurrency: _currencyName,
|
||||
amountFocusNode: amountTextFieldFocusNode,
|
||||
amountController: amountController,
|
||||
padding: EdgeInsets.only(top: 20, left: _width / 4),
|
||||
currentTheme: isLight ? ThemeType.light : ThemeType.dark,
|
||||
isAmountEditable: true,
|
||||
tag: addressListViewModel.selectedCurrency.tag,
|
||||
onTapPicker: () => _presentPicker(context),
|
||||
isPickerEnable: true)),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
Divider(height: 1, color: Theme.of(context).extension<PickerTheme>()!.dividerColor),
|
||||
Observer(
|
||||
builder: (_) => Padding(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Form(
|
||||
key: formKey,
|
||||
child: CurrencyAmountTextField(
|
||||
selectedCurrency: _currencyName,
|
||||
amountFocusNode: amountTextFieldFocusNode,
|
||||
amountController: amountController,
|
||||
padding:
|
||||
EdgeInsets.only(top: 20, left: _width / 4),
|
||||
currentTheme: currentTheme.type,
|
||||
isAmountEditable: true,
|
||||
tag: addressListViewModel.selectedCurrency.tag,
|
||||
onTapPicker: () => _presentPicker(context),
|
||||
isPickerEnable: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)),
|
||||
Divider(
|
||||
height: 1,
|
||||
color:
|
||||
Theme.of(context).extension<PickerTheme>()!.dividerColor),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 20, bottom: 8),
|
||||
child: Builder(
|
||||
builder: (context) => Observer(
|
||||
builder: (context) => GestureDetector(
|
||||
onTap: () {
|
||||
Clipboard.setData(ClipboardData(text: addressUri.address));
|
||||
Clipboard.setData(
|
||||
ClipboardData(text: addressUri.address));
|
||||
showBar<void>(context, S.of(context).copied_to_clipboard);
|
||||
},
|
||||
child: Row(
|
||||
|
@ -189,17 +258,16 @@ class QRWidget extends StatelessWidget {
|
|||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: AddressFormatter.buildSegmentedAddress(
|
||||
address: addressUri.address,
|
||||
walletType: addressListViewModel.type,
|
||||
textAlign: TextAlign.center,
|
||||
evenTextStyle: TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context).extension<DashboardPageTheme>()!.textColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: AddressFormatter.buildSegmentedAddress(
|
||||
address: addressUri.address,
|
||||
walletType: addressListViewModel.type,
|
||||
textAlign: TextAlign.center,
|
||||
evenTextStyle: TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context)
|
||||
.extension<DashboardPageTheme>()!
|
||||
.textColor))),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 12),
|
||||
child: copyImage,
|
||||
|
@ -212,12 +280,14 @@ class QRWidget extends StatelessWidget {
|
|||
),
|
||||
Observer(
|
||||
builder: (_) => Offstage(
|
||||
offstage: addressListViewModel.payjoinEndpoint.isEmpty || addressListViewModel.isSilentPayments,
|
||||
offstage: addressListViewModel.payjoinEndpoint.isEmpty ||
|
||||
addressListViewModel.isSilentPayments,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(top: 12),
|
||||
child: PrimaryImageButton(
|
||||
onPressed: () {
|
||||
Clipboard.setData(ClipboardData(text: addressUri.toString()));
|
||||
Clipboard.setData(
|
||||
ClipboardData(text: addressUri.toString()));
|
||||
showBar<void>(context, S.of(context).copied_to_clipboard);
|
||||
},
|
||||
image: Image.asset(
|
||||
|
@ -226,7 +296,9 @@ class QRWidget extends StatelessWidget {
|
|||
),
|
||||
text: S.of(context).copy_payjoin_address,
|
||||
color: Theme.of(context).cardColor,
|
||||
textColor: Theme.of(context).extension<CakeTextTheme>()!.buttonTextColor,
|
||||
textColor: Theme.of(context)
|
||||
.extension<CakeTextTheme>()!
|
||||
.buttonTextColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -239,7 +311,9 @@ class QRWidget extends StatelessWidget {
|
|||
|
||||
String get _currencyName {
|
||||
if (addressListViewModel.selectedCurrency is CryptoCurrency) {
|
||||
return (addressListViewModel.selectedCurrency as CryptoCurrency).title.toUpperCase();
|
||||
return (addressListViewModel.selectedCurrency as CryptoCurrency)
|
||||
.title
|
||||
.toUpperCase();
|
||||
}
|
||||
return addressListViewModel.selectedCurrency.name.toUpperCase();
|
||||
}
|
||||
|
@ -257,4 +331,23 @@ class QRWidget extends StatelessWidget {
|
|||
// update amount if currency changed
|
||||
addressListViewModel.changeAmount(amountController.text);
|
||||
}
|
||||
|
||||
void _onPayjoinInactivePressed(BuildContext context) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (context) => InfoBottomSheet(
|
||||
titleText: S.of(context).payjoin_unavailable_sheet_title,
|
||||
content: S.of(context).payjoin_unavailable_sheet_content,
|
||||
currentTheme: currentTheme,
|
||||
isTwoAction: true,
|
||||
leftButtonText: S.of(context).learn_more,
|
||||
actionLeftButton: () => launchUrl(
|
||||
Uri.parse("https://docs.cakewallet.com/cryptos/bitcoin/#payjoin"),
|
||||
mode: LaunchMode.externalApplication,
|
||||
),
|
||||
rightButtonText: S.of(context).ok,
|
||||
actionRightButton: () => Navigator.of(context).pop(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -122,6 +122,7 @@ abstract class SettingsStoreBase with Store {
|
|||
required this.lookupsENS,
|
||||
required this.lookupsWellKnown,
|
||||
required this.usePayjoin,
|
||||
required this.showPayjoinCard,
|
||||
required this.customBitcoinFeeRate,
|
||||
required this.silentPaymentsCardDisplay,
|
||||
required this.silentPaymentsAlwaysScan,
|
||||
|
@ -489,6 +490,11 @@ abstract class SettingsStoreBase with Store {
|
|||
(bool usePayjoin) =>
|
||||
_sharedPreferences.setBool(PreferencesKey.usePayjoin, usePayjoin));
|
||||
|
||||
reaction(
|
||||
(_) => showPayjoinCard,
|
||||
(bool showPayjoinCard) => _sharedPreferences.setBool(
|
||||
PreferencesKey.showPayjoinCard, showPayjoinCard));
|
||||
|
||||
// secure storage keys:
|
||||
reaction(
|
||||
(_) => allowBiometricalAuthentication,
|
||||
|
@ -811,6 +817,9 @@ abstract class SettingsStoreBase with Store {
|
|||
@observable
|
||||
bool usePayjoin;
|
||||
|
||||
@observable
|
||||
bool showPayjoinCard;
|
||||
|
||||
@observable
|
||||
SyncMode currentSyncMode;
|
||||
|
||||
|
@ -1019,6 +1028,7 @@ abstract class SettingsStoreBase with Store {
|
|||
final lookupsENS = sharedPreferences.getBool(PreferencesKey.lookupsENS) ?? true;
|
||||
final lookupsWellKnown = sharedPreferences.getBool(PreferencesKey.lookupsWellKnown) ?? true;
|
||||
final usePayjoin = sharedPreferences.getBool(PreferencesKey.usePayjoin) ?? false;
|
||||
final showPayjoinCard = sharedPreferences.getBool(PreferencesKey.showPayjoinCard) ?? true;
|
||||
final customBitcoinFeeRate = sharedPreferences.getInt(PreferencesKey.customBitcoinFeeRate) ?? 1;
|
||||
final silentPaymentsCardDisplay =
|
||||
sharedPreferences.getBool(PreferencesKey.silentPaymentsCardDisplay) ?? true;
|
||||
|
@ -1322,6 +1332,7 @@ abstract class SettingsStoreBase with Store {
|
|||
lookupsENS: lookupsENS,
|
||||
lookupsWellKnown: lookupsWellKnown,
|
||||
usePayjoin: usePayjoin,
|
||||
showPayjoinCard: showPayjoinCard,
|
||||
customBitcoinFeeRate: customBitcoinFeeRate,
|
||||
silentPaymentsCardDisplay: silentPaymentsCardDisplay,
|
||||
silentPaymentsAlwaysScan: silentPaymentsAlwaysScan,
|
||||
|
|
|
@ -33,7 +33,6 @@ import 'package:cake_wallet/view_model/dashboard/payjoin_transaction_list_item.d
|
|||
import 'package:cake_wallet/view_model/dashboard/trade_list_item.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/transaction_list_item.dart';
|
||||
import 'package:cake_wallet/view_model/settings/sync_mode.dart';
|
||||
import 'package:cake_wallet/wallet_type_utils.dart';
|
||||
import 'package:cake_wallet/wownero/wownero.dart' as wow;
|
||||
import 'package:cryptography/cryptography.dart';
|
||||
import 'package:cw_core/balance.dart';
|
||||
|
@ -559,6 +558,12 @@ abstract class DashboardViewModelBase with Store {
|
|||
@observable
|
||||
late bool showDecredInfoCard;
|
||||
|
||||
@computed
|
||||
bool get showPayjoinCard =>
|
||||
wallet.type == WalletType.bitcoin &&
|
||||
settingsStore.showPayjoinCard &&
|
||||
!settingsStore.usePayjoin;
|
||||
|
||||
@observable
|
||||
bool backgroundSyncEnabled = false;
|
||||
|
||||
|
@ -764,6 +769,18 @@ abstract class DashboardViewModelBase with Store {
|
|||
sharedPreferences.setBool(PreferencesKey.showDecredInfoCard, false);
|
||||
}
|
||||
|
||||
@action
|
||||
void dismissPayjoin() {
|
||||
settingsStore.showPayjoinCard = false;
|
||||
}
|
||||
|
||||
@action
|
||||
void enablePayjoin() {
|
||||
settingsStore.usePayjoin = true;
|
||||
settingsStore.showPayjoinCard = false;
|
||||
bitcoin!.updatePayjoinState(wallet, true);
|
||||
}
|
||||
|
||||
BalanceViewModel balanceViewModel;
|
||||
|
||||
AppStore appStore;
|
||||
|
|
|
@ -310,6 +310,12 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
|
|||
? bitcoin!.getPayjoinEndpoint(wallet)
|
||||
: "";
|
||||
|
||||
@computed
|
||||
bool get isPayjoinUnavailable =>
|
||||
wallet.type == WalletType.bitcoin &&
|
||||
_settingsStore.usePayjoin &&
|
||||
payjoinEndpoint.isEmpty;
|
||||
|
||||
@computed
|
||||
PaymentURI get uri {
|
||||
switch (wallet.type) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue