receive pt.2

This commit is contained in:
fosse 2024-02-15 17:27:05 -05:00
parent d309e528f6
commit 3d65ccffa2
10 changed files with 379 additions and 341 deletions

BIN
assets/images/warning.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 926 B

View file

@ -23,6 +23,8 @@ part 'lightning_wallet.g.dart';
class LightningWallet = LightningWalletBase with _$LightningWallet; class LightningWallet = LightningWalletBase with _$LightningWallet;
abstract class LightningWalletBase extends ElectrumWallet with Store { abstract class LightningWalletBase extends ElectrumWallet with Store {
int satBalance = 0;
LightningWalletBase( LightningWalletBase(
{required String mnemonic, {required String mnemonic,
required String password, required String password,
@ -128,6 +130,18 @@ abstract class LightningWalletBase extends ElectrumWallet with Store {
breezConfig = breezConfig.copyWith(workingDir: workingDir); breezConfig = breezConfig.copyWith(workingDir: workingDir);
await sdk.connect(config: breezConfig, seed: seedBytes); await sdk.connect(config: breezConfig, seed: seedBytes);
print("initialized: ${(await sdk.isInitialized())}"); sdk.nodeStateStream.listen((event) {
// print("Node state: $event");
if (event == null) return;
// int balanceSat = event.maxPayableMsat ~/ 1000;
// print("sats: $balanceSat");
balance[CryptoCurrency.btc] = ElectrumBalance(
confirmed: event.maxPayableMsat,
unconfirmed: event.maxReceivableMsat,
frozen: 0,
);
});
print("initialized breez: ${(await sdk.isInitialized())}");
} }
} }

View file

@ -1200,10 +1200,8 @@ Future<void> setup({
getIt.registerFactory<TorPage>(() => TorPage(getIt.get<AppStore>())); getIt.registerFactory<TorPage>(() => TorPage(getIt.get<AppStore>()));
getIt.registerFactoryParam<LightningInvoicePageViewModel, List<dynamic>, void>((args, _) { getIt.registerFactoryParam<LightningInvoicePageViewModel, List<dynamic>, void>((args, _) {
final address = args.first as String; final pageOption = args.first as ReceivePageOption;
final pageOption = args.last as ReceivePageOption;
return LightningInvoicePageViewModel( return LightningInvoicePageViewModel(
address,
getIt.get<SettingsStore>(), getIt.get<SettingsStore>(),
getIt.get<AppStore>().wallet!, getIt.get<AppStore>().wallet!,
getIt.get<SharedPreferences>(), getIt.get<SharedPreferences>(),
@ -1222,7 +1220,7 @@ Future<void> setup({
final pageOption = args.last as ReceivePageOption; final pageOption = args.last as ReceivePageOption;
return LightningReceiveOnchainPage( return LightningReceiveOnchainPage(
addressListViewModel: getIt.get<WalletAddressListViewModel>(), addressListViewModel: getIt.get<WalletAddressListViewModel>(),
// lightningViewModel: LightningViewModel(), lightningViewModel: LightningViewModel(),
receiveOptionViewModel: getIt.get<ReceiveOptionViewModel>(param1: pageOption)); receiveOptionViewModel: getIt.get<ReceiveOptionViewModel>(param1: pageOption));
}); });

View file

@ -60,7 +60,7 @@ class MainActions {
Navigator.pushNamed( Navigator.pushNamed(
context, context,
Routes.lightningInvoice, Routes.lightningInvoice,
arguments: [viewModel.address, ReceivePageOption.lightningInvoice], arguments: [ReceivePageOption.lightningInvoice],
); );
return; return;
} }

View file

@ -19,10 +19,10 @@ enum ReceivePageOption {
label = 'Trocador AnonPay Donation Link'; label = 'Trocador AnonPay Donation Link';
break; break;
case ReceivePageOption.lightningInvoice: case ReceivePageOption.lightningInvoice:
label = 'Sats via Invoice'; label = 'Lightning via Invoice';
break; break;
case ReceivePageOption.lightningOnchain: case ReceivePageOption.lightningOnchain:
label = 'Sats via BTC address'; label = 'Lightning via BTC address';
break; break;
} }
return label; return label;

View file

@ -1,4 +1,5 @@
import 'package:cake_wallet/src/screens/receive/widgets/lightning_input_form.dart'; import 'package:cake_wallet/src/screens/receive/widgets/lightning_input_form.dart';
import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart';
import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart'; import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart';
import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; import 'package:cake_wallet/themes/extensions/keyboard_theme.dart';
import 'package:cake_wallet/anonpay/anonpay_donation_link_info.dart'; import 'package:cake_wallet/anonpay/anonpay_donation_link_info.dart';
@ -151,11 +152,46 @@ class LightningInvoicePage extends BasePage {
// ), // ),
// ), // ),
// ), // ),
Container(
padding: const EdgeInsets.only(top: 12, bottom: 12, right: 6),
margin: const EdgeInsets.only(left: 24, right: 24, bottom: 48),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(15)),
color: Color.fromARGB(94, 255, 221, 44),
border: Border.all(
color: Color.fromARGB(178, 223, 214, 0),
width: 2,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
width: 48,
height: 48,
margin: EdgeInsets.only(left: 12, bottom: 48, right: 12),
child: Image.asset("assets/images/warning.png"),
),
Expanded(
child: Text(
"A setup fee of 0.4% with a minimum of 2,079 sats will be applied upon receiving this invoice.",
maxLines: 3,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Theme.of(context).extension<DashboardPageTheme>()!.textColor,
),
),
),
],
),
),
LoadingPrimaryButton( LoadingPrimaryButton(
text: S.of(context).create_invoice, text: S.of(context).create_invoice,
onPressed: () { onPressed: () {
FocusScope.of(context).unfocus(); FocusScope.of(context).unfocus();
lightningViewModel.createInvoice(amount: _amountController.text, description: _descriptionController.text); lightningViewModel.createInvoice(
amount: _amountController.text, description: _descriptionController.text);
lightningInvoicePageViewModel.setRequestParams( lightningInvoicePageViewModel.setRequestParams(
inputAmount: _amountController.text, inputAmount: _amountController.text,
inputDescription: _descriptionController.text, inputDescription: _descriptionController.text,
@ -185,14 +221,14 @@ class LightningInvoicePage extends BasePage {
case ReceivePageOption.lightningInvoice: case ReceivePageOption.lightningInvoice:
break; break;
case ReceivePageOption.lightningOnchain: case ReceivePageOption.lightningOnchain:
final address = await lightningViewModel.receiveOnchain();
Navigator.popAndPushNamed( Navigator.popAndPushNamed(
context, context,
Routes.lightningReceiveOnchain, Routes.lightningReceiveOnchain,
arguments: [address, ReceivePageOption.lightningInvoice], arguments: [ReceivePageOption.lightningOnchain],
); );
break; break;
default: default:
break;
} }
}); });

View file

@ -1,15 +1,29 @@
import 'package:cake_wallet/entities/qr_view_data.dart';
import 'package:cake_wallet/entities/receive_page_option.dart';
import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/screens/dashboard/widgets/present_receive_option_picker.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/present_receive_option_picker.dart';
import 'package:cake_wallet/src/screens/receive/widgets/qr_image.dart';
import 'package:cake_wallet/src/widgets/gradient_background.dart'; import 'package:cake_wallet/src/widgets/gradient_background.dart';
import 'package:cake_wallet/themes/extensions/dashboard_page_theme.dart';
import 'package:cake_wallet/themes/extensions/qr_code_theme.dart';
import 'package:cake_wallet/utils/brightness_util.dart';
import 'package:cake_wallet/utils/show_bar.dart';
import 'package:cake_wallet/view_model/dashboard/receive_option_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/receive_option_view_model.dart';
import 'package:cake_wallet/view_model/lightning_view_model.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart'; import 'package:cake_wallet/view_model/wallet_address_list/wallet_address_list_view_model.dart';
import 'package:flutter/services.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:mobx/mobx.dart';
class LightningReceiveOnchainPage extends BasePage { class LightningReceiveOnchainPage extends BasePage {
LightningReceiveOnchainPage({required this.addressListViewModel, required this.receiveOptionViewModel}) LightningReceiveOnchainPage(
: _cryptoAmountFocus = FocusNode(), {required this.addressListViewModel,
_amountController = TextEditingController(), required this.receiveOptionViewModel,
required this.lightningViewModel})
: _amountController = TextEditingController(),
_formKey = GlobalKey<FormState>() { _formKey = GlobalKey<FormState>() {
_amountController.addListener(() { _amountController.addListener(() {
if (_formKey.currentState!.validate()) { if (_formKey.currentState!.validate()) {
@ -20,9 +34,11 @@ class LightningReceiveOnchainPage extends BasePage {
final WalletAddressListViewModel addressListViewModel; final WalletAddressListViewModel addressListViewModel;
final ReceiveOptionViewModel receiveOptionViewModel; final ReceiveOptionViewModel receiveOptionViewModel;
final LightningViewModel lightningViewModel;
final TextEditingController _amountController; final TextEditingController _amountController;
final GlobalKey<FormState> _formKey; final GlobalKey<FormState> _formKey;
static const _heroTag = 'receive_page';
bool effectsInstalled = false;
@override @override
String get title => S.current.receive; String get title => S.current.receive;
@ -33,20 +49,6 @@ class LightningReceiveOnchainPage extends BasePage {
@override @override
bool get resizeToAvoidBottomInset => true; bool get resizeToAvoidBottomInset => true;
final FocusNode _cryptoAmountFocus;
// @override
// Widget middle(BuildContext context) {
// return Text(
// title,
// style: TextStyle(
// fontSize: 18.0,
// fontWeight: FontWeight.bold,
// fontFamily: 'Lato',
// color: pageIconColor(context)),
// );
// }
@override @override
Widget middle(BuildContext context) => PresentReceiveOptionPicker( Widget middle(BuildContext context) => PresentReceiveOptionPicker(
color: titleColor(context), receiveOptionViewModel: receiveOptionViewModel); color: titleColor(context), receiveOptionViewModel: receiveOptionViewModel);
@ -57,6 +59,186 @@ class LightningReceiveOnchainPage extends BasePage {
@override @override
Widget body(BuildContext context) { Widget body(BuildContext context) {
return SizedBox(); WidgetsBinding.instance.addPostFrameCallback((_) => _setReactions(context));
final copyImage = Image.asset('assets/images/copy_address.png',
color: Theme.of(context).extension<QRCodeTheme>()!.qrWidgetCopyButtonColor);
String heroTag = "lightning_receive";
return Center(
child: Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
FutureBuilder(
future: lightningViewModel.receiveOnchain(),
builder: ((context, snapshot) {
if (snapshot.data == null) {
return CircularProgressIndicator();
}
String data = (snapshot.data as List<String>)[0];
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.only(bottom: 12),
child: Text(
S.of(context).qr_fullscreen,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Theme.of(context).extension<DashboardPageTheme>()!.textColor),
),
),
Row(
children: <Widget>[
Spacer(flex: 3),
Observer(
builder: (_) => Flexible(
flex: 5,
child: GestureDetector(
onTap: () {
BrightnessUtil.changeBrightnessForFunction(
() async {
await Navigator.pushNamed(context, Routes.fullscreenQR,
arguments: QrViewData(
data: data,
heroTag: heroTag,
));
},
);
},
child: Hero(
tag: Key(heroTag),
child: Center(
child: AspectRatio(
aspectRatio: 1.0,
child: Container(
padding: EdgeInsets.all(5),
decoration: BoxDecoration(
border: Border.all(
width: 3,
color: Theme.of(context)
.extension<DashboardPageTheme>()!
.textColor,
),
),
child: Container(
decoration: BoxDecoration(
border: Border.all(
width: 3,
color: Colors.white,
),
),
child: QrImage(data: data)),
),
),
),
),
),
),
),
Spacer(flex: 3)
],
),
Padding(
padding: EdgeInsets.only(top: 20, bottom: 8, left: 24, right: 24),
child: Builder(
builder: (context) => Observer(
builder: (context) => GestureDetector(
onTap: () {
Clipboard.setData(ClipboardData(text: data));
showBar<void>(context, S.of(context).copied_to_clipboard);
},
child: Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
child: Text(
addressListViewModel.address.address,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.w500,
color: Theme.of(context)
.extension<DashboardPageTheme>()!
.textColor),
),
),
Padding(
padding: EdgeInsets.only(left: 12),
child: copyImage,
)
],
),
),
),
),
)
],
);
}),
),
Container(
padding: const EdgeInsets.only(top: 24, bottom: 24, right: 6),
margin: const EdgeInsets.symmetric(horizontal: 24),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(15)),
color: Color.fromARGB(94, 255, 221, 44),
border: Border.all(
color: Color.fromARGB(178, 223, 214, 0),
width: 2,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
width: 48,
height: 48,
margin: EdgeInsets.only(left: 12, bottom: 48, right: 12),
child: Image.asset("assets/images/warning.png"),
),
Expanded(
child: Text(
"Send more than 20,029 sats and up to 3,998,387 sats to this address. A setup fee of 0.4% with a minimum of 2,079 sats will be applied upon receiving this invoice. This will convert any received Bitcoin into Lightning. An on-chain fee will be applied. This address can only be used once.",
maxLines: 10,
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
color: Theme.of(context).extension<DashboardPageTheme>()!.textColor,
),
),
),
],
),
),
],
),
),
);
}
void _setReactions(BuildContext context) {
if (effectsInstalled) {
return;
}
reaction((_) => receiveOptionViewModel.selectedReceiveOption, (ReceivePageOption option) async {
switch (option) {
case ReceivePageOption.lightningInvoice:
Navigator.popAndPushNamed(
context,
Routes.lightningInvoice,
arguments: [ReceivePageOption.lightningInvoice],
);
break;
case ReceivePageOption.lightningOnchain:
break;
default:
break;
}
});
effectsInstalled = true;
} }
} }

View file

@ -5,8 +5,12 @@ import 'package:cake_wallet/src/screens/dashboard/widgets/sync_indicator_icon.da
import 'package:cake_wallet/src/screens/send/widgets/send_card.dart'; import 'package:cake_wallet/src/screens/send/widgets/send_card.dart';
import 'package:cake_wallet/src/widgets/add_template_button.dart'; import 'package:cake_wallet/src/widgets/add_template_button.dart';
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart'; import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
import 'package:cake_wallet/src/widgets/keyboard_done_button.dart';
import 'package:cake_wallet/src/widgets/picker.dart'; import 'package:cake_wallet/src/widgets/picker.dart';
import 'package:cake_wallet/src/widgets/template_tile.dart'; import 'package:cake_wallet/src/widgets/template_tile.dart';
import 'package:cake_wallet/themes/extensions/exchange_page_theme.dart';
import 'package:cake_wallet/themes/extensions/keyboard_theme.dart';
import 'package:cake_wallet/themes/extensions/seed_widget_theme.dart'; import 'package:cake_wallet/themes/extensions/seed_widget_theme.dart';
import 'package:cake_wallet/themes/extensions/send_page_theme.dart'; import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
import 'package:cake_wallet/themes/theme_base.dart'; import 'package:cake_wallet/themes/theme_base.dart';
@ -16,6 +20,7 @@ import 'package:cake_wallet/utils/responsive_layout_util.dart';
import 'package:cake_wallet/view_model/send/output.dart'; import 'package:cake_wallet/view_model/send/output.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:keyboard_actions/keyboard_actions.dart';
import 'package:mobx/mobx.dart'; import 'package:mobx/mobx.dart';
import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/view_model/send/send_view_model.dart'; import 'package:cake_wallet/view_model/send/send_view_model.dart';
@ -45,6 +50,9 @@ class LightningSendPage extends BasePage {
final controller = PageController(initialPage: 0); final controller = PageController(initialPage: 0);
final PaymentRequest? initialPaymentRequest; final PaymentRequest? initialPaymentRequest;
final bolt11Controller = TextEditingController();
final _bolt11FocusNode = FocusNode();
bool _effectsInstalled = false; bool _effectsInstalled = false;
@override @override
@ -133,18 +141,16 @@ class LightningSendPage extends BasePage {
? TrailButton( ? TrailButton(
caption: S.of(context).remove, caption: S.of(context).remove,
onPressed: () { onPressed: () {
var pageToJump = (controller.page?.round() ?? 0) - 1; // var pageToJump = (controller.page?.round() ?? 0) - 1;
pageToJump = pageToJump > 0 ? pageToJump : 0; // pageToJump = pageToJump > 0 ? pageToJump : 0;
final output = _defineCurrentOutput(); // final output = _defineCurrentOutput();
sendViewModel.removeOutput(output); // sendViewModel.removeOutput(output);
controller.jumpToPage(pageToJump); // controller.jumpToPage(pageToJump);
}) })
: TrailButton( : TrailButton(
caption: S.of(context).clear, caption: S.of(context).clear,
onPressed: () { onPressed: () {
final output = _defineCurrentOutput();
_formKey.currentState?.reset(); _formKey.currentState?.reset();
output.reset();
}); });
}); });
@ -152,242 +158,117 @@ class LightningSendPage extends BasePage {
Widget body(BuildContext context) { Widget body(BuildContext context) {
_setEffects(context); _setEffects(context);
return GestureDetector( return WillPopScope(
onLongPress: () => onWillPop: () => _onNavigateBack(context),
sendViewModel.balanceViewModel.isReversing = !sendViewModel.balanceViewModel.isReversing, child: KeyboardActions(
onLongPressUp: () => disableScroll: true,
sendViewModel.balanceViewModel.isReversing = !sendViewModel.balanceViewModel.isReversing, config: KeyboardActionsConfig(
child: Form( keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
key: _formKey, keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor,
nextFocus: false,
actions: [
KeyboardActionsItem(
focusNode: FocusNode(),
// focusNode: _amountFocusNode,
toolbarButtons: [(_) => KeyboardDoneButton()],
),
]),
child: Container(
color: Theme.of(context).colorScheme.background,
child: ScrollableWithBottomSection( child: ScrollableWithBottomSection(
contentPadding: EdgeInsets.only(bottom: 24), contentPadding: EdgeInsets.only(bottom: 24),
content: FocusTraversalGroup( content: Container(
policy: OrderedTraversalPolicy(), decoration: responsiveLayoutUtil.shouldRenderMobileUI
child: Column( ? BoxDecoration(
children: <Widget>[ borderRadius: BorderRadius.only(
Container( bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)),
height: _sendCardHeight(context), gradient: LinearGradient(
child: Observer( colors: [
builder: (_) { Theme.of(context)
return PageView.builder( .extension<ExchangePageTheme>()!
scrollDirection: Axis.horizontal, .firstGradientTopPanelColor,
controller: controller, Theme.of(context)
itemCount: sendViewModel.outputs.length, .extension<ExchangePageTheme>()!
itemBuilder: (context, index) { .secondGradientTopPanelColor,
final output = sendViewModel.outputs[index]; ],
begin: Alignment.topLeft,
return SendCard( end: Alignment.bottomRight,
key: output.key, ),
output: output,
sendViewModel: sendViewModel,
initialPaymentRequest: initialPaymentRequest,
);
});
},
)),
Padding(
padding: EdgeInsets.only(top: 10, left: 24, right: 24, bottom: 10),
child: Container(
height: 10,
child: Observer(
builder: (_) {
final count = sendViewModel.outputs.length;
return count > 1
? SmoothPageIndicator(
controller: controller,
count: count,
effect: ScrollingDotsEffect(
spacing: 6.0,
radius: 6.0,
dotWidth: 6.0,
dotHeight: 6.0,
dotColor: Theme.of(context)
.extension<SendPageTheme>()!
.indicatorDotColor,
activeDotColor: Theme.of(context)
.extension<SendPageTheme>()!
.templateBackgroundColor),
) )
: Offstage(); : null,
}, child: Observer(builder: (_) {
return Padding(
padding: EdgeInsets.fromLTRB(24, 120, 24, 0),
child: BaseTextFormField(
controller: bolt11Controller,
focusNode: _bolt11FocusNode,
textInputAction: TextInputAction.next,
borderColor: Theme.of(context)
.extension<ExchangePageTheme>()!
.textFieldBorderTopPanelColor,
suffixIcon: SizedBox(width: 36),
hintText: S.of(context).invoice_details,
placeholderTextStyle: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Theme.of(context).extension<ExchangePageTheme>()!.hintTextColor,
), ),
textStyle:
TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white),
validator: null,
), ),
),
Container(
height: 40,
width: double.infinity,
padding: EdgeInsets.only(left: 24),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Observer(
builder: (_) {
final templates = sendViewModel.templates;
final itemCount = templates.length;
return Row(
children: <Widget>[
AddTemplateButton(
onTap: () => Navigator.of(context).pushNamed(Routes.sendTemplate),
currentTemplatesLength: templates.length,
),
ListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: itemCount,
itemBuilder: (context, index) {
final template = templates[index];
return TemplateTile(
key: UniqueKey(),
to: template.name,
hasMultipleRecipients: template.additionalRecipients != null &&
template.additionalRecipients!.length > 1,
amount: template.isCurrencySelected
? template.amount
: template.amountFiat,
from: template.isCurrencySelected
? template.cryptoCurrency
: template.fiatCurrency,
onTap: () async {
if (template.additionalRecipients?.isNotEmpty ?? false) {
sendViewModel.clearOutputs();
for (int i = 0;
i < template.additionalRecipients!.length;
i++) {
Output output;
try {
output = sendViewModel.outputs[i];
} catch (e) {
sendViewModel.addOutput();
output = sendViewModel.outputs[i];
}
await _setInputsFromTemplate(
context,
output: output,
template: template.additionalRecipients![i],
); );
} }),
} else {
final output = _defineCurrentOutput();
await _setInputsFromTemplate(
context,
output: output,
template: template,
);
}
},
onRemove: () {
showPopUp<void>(
context: context,
builder: (dialogContext) {
return AlertWithTwoActions(
alertTitle: S.of(context).template,
alertContent: S.of(context).confirm_delete_template,
rightButtonText: S.of(context).delete,
leftButtonText: S.of(context).cancel,
actionRightButton: () {
Navigator.of(dialogContext).pop();
sendViewModel.sendTemplateViewModel
.removeTemplate(template: template);
},
actionLeftButton: () =>
Navigator.of(dialogContext).pop());
},
);
},
);
},
),
],
);
},
),
),
),
],
),
), ),
bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24), bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
bottomSection: Column( bottomSection: Observer(builder: (_) {
children: [ return Column(
if (sendViewModel.hasCurrecyChanger) children: <Widget>[
Observer( // Padding(
builder: (_) => Padding( // padding: EdgeInsets.only(bottom: 15),
padding: EdgeInsets.only(bottom: 12), // child: Center(
child: PrimaryButton( // child: Text(
onPressed: () => presentCurrencyPicker(context), // S.of(context).anonpay_description("an invoice", "pay"),
text: 'Change your asset (${sendViewModel.selectedCryptoCurrency})', // textAlign: TextAlign.center,
color: Colors.transparent, // style: TextStyle(
textColor: // color: Theme.of(context)
Theme.of(context).extension<SeedWidgetTheme>()!.hintTextColor, // .extension<ExchangePageTheme>()!
))), // .receiveAmountColor,
if (sendViewModel.sendTemplateViewModel.hasMultiRecipient) // fontWeight: FontWeight.w500,
Padding( // fontSize: 12),
padding: EdgeInsets.only(bottom: 12), // ),
child: PrimaryButton( // ),
onPressed: () { // ),
sendViewModel.addOutput(); LoadingPrimaryButton(
Future.delayed(const Duration(milliseconds: 250), () {
controller.jumpToPage(sendViewModel.outputs.length - 1);
});
},
text: S.of(context).add_receiver,
color: Colors.transparent,
textColor: Theme.of(context).extension<SeedWidgetTheme>()!.hintTextColor,
isDottedBorder: true,
borderColor:
Theme.of(context).extension<SendPageTheme>()!.templateDottedBorderColor,
)),
Observer(
builder: (_) {
return LoadingPrimaryButton(
onPressed: () async {
if (_formKey.currentState != null && !_formKey.currentState!.validate()) {
if (sendViewModel.outputs.length > 1) {
showErrorValidationAlert(context);
}
return;
}
final notValidItems = sendViewModel.outputs
.where((item) => item.address.isEmpty || item.cryptoAmount.isEmpty)
.toList();
if (notValidItems.isNotEmpty) {
showErrorValidationAlert(context);
return;
}
final check = sendViewModel.shouldDisplayTotp();
authService.authenticateAction(
context,
conditionToDetermineIfToUse2FA: check,
onAuthSuccess: (value) async {
if (value) {
await sendViewModel.createTransaction();
}
},
);
},
text: S.of(context).send, text: S.of(context).send,
onPressed: () {
FocusScope.of(context).unfocus();
// lightningViewModel.createInvoice(
// amount: _amountController.text, description: _descriptionController.text);
// lightningInvoicePageViewModel.setRequestParams(
// inputAmount: _amountController.text,
// inputDescription: _descriptionController.text,
// );
// lightningInvoicePageViewModel.createInvoice();
},
color: Theme.of(context).primaryColor, color: Theme.of(context).primaryColor,
textColor: Colors.white, textColor: Colors.white,
isLoading: sendViewModel.state is IsExecutingState || isLoading: false,
sendViewModel.state is TransactionCommitting, ),
isDisabled: !sendViewModel.isReadyForSend,
);
},
)
], ],
)), );
}),
),
),
), ),
); );
} }
Future<bool> _onNavigateBack(BuildContext context) async {
onClose(context);
return false;
}
void _setEffects(BuildContext context) { void _setEffects(BuildContext context) {
if (_effectsInstalled) { if (_effectsInstalled) {
return; return;
@ -469,57 +350,4 @@ class LightningSendPage extends BasePage {
_effectsInstalled = true; _effectsInstalled = true;
} }
Future<void> _setInputsFromTemplate(BuildContext context,
{required Output output, required Template template}) async {
output.address = template.address;
if (template.isCurrencySelected) {
sendViewModel.setSelectedCryptoCurrency(template.cryptoCurrency);
output.setCryptoAmount(template.amount);
} else {
final fiatFromTemplate =
FiatCurrency.all.singleWhere((element) => element.title == template.fiatCurrency);
sendViewModel.setFiatCurrency(fiatFromTemplate);
output.setFiatAmount(template.amountFiat);
}
output.resetParsedAddress();
await output.fetchParsedAddress(context);
}
Output _defineCurrentOutput() {
if (controller.page == null) {
throw Exception('Controller page is null');
}
final itemCount = controller.page!.round();
return sendViewModel.outputs[itemCount];
}
void showErrorValidationAlert(BuildContext context) async {
await showPopUp<void>(
context: context,
builder: (BuildContext context) {
return AlertWithOneAction(
alertTitle: S.of(context).error,
alertContent: 'Please, check receiver forms',
buttonText: S.of(context).ok,
buttonAction: () => Navigator.of(context).pop());
});
}
void presentCurrencyPicker(BuildContext context) async {
await showPopUp<CryptoCurrency>(
builder: (_) => Picker(
items: sendViewModel.currencies,
displayItem: (Object item) => item.toString(),
selectedAtIndex:
sendViewModel.currencies.indexOf(sendViewModel.selectedCryptoCurrency),
title: S.of(context).please_select,
mainAxisAlignment: MainAxisAlignment.center,
onItemSelected: (CryptoCurrency cur) => sendViewModel.selectedCryptoCurrency = cur,
),
context: context);
}
} }

View file

@ -1,9 +1,5 @@
import 'package:cake_wallet/anonpay/anonpay_api.dart';
import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart';
import 'package:cake_wallet/anonpay/anonpay_request.dart';
import 'package:cake_wallet/core/execution_state.dart'; import 'package:cake_wallet/core/execution_state.dart';
import 'package:cake_wallet/entities/fiat_currency.dart'; import 'package:cake_wallet/entities/fiat_currency.dart';
import 'package:cake_wallet/entities/preferences_key.dart';
import 'package:cake_wallet/entities/receive_page_option.dart'; import 'package:cake_wallet/entities/receive_page_option.dart';
import 'package:cake_wallet/store/settings_store.dart'; import 'package:cake_wallet/store/settings_store.dart';
import 'package:cake_wallet/view_model/lightning_view_model.dart'; import 'package:cake_wallet/view_model/lightning_view_model.dart';
@ -11,7 +7,6 @@ import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/currency.dart'; import 'package:cw_core/currency.dart';
import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_type.dart'; import 'package:cw_core/wallet_type.dart';
import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart'; import 'package:mobx/mobx.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
@ -22,7 +17,6 @@ class LightningInvoicePageViewModel = LightningInvoicePageViewModelBase
abstract class LightningInvoicePageViewModelBase with Store { abstract class LightningInvoicePageViewModelBase with Store {
LightningInvoicePageViewModelBase( LightningInvoicePageViewModelBase(
this.address,
this.settingsStore, this.settingsStore,
this._wallet, this._wallet,
this.sharedPreferences, this.sharedPreferences,
@ -37,10 +31,8 @@ abstract class LightningInvoicePageViewModelBase with Store {
} }
List<Currency> get currencies => [walletTypeToCryptoCurrency(_wallet.type), ...FiatCurrency.all]; List<Currency> get currencies => [walletTypeToCryptoCurrency(_wallet.type), ...FiatCurrency.all];
final String address;
final SettingsStore settingsStore; final SettingsStore settingsStore;
final WalletBase _wallet; final WalletBase _wallet;
// final Box<AnonpayInvoiceInfo> _anonpayInvoiceInfoSource;
final SharedPreferences sharedPreferences; final SharedPreferences sharedPreferences;
final ReceivePageOption pageOption; final ReceivePageOption pageOption;
final LightningViewModel lightningViewModel; final LightningViewModel lightningViewModel;
@ -120,12 +112,8 @@ abstract class LightningInvoicePageViewModelBase with Store {
Future<void> _fetchLimits() async { Future<void> _fetchLimits() async {
List<String> limits = await lightningViewModel.invoiceLimits(); List<String> limits = await lightningViewModel.invoiceLimits();
// final limit = await anonPayApi.fetchLimits( minimum = double.tryParse(limits[0]);
// cryptoCurrency: cryptoCurrency, maximum = double.tryParse(limits[1]);
// fiatCurrency: selectedCurrency is FiatCurrency ? selectedCurrency as FiatCurrency : null,
// );
// minimum = limit.min;
// maximum = limit.max != null ? limit.max! / 4 : null;
} }
@action @action

View file

@ -1,15 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'package:breez_sdk/breez_sdk.dart'; import 'package:breez_sdk/breez_sdk.dart';
import 'package:breez_sdk/bridge_generated.dart'; import 'package:breez_sdk/bridge_generated.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:mobx/mobx.dart'; import 'package:mobx/mobx.dart';
import 'package:cake_wallet/view_model/auth_state.dart';
import 'package:cake_wallet/core/auth_service.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/core/execution_state.dart';
import 'package:cake_wallet/entities/biometric_auth.dart';
import 'package:cake_wallet/store/settings_store.dart';
part 'lightning_view_model.g.dart'; part 'lightning_view_model.g.dart';