diff --git a/lib/src/screens/dashboard/pages/transactions_page.dart b/lib/src/screens/dashboard/pages/transactions_page.dart index efdd764f1..7c0e9cad4 100644 --- a/lib/src/screens/dashboard/pages/transactions_page.dart +++ b/lib/src/screens/dashboard/pages/transactions_page.dart @@ -2,7 +2,6 @@ import 'package:cake_wallet/src/screens/dashboard/widgets/anonpay_transaction_ro import 'package:cake_wallet/src/screens/dashboard/widgets/order_row.dart'; import 'package:cake_wallet/themes/extensions/placeholder_theme.dart'; import 'package:cake_wallet/src/widgets/dashboard_card_widget.dart'; -import 'package:cake_wallet/utils/device_info.dart'; import 'package:cake_wallet/utils/responsive_layout_util.dart'; import 'package:cake_wallet/view_model/dashboard/anonpay_transaction_list_item.dart'; import 'package:cake_wallet/view_model/dashboard/order_list_item.dart'; @@ -53,11 +52,7 @@ class TransactionsPage extends StatelessWidget { try { final uri = Uri.parse( "https://guides.cakewallet.com/docs/FAQ/why_are_my_funds_not_appearing/"); - if (DeviceInfo.instance.isMobile) { - Navigator.of(context).pushNamed(Routes.webViewPage, arguments: ['', uri]); - } else { - launchUrl(uri); - } + launchUrl(uri, mode: LaunchMode.externalApplication); } catch (_) {} }, title: S.of(context).syncing_wallet_alert_title, diff --git a/lib/src/screens/disclaimer/disclaimer_page.dart b/lib/src/screens/disclaimer/disclaimer_page.dart index 3805f6240..f82a9efbe 100644 --- a/lib/src/screens/disclaimer/disclaimer_page.dart +++ b/lib/src/screens/disclaimer/disclaimer_page.dart @@ -46,10 +46,6 @@ class DisclaimerBodyState extends State { bool _checked = false; String _fileText = ''; - Future launchUrl(String url) async { - if (await canLaunch(url)) await launch(url); - } - Future getFileLines() async { _fileText = await rootBundle.loadString( isMoneroOnly @@ -152,7 +148,11 @@ class DisclaimerBodyState extends State { children: [ Expanded( child: GestureDetector( - onTap: () => launchUrl(changenowUrl), + onTap: () async { + final uri = Uri.parse(changenowUrl); + if (await canLaunchUrl(uri)) + await launchUrl(uri, mode: LaunchMode.externalApplication); + }, child: Text( changenowUrl, textAlign: TextAlign.left, diff --git a/lib/src/screens/ionia/auth/ionia_create_account_page.dart b/lib/src/screens/ionia/auth/ionia_create_account_page.dart new file mode 100644 index 000000000..4762216c1 --- /dev/null +++ b/lib/src/screens/ionia/auth/ionia_create_account_page.dart @@ -0,0 +1,163 @@ +import 'package:cake_wallet/themes/extensions/cake_text_theme.dart'; +import 'package:cake_wallet/core/email_validator.dart'; +import 'package:cake_wallet/ionia/ionia_create_state.dart'; +import 'package:cake_wallet/routes.dart'; +import 'package:cake_wallet/src/screens/base_page.dart'; +import 'package:cake_wallet/src/widgets/alert_with_one_action.dart'; +import 'package:cake_wallet/src/widgets/base_text_form_field.dart'; +import 'package:cake_wallet/src/widgets/primary_button.dart'; +import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart'; +import 'package:cake_wallet/typography.dart'; +import 'package:cake_wallet/utils/show_pop_up.dart'; +import 'package:cake_wallet/view_model/ionia/ionia_auth_view_model.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:cake_wallet/generated/i18n.dart'; +import 'package:flutter_mobx/flutter_mobx.dart'; +import 'package:mobx/mobx.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class IoniaCreateAccountPage extends BasePage { + IoniaCreateAccountPage(this._authViewModel) + : _emailFocus = FocusNode(), + _emailController = TextEditingController(), + _formKey = GlobalKey() { + _emailController.text = _authViewModel.email; + _emailController.addListener(() => _authViewModel.email = _emailController.text); + } + + final IoniaAuthViewModel _authViewModel; + + final GlobalKey _formKey; + + final FocusNode _emailFocus; + final TextEditingController _emailController; + + static const privacyPolicyUrl = 'https://ionia.docsend.com/view/jhjvdn7qq7k3ukwt'; + static const termsAndConditionsUrl = 'https://ionia.docsend.com/view/uceirymz2ijacq5g'; + + @override + Widget middle(BuildContext context) { + return Text( + S.current.sign_up, + style: textMediumSemiBold( + color: Theme.of(context).extension()!.titleColor, + ), + ); + } + + @override + Widget body(BuildContext context) { + reaction((_) => _authViewModel.createUserState, (IoniaCreateAccountState state) { + if (state is IoniaCreateStateFailure) { + _onCreateUserFailure(context, state.error); + } + if (state is IoniaCreateStateSuccess) { + _onCreateSuccessful(context, _authViewModel); + } + }); + + return ScrollableWithBottomSection( + contentPadding: EdgeInsets.all(24), + content: Form( + key: _formKey, + child: BaseTextFormField( + hintText: S.of(context).email_address, + focusNode: _emailFocus, + validator: EmailValidator(), + keyboardType: TextInputType.emailAddress, + controller: _emailController, + onSubmit: (_) => _createAccount(), + ), + ), + bottomSectionPadding: EdgeInsets.symmetric(vertical: 36, horizontal: 24), + bottomSection: Column( + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Observer( + builder: (_) => LoadingPrimaryButton( + text: S.of(context).create_account, + onPressed: _createAccount, + isLoading: + _authViewModel.createUserState is IoniaCreateStateLoading, + color: Theme.of(context).primaryColor, + textColor: Colors.white, + ), + ), + SizedBox( + height: 20, + ), + RichText( + textAlign: TextAlign.center, + text: TextSpan( + text: S.of(context).agree_to, + style: TextStyle( + color: Color(0xff7A93BA), + fontSize: 12, + fontFamily: 'Lato', + ), + children: [ + TextSpan( + text: S.of(context).settings_terms_and_conditions, + style: TextStyle( + color: Theme.of(context).primaryColor, + fontWeight: FontWeight.w700, + ), + recognizer: TapGestureRecognizer() + ..onTap = () async { + final uri = Uri.parse(termsAndConditionsUrl); + if (await canLaunchUrl(uri)) + await launchUrl(uri, mode: LaunchMode.externalApplication); + }, + ), + TextSpan(text: ' ${S.of(context).and} '), + TextSpan( + text: S.of(context).privacy_policy, + style: TextStyle( + color: Theme.of(context).primaryColor, + fontWeight: FontWeight.w700, + ), + recognizer: TapGestureRecognizer() + ..onTap = () async { + final uri = Uri.parse(privacyPolicyUrl); + if (await canLaunchUrl(uri)) + await launchUrl(uri, mode: LaunchMode.externalApplication); + }), + TextSpan(text: ' ${S.of(context).by_cake_pay}'), + ], + ), + ), + ], + ), + ], + ), + ); + } + + void _onCreateUserFailure(BuildContext context, String error) { + showPopUp( + context: context, + builder: (BuildContext context) { + return AlertWithOneAction( + alertTitle: S.current.create_account, + alertContent: error, + buttonText: S.of(context).ok, + buttonAction: () => Navigator.of(context).pop()); + }); + } + + void _onCreateSuccessful(BuildContext context, IoniaAuthViewModel authViewModel) => Navigator.pushNamed( + context, + Routes.ioniaVerifyIoniaOtpPage, + arguments: [authViewModel.email, false], + ); + + void _createAccount() async { + if (_formKey.currentState != null && !_formKey.currentState!.validate()) { + return; + } + await _authViewModel.createUser(_emailController.text); + } +} diff --git a/lib/src/screens/settings/widgets/settings_link_provider_cell.dart b/lib/src/screens/settings/widgets/settings_link_provider_cell.dart index 6e5d48a69..5b6d1881f 100644 --- a/lib/src/screens/settings/widgets/settings_link_provider_cell.dart +++ b/lib/src/screens/settings/widgets/settings_link_provider_cell.dart @@ -31,7 +31,8 @@ class SettingsLinkProviderCell extends StandardListRow { static void _launchUrl(String url) async { try { - await launch(url, forceSafariVC: false); + final uri = Uri.parse(url); + if (await canLaunchUrl(uri)) await launchUrl(uri, mode: LaunchMode.externalApplication); } catch (e) {} } } diff --git a/lib/src/screens/yat/yat_popup.dart b/lib/src/screens/yat/yat_popup.dart index 89a23d9c7..4ccd24259 100644 --- a/lib/src/screens/yat/yat_popup.dart +++ b/lib/src/screens/yat/yat_popup.dart @@ -161,27 +161,26 @@ class YatPopup extends StatelessWidget { onClose: onClose, onGet: () { var createNewYatUrl = YatLink.startFlowUrl; - final createNewYatUrlParameters = dashboardViewModel. - yatStore.defineQueryParameters(); - + final createNewYatUrlParameters = + dashboardViewModel.yatStore.defineQueryParameters(); + if (createNewYatUrlParameters.isNotEmpty) { createNewYatUrl += '?sub1=' + createNewYatUrlParameters; } - launch(createNewYatUrl, forceSafariVC: false); + final uri = Uri.parse(createNewYatUrl); + launchUrl(uri, mode: LaunchMode.externalApplication); }, onConnect: () { String url = baseUrl + YatLink.signInSuffix; - final parameters = dashboardViewModel - .yatStore.defineQueryParameters(); + final parameters = dashboardViewModel.yatStore.defineQueryParameters(); if (parameters.isNotEmpty) { url += YatLink.queryParameter + parameters; } - launch(url, forceSafariVC: false); - } - )) - : Container() - ) + final uri = Uri.parse(url); + launchUrl(uri, mode: LaunchMode.externalApplication); + })) + : Container()) ], ); } diff --git a/lib/src/widgets/services_updates_widget.dart b/lib/src/widgets/services_updates_widget.dart index 5d56e967d..1babd23d0 100644 --- a/lib/src/widgets/services_updates_widget.dart +++ b/lib/src/widgets/services_updates_widget.dart @@ -103,7 +103,8 @@ class _ServicesUpdatesWidgetState extends State { child: PrimaryImageButton( onPressed: () { try { - launchUrl(Uri.parse("https://status.cakewallet.com/")); + launchUrl(Uri.parse("https://status.cakewallet.com/"), + mode: LaunchMode.externalApplication); } catch (_) {} }, image: Image.asset( diff --git a/lib/view_model/order_details_view_model.dart b/lib/view_model/order_details_view_model.dart index 412f1b962..1eab2f861 100644 --- a/lib/view_model/order_details_view_model.dart +++ b/lib/view_model/order_details_view_model.dart @@ -19,7 +19,7 @@ class OrderDetailsViewModel = OrderDetailsViewModelBase abstract class OrderDetailsViewModelBase with Store { OrderDetailsViewModelBase({required WalletBase wallet, required Order orderForDetails}) - : items = ObservableList(), + : items = ObservableList(), order = orderForDetails { if (order.provider != null) { switch (order.provider) { @@ -101,13 +101,13 @@ abstract class OrderDetailsViewModelBase with Store { TrackTradeListItem( title: S.current.track, value: buildURL, - onTap: () { + onTap: () async { try { - launch(buildURL); + final uri = Uri.parse(buildURL); + if (await canLaunchUrl(uri)) + await launchUrl(uri, mode: LaunchMode.externalApplication); } catch (e) {} - } - ) - ); + })); } } diff --git a/lib/view_model/trade_details_view_model.dart b/lib/view_model/trade_details_view_model.dart index c88008982..eed1b6c75 100644 --- a/lib/view_model/trade_details_view_model.dart +++ b/lib/view_model/trade_details_view_model.dart @@ -179,7 +179,7 @@ abstract class TradeDetailsViewModelBase with Store { void _launchUrl(String url) { final uri = Uri.parse(url); try { - launchUrl(uri); + launchUrl(uri, mode: LaunchMode.externalApplication); } catch (e) {} } } diff --git a/lib/view_model/transaction_details_view_model.dart b/lib/view_model/transaction_details_view_model.dart index 5b7a1a8db..acf334382 100644 --- a/lib/view_model/transaction_details_view_model.dart +++ b/lib/view_model/transaction_details_view_model.dart @@ -103,9 +103,10 @@ abstract class TransactionDetailsViewModelBase with Store { items.add(BlockExplorerListItem( title: S.current.view_in_block_explorer, value: _explorerDescription(type), - onTap: () { + onTap: () async { try { - launch(_explorerUrl(type, tx.id)); + final uri = Uri.parse(_explorerUrl(type, tx.id)); + if (await canLaunchUrl(uri)) await launchUrl(uri, mode: LaunchMode.externalApplication); } catch (e) {} })); diff --git a/lib/view_model/unspent_coins/unspent_coins_details_view_model.dart b/lib/view_model/unspent_coins/unspent_coins_details_view_model.dart index fd142dd33..16f59aeb9 100644 --- a/lib/view_model/unspent_coins/unspent_coins_details_view_model.dart +++ b/lib/view_model/unspent_coins/unspent_coins_details_view_model.dart @@ -56,7 +56,7 @@ abstract class UnspentCoinsDetailsViewModelBase with Store { onTap: () { try { final url = Uri.parse(_explorerUrl(_type, unspentCoinsItem.hash)); - return launchUrl(url); + return launchUrl(url, mode: LaunchMode.externalApplication); } catch (e) {} }, ));