CW-400 investigate cupertino nav bar null exception (#943)

* Fix null error on back navigation after pushReplacementNamed

* Fix null error on back navigation after pushReplacementNamed

* Close all visible keyboard for page navigation context

* Fix issue with market place navigation

* Remove focus before back navigation

* Fix background color

* Fix background color

* Fix background color
This commit is contained in:
Godwin Asuquo 2023-06-08 02:16:52 +03:00 committed by GitHub
parent 3b073d9751
commit e8446f0c98
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 183 additions and 137 deletions

View file

@ -39,6 +39,7 @@ import 'package:cake_wallet/utils/payment_request.dart';
import 'package:cake_wallet/view_model/dashboard/desktop_sidebar_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/desktop_sidebar_view_model.dart';
import 'package:cake_wallet/view_model/anon_invoice_page_view_model.dart'; import 'package:cake_wallet/view_model/anon_invoice_page_view_model.dart';
import 'package:cake_wallet/view_model/anonpay_details_view_model.dart'; import 'package:cake_wallet/view_model/anonpay_details_view_model.dart';
import 'package:cake_wallet/view_model/dashboard/market_place_view_model.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/ionia/ionia_auth_view_model.dart'; import 'package:cake_wallet/view_model/ionia/ionia_auth_view_model.dart';
import 'package:cake_wallet/view_model/ionia/ionia_buy_card_view_model.dart'; import 'package:cake_wallet/view_model/ionia/ionia_buy_card_view_model.dart';
@ -873,6 +874,8 @@ Future setup({
getIt.registerFactory(() => IoniaGiftCardsListViewModel(ioniaService: getIt.get<IoniaService>())); getIt.registerFactory(() => IoniaGiftCardsListViewModel(ioniaService: getIt.get<IoniaService>()));
getIt.registerFactory(()=> MarketPlaceViewModel(getIt.get<IoniaService>()));
getIt.registerFactory(() => IoniaAuthViewModel(ioniaService: getIt.get<IoniaService>())); getIt.registerFactory(() => IoniaAuthViewModel(ioniaService: getIt.get<IoniaService>()));
getIt.registerFactoryParam<IoniaMerchPurchaseViewModel, double, IoniaMerchant>( getIt.registerFactoryParam<IoniaMerchPurchaseViewModel, double, IoniaMerchant>(
@ -902,7 +905,7 @@ Future setup({
return IoniaVerifyIoniaOtp(getIt.get<IoniaAuthViewModel>(), email, isSignIn); return IoniaVerifyIoniaOtp(getIt.get<IoniaAuthViewModel>(), email, isSignIn);
}); });
getIt.registerFactory(() => IoniaWelcomePage(getIt.get<IoniaGiftCardsListViewModel>())); getIt.registerFactory(() => IoniaWelcomePage());
getIt.registerFactoryParam<IoniaBuyGiftCardPage, List, void>((List args, _) { getIt.registerFactoryParam<IoniaBuyGiftCardPage, List, void>((List args, _) {
final merchant = args.first as IoniaMerchant; final merchant = args.first as IoniaMerchant;

View file

@ -175,7 +175,6 @@ Route<dynamic> createRoute(RouteSettings settings) {
fullscreenDialog: true); fullscreenDialog: true);
} else if (isSingleCoin) { } else if (isSingleCoin) {
return MaterialPageRoute<void>( return MaterialPageRoute<void>(
fullscreenDialog: true,
builder: (_) => getIt.get<WalletRestorePage>( builder: (_) => getIt.get<WalletRestorePage>(
param1: availableWalletTypes.first param1: availableWalletTypes.first
)); ));
@ -196,7 +195,6 @@ Route<dynamic> createRoute(RouteSettings settings) {
case Routes.restoreWallet: case Routes.restoreWallet:
return MaterialPageRoute<void>( return MaterialPageRoute<void>(
fullscreenDialog: true,
builder: (_) => getIt.get<WalletRestorePage>( builder: (_) => getIt.get<WalletRestorePage>(
param1: settings.arguments as WalletType)); param1: settings.arguments as WalletType));
@ -206,6 +204,7 @@ Route<dynamic> createRoute(RouteSettings settings) {
case Routes.dashboard: case Routes.dashboard:
return CupertinoPageRoute<void>( return CupertinoPageRoute<void>(
settings: settings,
builder: (_) => getIt.get<DashboardPage>()); builder: (_) => getIt.get<DashboardPage>());
case Routes.send: case Routes.send:
@ -468,7 +467,8 @@ Route<dynamic> createRoute(RouteSettings settings) {
return CupertinoPageRoute<void>( builder: (_) => getIt.get<IoniaCreateAccountPage>()); return CupertinoPageRoute<void>( builder: (_) => getIt.get<IoniaCreateAccountPage>());
case Routes.ioniaManageCardsPage: case Routes.ioniaManageCardsPage:
return CupertinoPageRoute<void>(builder: (_) => getIt.get<IoniaManageCardsPage>()); return CupertinoPageRoute<void>(
builder: (_) => getIt.get<IoniaManageCardsPage>());
case Routes.ioniaBuyGiftCardPage: case Routes.ioniaBuyGiftCardPage:
final args = settings.arguments as List; final args = settings.arguments as List;
@ -536,7 +536,6 @@ Route<dynamic> createRoute(RouteSettings settings) {
case Routes.anonPayInvoicePage: case Routes.anonPayInvoicePage:
final args = settings.arguments as List; final args = settings.arguments as List;
return CupertinoPageRoute<void>( return CupertinoPageRoute<void>(
fullscreenDialog: true,
builder: (_) => getIt.get<AnonPayInvoicePage>(param1: args)); builder: (_) => getIt.get<AnonPayInvoicePage>(param1: args));
case Routes.anonPayReceivePage: case Routes.anonPayReceivePage:

View file

@ -5,7 +5,7 @@ import 'package:cake_wallet/entities/main_actions.dart';
import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart'; import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_sidebar_wrapper.dart';
import 'package:cake_wallet/src/screens/dashboard/widgets/market_place_page.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/market_place_page.dart';
import 'package:cake_wallet/utils/version_comparator.dart'; import 'package:cake_wallet/utils/version_comparator.dart';
import 'package:cake_wallet/wallet_type_utils.dart'; import 'package:cake_wallet/view_model/dashboard/market_place_view_model.dart';
import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/generated/i18n.dart';
import 'package:cake_wallet/routes.dart'; import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/screens/yat_emoji_id.dart'; import 'package:cake_wallet/src/screens/yat_emoji_id.dart';
@ -27,8 +27,6 @@ import 'package:mobx/mobx.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:smooth_page_indicator/smooth_page_indicator.dart'; import 'package:smooth_page_indicator/smooth_page_indicator.dart';
import 'package:cake_wallet/main.dart'; import 'package:cake_wallet/main.dart';
import 'package:cake_wallet/buy/moonpay/moonpay_buy_provider.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:cake_wallet/src/screens/release_notes/release_notes_screen.dart'; import 'package:cake_wallet/src/screens/release_notes/release_notes_screen.dart';
class DashboardPage extends StatelessWidget { class DashboardPage extends StatelessWidget {
@ -251,7 +249,12 @@ class _DashboardPageView extends BasePage {
if (dashboardViewModel.shouldShowMarketPlaceInDashboard) { if (dashboardViewModel.shouldShowMarketPlaceInDashboard) {
pages.add(Semantics( pages.add(Semantics(
label: 'Marketplace Page', label: 'Marketplace Page',
child: MarketPlacePage(dashboardViewModel: dashboardViewModel))); child: MarketPlacePage(
dashboardViewModel: dashboardViewModel,
marketPlaceViewModel: getIt.get<MarketPlaceViewModel>(),
),
),
);
} }
pages.add(Semantics(label: 'Balance Page', child: balancePage)); pages.add(Semantics(label: 'Balance Page', child: balancePage));
pages.add(Semantics( pages.add(Semantics(

View file

@ -1,7 +1,9 @@
import 'package:cake_wallet/di.dart';
import 'package:cake_wallet/entities/main_actions.dart'; import 'package:cake_wallet/entities/main_actions.dart';
import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_action_button.dart'; import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_action_button.dart';
import 'package:cake_wallet/src/screens/dashboard/widgets/market_place_page.dart'; import 'package:cake_wallet/src/screens/dashboard/widgets/market_place_page.dart';
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
import 'package:cake_wallet/view_model/dashboard/market_place_view_model.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';
@ -70,7 +72,10 @@ class DesktopDashboardActions extends StatelessWidget {
], ],
), ),
Expanded( Expanded(
child: MarketPlacePage(dashboardViewModel: dashboardViewModel), child: MarketPlacePage(
dashboardViewModel: dashboardViewModel,
marketPlaceViewModel: getIt.get<MarketPlaceViewModel>(),
),
), ),
], ],
); );

View file

@ -273,7 +273,7 @@ class AddressPage extends BasePage {
reaction((_) => receiveOptionViewModel.selectedReceiveOption, (ReceivePageOption option) { reaction((_) => receiveOptionViewModel.selectedReceiveOption, (ReceivePageOption option) {
switch (option) { switch (option) {
case ReceivePageOption.anonPayInvoice: case ReceivePageOption.anonPayInvoice:
Navigator.pushReplacementNamed( Navigator.pushNamed(
context, context,
Routes.anonPayInvoicePage, Routes.anonPayInvoicePage,
arguments: [addressListViewModel.address.address, option], arguments: [addressListViewModel.address.address, option],
@ -285,7 +285,7 @@ class AddressPage extends BasePage {
final onionUrl = sharedPreferences.getString(PreferencesKey.onionDonationLink); final onionUrl = sharedPreferences.getString(PreferencesKey.onionDonationLink);
if (clearnetUrl != null && onionUrl != null) { if (clearnetUrl != null && onionUrl != null) {
Navigator.pushReplacementNamed( Navigator.pushNamed(
context, context,
Routes.anonPayReceivePage, Routes.anonPayReceivePage,
arguments: AnonpayDonationLinkInfo( arguments: AnonpayDonationLinkInfo(
@ -295,7 +295,7 @@ class AddressPage extends BasePage {
), ),
); );
} else { } else {
Navigator.pushReplacementNamed( Navigator.pushNamed(
context, context,
Routes.anonPayInvoicePage, Routes.anonPayInvoicePage,
arguments: [addressListViewModel.address.address, option], arguments: [addressListViewModel.address.address, option],

View file

@ -3,16 +3,20 @@ import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
import 'package:cake_wallet/src/widgets/market_place_item.dart'; import 'package:cake_wallet/src/widgets/market_place_item.dart';
import 'package:cake_wallet/utils/show_pop_up.dart'; import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart'; import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
import 'package:cake_wallet/view_model/dashboard/market_place_view_model.dart';
import 'package:cw_core/wallet_type.dart'; import 'package:cw_core/wallet_type.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:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
class MarketPlacePage extends StatelessWidget { class MarketPlacePage extends StatelessWidget {
MarketPlacePage({
MarketPlacePage({required this.dashboardViewModel}); required this.dashboardViewModel,
required this.marketPlaceViewModel,
});
final DashboardViewModel dashboardViewModel; final DashboardViewModel dashboardViewModel;
final MarketPlaceViewModel marketPlaceViewModel;
final _scrollController = ScrollController(); final _scrollController = ScrollController();
@override @override
@ -48,7 +52,7 @@ class MarketPlacePage extends StatelessWidget {
children: <Widget>[ children: <Widget>[
SizedBox(height: 20), SizedBox(height: 20),
MarketPlaceItem( MarketPlaceItem(
onTap: () =>_navigatorToGiftCardsPage(context), onTap: () => _navigatorToGiftCardsPage(context),
title: S.of(context).cake_pay_title, title: S.of(context).cake_pay_title,
subTitle: S.of(context).cake_pay_subtitle, subTitle: S.of(context).cake_pay_subtitle,
), ),
@ -70,12 +74,13 @@ class MarketPlacePage extends StatelessWidget {
), ),
); );
} }
void _navigatorToGiftCardsPage(BuildContext context) { void _navigatorToGiftCardsPage(BuildContext context) {
final walletType = dashboardViewModel.type; final walletType = dashboardViewModel.type;
switch (walletType) { switch (walletType) {
case WalletType.haven: case WalletType.haven:
showPopUp<void>( showPopUp<void>(
context: context, context: context,
builder: (BuildContext context) { builder: (BuildContext context) {
return AlertWithOneAction( return AlertWithOneAction(
@ -85,9 +90,14 @@ class MarketPlacePage extends StatelessWidget {
buttonAction: () => Navigator.of(context).pop()); buttonAction: () => Navigator.of(context).pop());
}); });
break; break;
default: default:
Navigator.of(context).pushNamed(Routes.ioniaWelcomePage); marketPlaceViewModel.isIoniaUserAuthenticated().then((value) {
if (value) {
Navigator.pushNamed(context, Routes.ioniaManageCardsPage);
return;
}
Navigator.of(context).pushNamed(Routes.ioniaWelcomePage);
});
} }
} }
} }

View file

@ -3,14 +3,11 @@ import 'package:cake_wallet/routes.dart';
import 'package:cake_wallet/src/screens/base_page.dart'; import 'package:cake_wallet/src/screens/base_page.dart';
import 'package:cake_wallet/src/widgets/primary_button.dart'; import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/typography.dart'; import 'package:cake_wallet/typography.dart';
import 'package:cake_wallet/view_model/ionia/ionia_gift_cards_list_view_model.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:cake_wallet/generated/i18n.dart'; import 'package:cake_wallet/generated/i18n.dart';
import 'package:mobx/mobx.dart';
class IoniaWelcomePage extends BasePage { class IoniaWelcomePage extends BasePage {
IoniaWelcomePage(this._cardsListViewModel); IoniaWelcomePage();
@override @override
Widget middle(BuildContext context) { Widget middle(BuildContext context) {
@ -25,15 +22,8 @@ class IoniaWelcomePage extends BasePage {
); );
} }
final IoniaGiftCardsListViewModel _cardsListViewModel;
@override @override
Widget body(BuildContext context) { Widget body(BuildContext context) {
reaction((_) => _cardsListViewModel.isLoggedIn, (bool state) {
if (state) {
Navigator.pushReplacementNamed(context, Routes.ioniaManageCardsPage);
}
});
return Padding( return Padding(
padding: const EdgeInsets.all(24.0), padding: const EdgeInsets.all(24.0),
child: Column( child: Column(
@ -41,7 +31,7 @@ class IoniaWelcomePage extends BasePage {
children: [ children: [
Column( Column(
children: [ children: [
SizedBox(height: 100), SizedBox(height: 90),
Text( Text(
S.of(context).about_cake_pay, S.of(context).about_cake_pay,
style: TextStyle( style: TextStyle(

View file

@ -17,7 +17,7 @@ import 'package:cake_wallet/generated/i18n.dart';
import 'package:flutter_mobx/flutter_mobx.dart'; import 'package:flutter_mobx/flutter_mobx.dart';
class IoniaManageCardsPage extends BasePage { class IoniaManageCardsPage extends BasePage {
IoniaManageCardsPage(this._cardsListViewModel) { IoniaManageCardsPage(this._cardsListViewModel): searchFocusNode = FocusNode() {
_searchController.addListener(() { _searchController.addListener(() {
if (_searchController.text != _cardsListViewModel.searchString) { if (_searchController.text != _cardsListViewModel.searchString) {
_searchDebounce.run(() { _searchDebounce.run(() {
@ -29,6 +29,7 @@ class IoniaManageCardsPage extends BasePage {
_cardsListViewModel.getMerchants(); _cardsListViewModel.getMerchants();
} }
final FocusNode searchFocusNode;
final IoniaGiftCardsListViewModel _cardsListViewModel; final IoniaGiftCardsListViewModel _cardsListViewModel;
final _searchDebounce = Debounce(Duration(milliseconds: 500)); final _searchDebounce = Debounce(Duration(milliseconds: 500));
@ -86,7 +87,14 @@ class IoniaManageCardsPage extends BasePage {
//highlightColor: Colors.transparent, //highlightColor: Colors.transparent,
//splashColor: Colors.transparent, //splashColor: Colors.transparent,
//padding: EdgeInsets.all(0), //padding: EdgeInsets.all(0),
onPressed: () => Navigator.pop(context), onPressed: (){
if (searchFocusNode.hasFocus) {
searchFocusNode.unfocus();
return;
}
Navigator.of(context).pop();
},
child: _backButton), child: _backButton),
), ),
); );
@ -149,6 +157,7 @@ class IoniaManageCardsPage extends BasePage {
Expanded( Expanded(
child: _SearchWidget( child: _SearchWidget(
controller: _searchController, controller: _searchController,
focusNode: searchFocusNode,
)), )),
SizedBox(width: 10), SizedBox(width: 10),
filterButton filterButton
@ -266,9 +275,10 @@ class _SearchWidget extends StatelessWidget {
const _SearchWidget({ const _SearchWidget({
Key? key, Key? key,
required this.controller, required this.controller,
required this.focusNode,
}) : super(key: key); }) : super(key: key);
final TextEditingController controller; final TextEditingController controller;
final FocusNode focusNode;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final searchIcon = Padding( final searchIcon = Padding(
@ -280,6 +290,7 @@ class _SearchWidget extends StatelessWidget {
); );
return TextField( return TextField(
focusNode: focusNode,
style: TextStyle(color: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!), style: TextStyle(color: Theme.of(context).accentTextTheme!.displayMedium!.backgroundColor!),
controller: controller, controller: controller,
decoration: InputDecoration( decoration: InputDecoration(

View file

@ -27,8 +27,7 @@ class AnonPayInvoicePage extends BasePage {
AnonPayInvoicePage( AnonPayInvoicePage(
this.anonInvoicePageViewModel, this.anonInvoicePageViewModel,
this.receiveOptionViewModel, this.receiveOptionViewModel,
) : _amountFocusNode = FocusNode() { ) : _amountFocusNode = FocusNode() {}
}
final _nameController = TextEditingController(); final _nameController = TextEditingController();
final _emailController = TextEditingController(); final _emailController = TextEditingController();
@ -53,6 +52,11 @@ class AnonPayInvoicePage extends BasePage {
@override @override
AppBarStyle get appBarStyle => AppBarStyle.transparent; AppBarStyle get appBarStyle => AppBarStyle.transparent;
@override
void onClose(BuildContext context) {
Navigator.popUntil(context, ModalRoute.withName(Routes.dashboard));
}
@override @override
Widget middle(BuildContext context) => Widget middle(BuildContext context) =>
PresentReceiveOptionPicker(receiveOptionViewModel: receiveOptionViewModel); PresentReceiveOptionPicker(receiveOptionViewModel: receiveOptionViewModel);
@ -65,114 +69,125 @@ class AnonPayInvoicePage extends BasePage {
anonInvoicePageViewModel.reset(); anonInvoicePageViewModel.reset();
}); });
Future<bool> _onNavigateBack(BuildContext context) async {
onClose(context);
return false;
}
@override @override
Widget body(BuildContext context) { Widget body(BuildContext context) {
WidgetsBinding.instance.addPostFrameCallback((_) => _setReactions(context)); WidgetsBinding.instance.addPostFrameCallback((_) => _setReactions(context));
return KeyboardActions( return WillPopScope(
disableScroll: true, onWillPop: () => _onNavigateBack(context),
config: KeyboardActionsConfig( child: KeyboardActions(
keyboardActionsPlatform: KeyboardActionsPlatform.IOS, disableScroll: true,
keyboardBarColor: Theme.of(context) config: KeyboardActionsConfig(
keyboardActionsPlatform: KeyboardActionsPlatform.IOS,
keyboardBarColor: Theme.of(context)
.accentTextTheme! .accentTextTheme!
.bodyLarge! .bodyLarge!
.backgroundColor!, .backgroundColor!,
nextFocus: false, nextFocus: false,
actions: [ actions: [
KeyboardActionsItem( KeyboardActionsItem(
focusNode: _amountFocusNode, focusNode: _amountFocusNode,
toolbarButtons: [(_) => KeyboardDoneButton()], toolbarButtons: [(_) => KeyboardDoneButton()],
),
]),
child: Container(
color: Theme.of(context).colorScheme.background,
child: ScrollableWithBottomSection(
contentPadding: EdgeInsets.only(bottom: 24),
content: Container(
decoration: DeviceInfo.instance.isMobile ? BoxDecoration(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)),
gradient: LinearGradient(
colors: [
Theme.of(context).primaryTextTheme!.titleSmall!.color!,
Theme.of(context).primaryTextTheme!.titleSmall!.decorationColor!,
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
), ),
) : null, ]),
child: Observer(builder: (_) { child: Container(
return Padding( color: Theme.of(context).colorScheme.background,
padding: EdgeInsets.fromLTRB(24, 120, 24, 0), child: ScrollableWithBottomSection(
child: AnonInvoiceForm( contentPadding: EdgeInsets.only(bottom: 24),
nameController: _nameController, content: Container(
descriptionController: _descriptionController, decoration: DeviceInfo.instance.isMobile
amountController: _amountController, ? BoxDecoration(
emailController: _emailController, borderRadius: BorderRadius.only(
depositAmountFocus: _amountFocusNode, bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24)),
formKey: _formKey, gradient: LinearGradient(
isInvoice: receiveOptionViewModel.selectedReceiveOption == colors: [
ReceivePageOption.anonPayInvoice, Theme.of(context).primaryTextTheme!.titleSmall!.color!,
anonInvoicePageViewModel: anonInvoicePageViewModel, Theme.of(context).primaryTextTheme!.titleSmall!.decorationColor!,
), ],
); begin: Alignment.topLeft,
}), end: Alignment.bottomRight,
), ),
bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24), )
bottomSection: Observer(builder: (_) { : null,
final isInvoice = child: Observer(builder: (_) {
receiveOptionViewModel.selectedReceiveOption == ReceivePageOption.anonPayInvoice; return Padding(
return Column( padding: EdgeInsets.fromLTRB(24, 120, 24, 0),
children: <Widget>[ child: AnonInvoiceForm(
Padding( nameController: _nameController,
padding: EdgeInsets.only(bottom: 15), descriptionController: _descriptionController,
child: Center( amountController: _amountController,
child: Text( emailController: _emailController,
isInvoice depositAmountFocus: _amountFocusNode,
? S.of(context).anonpay_description("an invoice", "pay") formKey: _formKey,
: S.of(context).anonpay_description("a donation link", "donate"), isInvoice: receiveOptionViewModel.selectedReceiveOption ==
textAlign: TextAlign.center, ReceivePageOption.anonPayInvoice,
style: TextStyle( anonInvoicePageViewModel: anonInvoicePageViewModel,
color: Theme.of(context) ),
);
}),
),
bottomSectionPadding: EdgeInsets.only(left: 24, right: 24, bottom: 24),
bottomSection: Observer(builder: (_) {
final isInvoice =
receiveOptionViewModel.selectedReceiveOption == ReceivePageOption.anonPayInvoice;
return Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(bottom: 15),
child: Center(
child: Text(
isInvoice
? S.of(context).anonpay_description("an invoice", "pay")
: S.of(context).anonpay_description("a donation link", "donate"),
textAlign: TextAlign.center,
style: TextStyle(
color: Theme.of(context)
.primaryTextTheme! .primaryTextTheme!
.displayLarge! .displayLarge!
.decorationColor!, .decorationColor!,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
fontSize: 12), fontSize: 12),
),
), ),
), ),
), LoadingPrimaryButton(
LoadingPrimaryButton( text: isInvoice
text: ? S.of(context).create_invoice
isInvoice ? S.of(context).create_invoice : S.of(context).create_donation_link, : S.of(context).create_donation_link,
onPressed: () { onPressed: () {
anonInvoicePageViewModel.setRequestParams( anonInvoicePageViewModel.setRequestParams(
inputAmount: _amountController.text, inputAmount: _amountController.text,
inputName: _nameController.text, inputName: _nameController.text,
inputEmail: _emailController.text, inputEmail: _emailController.text,
inputDescription: _descriptionController.text, inputDescription: _descriptionController.text,
); );
if (anonInvoicePageViewModel.receipientEmail.isNotEmpty && if (anonInvoicePageViewModel.receipientEmail.isNotEmpty &&
_formKey.currentState != null && _formKey.currentState != null &&
!_formKey.currentState!.validate()) { !_formKey.currentState!.validate()) {
return; return;
} }
if (isInvoice) { if (isInvoice) {
anonInvoicePageViewModel.createInvoice(); anonInvoicePageViewModel.createInvoice();
} else { } else {
anonInvoicePageViewModel.generateDonationLink(); anonInvoicePageViewModel.generateDonationLink();
} }
}, },
color: Theme.of(context) color: Theme.of(context)
.accentTextTheme! .accentTextTheme!
.bodyLarge! .bodyLarge!
.color!, .color!,
textColor: Colors.white, textColor: Colors.white,
isLoading: anonInvoicePageViewModel.state is IsExecutingState, isLoading: anonInvoicePageViewModel.state is IsExecutingState,
), ),
], ],
); );
}), }),
),
), ),
), ),
); );

View file

@ -266,6 +266,8 @@ class WalletRestorePage extends BasePage {
} }
void _confirmForm() { void _confirmForm() {
// Dismissing all visible keyboard to provide context for navigation
FocusManager.instance.primaryFocus?.unfocus();
final formContext = walletRestoreViewModel.mode == WalletRestoreMode.seed final formContext = walletRestoreViewModel.mode == WalletRestoreMode.seed
? walletRestoreFromSeedFormKey.currentContext ? walletRestoreFromSeedFormKey.currentContext
: walletRestoreFromKeysFormKey.currentContext; : walletRestoreFromKeysFormKey.currentContext;

View file

@ -0,0 +1,17 @@
import 'package:cake_wallet/ionia/ionia_service.dart';
import 'package:mobx/mobx.dart';
part 'market_place_view_model.g.dart';
class MarketPlaceViewModel = MarketPlaceViewModelBase with _$MarketPlaceViewModel;
abstract class MarketPlaceViewModelBase with Store {
final IoniaService _ioniaService;
MarketPlaceViewModelBase(this._ioniaService);
Future<bool> isIoniaUserAuthenticated() async {
return await _ioniaService.isLogined();
}
}

View file

@ -16,12 +16,10 @@ abstract class IoniaGiftCardsListViewModelBase with Store {
ioniaCategories = IoniaCategory.allCategories, ioniaCategories = IoniaCategory.allCategories,
selectedIndices = ObservableList<IoniaCategory>.of([IoniaCategory.all]), selectedIndices = ObservableList<IoniaCategory>.of([IoniaCategory.all]),
scrollOffsetFromTop = 0.0, scrollOffsetFromTop = 0.0,
isLoggedIn = false,
merchantState = InitialIoniaMerchantLoadingState(), merchantState = InitialIoniaMerchantLoadingState(),
createCardState = IoniaCreateCardState(), createCardState = IoniaCreateCardState(),
searchString = '', searchString = '',
ioniaMerchantList = <IoniaMerchant>[] { ioniaMerchantList = <IoniaMerchant>[] {
_getAuthStatus().then((value) => isLoggedIn = value);
} }
final IoniaService ioniaService; final IoniaService ioniaService;
@ -45,24 +43,17 @@ abstract class IoniaGiftCardsListViewModelBase with Store {
@observable @observable
List<IoniaMerchant> ioniaMerchants; List<IoniaMerchant> ioniaMerchants;
@observable
bool isLoggedIn;
@observable @observable
List<IoniaCategory> ioniaCategories; List<IoniaCategory> ioniaCategories;
@observable @observable
ObservableList<IoniaCategory> selectedIndices; ObservableList<IoniaCategory> selectedIndices;
Future<bool> _getAuthStatus() async {
return await ioniaService.isLogined();
}
@action @action
Future<void> createCard() async { Future<void> createCard() async {
try { try {
createCardState = IoniaCreateCardLoading(); createCardState = IoniaCreateCardLoading();
final card = await ioniaService.createCard(); await ioniaService.createCard();
createCardState = IoniaCreateCardSuccess(); createCardState = IoniaCreateCardSuccess();
} catch (e) { } catch (e) {
createCardState = IoniaCreateCardFailure(error: e.toString()); createCardState = IoniaCreateCardFailure(error: e.toString());