From f2460c39d4767b328701087d2b3e64c02d82b659 Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 26 May 2025 10:10:28 -0600 Subject: [PATCH 1/6] liberal use of `SafeArea` --- .../add_token_view/add_custom_token_view.dart | 140 +- .../edit_wallet_tokens_view.dart | 525 ++-- .../add_wallet_view/add_wallet_view.dart | 310 +- .../select_new_frost_import_type_view.dart | 161 +- .../name_your_wallet_view.dart | 518 ++-- .../address_book_views/address_book_view.dart | 276 +- .../subviews/add_address_book_entry_view.dart | 664 ++--- .../add_new_contact_address_view.dart | 150 +- .../subviews/address_book_filter_view.dart | 96 +- .../subviews/contact_details_view.dart | 680 +++-- .../subviews/edit_contact_address_view.dart | 175 +- .../edit_contact_name_emoji_view.dart | 281 +- lib/pages/buy_view/buy_order_details.dart | 133 +- lib/pages/buy_view/buy_quote_preview.dart | 107 +- .../sub_widgets/crypto_selection_view.dart | 94 +- .../sub_widgets/fiat_selection_view.dart | 225 +- lib/pages/cashfusion/cashfusion_view.dart | 501 ++-- .../cashfusion/fusion_progress_view.dart | 151 +- .../churning/churning_progress_view.dart | 175 +- lib/pages/churning/churning_view.dart | 199 +- .../exchange_view/choose_from_stack_view.dart | 159 +- .../confirm_change_now_send.dart | 38 +- .../exchange_view/edit_trade_note_view.dart | 155 +- .../exchange_currency_selection_view.dart | 343 +-- .../exchange_step_views/step_1_view.dart | 274 +- .../exchange_step_views/step_2_view.dart | 917 +++--- .../exchange_step_views/step_3_view.dart | 478 ++-- .../exchange_step_views/step_4_view.dart | 817 +++--- lib/pages/exchange_view/send_from_view.dart | 4 +- .../exchange_view/trade_details_view.dart | 14 +- .../wallet_initiated_exchange_view.dart | 103 +- lib/pages/generic/single_field_edit_view.dart | 220 +- lib/pages/home_view/home_view.dart | 310 +- lib/pages/intro_view.dart | 320 +-- lib/pages/loading_view.dart | 66 +- lib/pages/monkey/monkey_view.dart | 2 +- .../confirm_name_transaction_view.dart | 43 +- .../notifications_view.dart | 120 +- lib/pages/ordinals/ordinal_details_view.dart | 21 +- lib/pages/ordinals/ordinals_filter_view.dart | 383 ++- lib/pages/ordinals/ordinals_view.dart | 135 +- .../addresses/edit_address_label_view.dart | 316 +-- .../addresses/wallet_addresses_view.dart | 296 +- .../generate_receiving_uri_qr_code_view.dart | 427 +-- lib/pages/receive_view/receive_view.dart | 508 ++-- .../send_view/confirm_transaction_view.dart | 42 +- .../send_view/frost_ms/frost_send_view.dart | 295 +- lib/pages/send_view/send_view.dart | 2016 ++++++------- lib/pages/send_view/token_send_view.dart | 1114 ++++---- .../global_settings_view/about_view.dart | 633 ++--- .../advanced_settings_view.dart | 495 ++-- .../edit_coin_units_view.dart | 8 +- .../manage_coin_units_view.dart | 2 +- .../advanced_views/manage_explorer_view.dart | 121 +- .../appearance_settings_view.dart | 217 +- .../appearance_settings/manage_themes.dart | 310 +- ...ystem_brightness_theme_selection_view.dart | 161 +- .../global_settings_view/currency_view.dart | 281 +- .../global_settings_view.dart | 469 ++- .../global_settings_view/hidden_settings.dart | 596 ++-- .../global_settings_view/language_view.dart | 246 +- .../add_edit_node_view.dart | 42 +- .../manage_nodes_views/manage_nodes_view.dart | 70 +- .../manage_nodes_views/node_details_view.dart | 336 ++- .../security_views/security_view.dart | 436 +-- .../stack_backup_views/auto_backup_view.dart | 435 ++- .../create_auto_backup_view.dart | 1062 +++---- .../create_backup_information_view.dart | 101 +- .../create_backup_view.dart | 401 ++- .../edit_auto_backup_view.dart | 377 ++- .../restore_from_encrypted_string_view.dart | 345 +-- .../restore_from_file_view.dart | 326 ++- .../stack_backup_views/stack_backup_view.dart | 231 +- .../sub_views/recovery_phrase_view.dart | 83 +- .../stack_restore_progress_view.dart | 684 ++--- .../startup_preferences_view.dart | 511 ++-- .../startup_wallet_selection_view.dart | 302 +- .../global_settings_view/support_view.dart | 96 +- .../syncing_options_view.dart | 182 +- .../syncing_preferences_view.dart | 219 +- .../wallet_syncing_options_view.dart | 66 +- .../tor_settings/tor_settings_view.dart | 262 +- .../frost_ms/frost_ms_options_view.dart | 107 +- .../wallet_backup_view.dart | 250 +- .../wallet_network_settings_view.dart | 543 ++-- .../wallet_settings_view.dart | 748 ++--- .../change_representative_view.dart | 325 +-- .../delete_wallet_recovery_phrase_view.dart | 484 ++-- .../delete_wallet_warning_view.dart | 242 +- .../edit_refresh_height_view.dart | 100 +- .../lelantus_settings_view.dart | 141 +- .../rbf_settings_view.dart | 93 +- .../rename_wallet_view.dart | 185 +- .../spark_info.dart | 54 +- .../wallet_settings_wallet_settings_view.dart | 574 ++-- .../xpub_view.dart | 224 +- .../confirm_spark_name_transaction_view.dart | 42 +- .../firo_rescan_recovery_error_dialog.dart | 286 +- lib/pages/token_view/my_tokens_view.dart | 212 +- lib/pages/token_view/token_view.dart | 171 +- .../transaction_views/edit_note_view.dart | 210 +- .../transaction_details_view.dart | 2216 ++++++++------- .../transaction_search_filter_view.dart | 510 ++-- .../tx_v2/boost_transaction_view.dart | 2 +- .../tx_v2/fusion_group_details_view.dart | 84 +- .../tx_v2/transaction_v2_details_view.dart | 2506 +++++++++-------- lib/widgets/desktop/desktop_scaffold.dart | 14 +- 107 files changed, 17699 insertions(+), 18227 deletions(-) diff --git a/lib/pages/add_wallet_views/add_token_view/add_custom_token_view.dart b/lib/pages/add_wallet_views/add_token_view/add_custom_token_view.dart index 210fc954f..8d141eb15 100644 --- a/lib/pages/add_wallet_views/add_token_view/add_custom_token_view.dart +++ b/lib/pages/add_wallet_views/add_token_view/add_custom_token_view.dart @@ -29,9 +29,7 @@ import '../../../widgets/desktop/secondary_button.dart'; import '../../../widgets/stack_dialog.dart'; class AddCustomTokenView extends ConsumerStatefulWidget { - const AddCustomTokenView({ - super.key, - }); + const AddCustomTokenView({super.key}); static const routeName = "/addCustomToken"; @@ -56,60 +54,62 @@ class _AddCustomTokenViewState extends ConsumerState { Widget build(BuildContext context) { return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () { - Navigator.of(context).pop(); - }, - ), - ), - body: Padding( - padding: const EdgeInsets.only( - top: 10, - left: 16, - right: 16, - bottom: 16, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only( + top: 10, + left: 16, + right: 16, + bottom: 16, + ), + child: child, + ), + ), ), - child: child, ), - ), - ), child: ConditionalParent( condition: isDesktop, - builder: (child) => Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + builder: + (child) => Column( children: [ - Padding( - padding: const EdgeInsets.only( - left: 32, - ), - child: Text( - "Add custom ETH token", - style: STextStyles.desktopH3(context), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "Add custom ETH token", + style: STextStyles.desktopH3(context), + ), + ), + const DesktopDialogCloseButton(), + ], + ), + Flexible( + child: Padding( + padding: const EdgeInsets.only( + left: 32, + right: 32, + bottom: 32, + top: 16, + ), + child: child, ), ), - const DesktopDialogCloseButton(), ], ), - Flexible( - child: Padding( - padding: const EdgeInsets.only( - left: 32, - right: 32, - bottom: 32, - top: 16, - ), - child: child, - ), - ), - ], - ), child: Column( children: [ if (!isDesktop) @@ -117,10 +117,7 @@ class _AddCustomTokenViewState extends ConsumerState { "Add custom ETH token", style: STextStyles.pageTitleH1(context), ), - if (!isDesktop) - const SizedBox( - height: 16, - ), + if (!isDesktop) const SizedBox(height: 16), TextField( autocorrect: !isDesktop, enableSuggestions: !isDesktop, @@ -131,9 +128,7 @@ class _AddCustomTokenViewState extends ConsumerState { hintStyle: STextStyles.fieldLabel(context), ), ), - SizedBox( - height: isDesktop ? 16 : 8, - ), + SizedBox(height: isDesktop ? 16 : 8), PrimaryButton( label: "Search", onPressed: () async { @@ -157,10 +152,11 @@ class _AddCustomTokenViewState extends ConsumerState { unawaited( showDialog( context: context, - builder: (context) => StackOkDialog( - title: "Failed to look up token", - message: response!.exception?.message, - ), + builder: + (context) => StackOkDialog( + title: "Failed to look up token", + message: response!.exception?.message, + ), ), ); } @@ -170,9 +166,7 @@ class _AddCustomTokenViewState extends ConsumerState { }); }, ), - SizedBox( - height: isDesktop ? 16 : 8, - ), + SizedBox(height: isDesktop ? 16 : 8), TextField( enabled: enableSubFields, autocorrect: !isDesktop, @@ -184,9 +178,7 @@ class _AddCustomTokenViewState extends ConsumerState { hintStyle: STextStyles.fieldLabel(context), ), ), - SizedBox( - height: isDesktop ? 16 : 8, - ), + SizedBox(height: isDesktop ? 16 : 8), if (isDesktop) Row( children: [ @@ -203,9 +195,7 @@ class _AddCustomTokenViewState extends ConsumerState { ), ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: TextField( enabled: enableSubFields, @@ -245,10 +235,7 @@ class _AddCustomTokenViewState extends ConsumerState { hintStyle: STextStyles.fieldLabel(context), ), ), - if (!isDesktop) - const SizedBox( - height: 8, - ), + if (!isDesktop) const SizedBox(height: 8), if (!isDesktop) TextField( enabled: enableSubFields, @@ -273,9 +260,7 @@ class _AddCustomTokenViewState extends ConsumerState { hintStyle: STextStyles.fieldLabel(context), ), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), const Spacer(), Row( children: [ @@ -286,10 +271,7 @@ class _AddCustomTokenViewState extends ConsumerState { onPressed: Navigator.of(context).pop, ), ), - if (isDesktop) - const SizedBox( - width: 16, - ), + if (isDesktop) const SizedBox(width: 16), Expanded( child: PrimaryButton( label: "Add token", diff --git a/lib/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart b/lib/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart index 46fa6f333..3294ce18f 100644 --- a/lib/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart +++ b/lib/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart @@ -96,10 +96,11 @@ class _EditWalletTokensViewState extends ConsumerState { } Future onNextPressed() async { - final selectedTokens = tokenEntities - .where((e) => e.selected) - .map((e) => e.token.address) - .toList(); + final selectedTokens = + tokenEntities + .where((e) => e.selected) + .map((e) => e.token.address) + .toList(); final ethWallet = ref.read(pWallets).getWallet(widget.walletId) as EthereumWallet; @@ -110,14 +111,13 @@ class _EditWalletTokensViewState extends ConsumerState { Navigator.of(context).pop(42); } else { if (isDesktop) { - Navigator.of(context).popUntil( - ModalRoute.withName(DesktopHomeView.routeName), - ); + Navigator.of( + context, + ).popUntil(ModalRoute.withName(DesktopHomeView.routeName)); } else { - await Navigator.of(context).pushNamedAndRemoveUntil( - HomeView.routeName, - (route) => false, - ); + await Navigator.of( + context, + ).pushNamedAndRemoveUntil(HomeView.routeName, (route) => false); } if (mounted) { unawaited( @@ -138,16 +138,17 @@ class _EditWalletTokensViewState extends ConsumerState { if (isDesktop) { contract = await showDialog( context: context, - builder: (context) => const DesktopDialog( - maxWidth: 580, - maxHeight: 500, - child: AddCustomTokenView(), - ), + builder: + (context) => const DesktopDialog( + maxWidth: 580, + maxHeight: 500, + child: AddCustomTokenView(), + ), ); } else { - final result = await Navigator.of(context).pushNamed( - AddCustomTokenView.routeName, - ); + final result = await Navigator.of( + context, + ).pushNamed(AddCustomTokenView.routeName); contract = result as EthContract?; } @@ -159,8 +160,9 @@ class _EditWalletTokensViewState extends ConsumerState { if (tokenEntities .where((e) => e.token.address == contract!.address) .isEmpty) { - tokenEntities - .add(AddTokenListElementData(contract!)..selected = true); + tokenEntities.add( + AddTokenListElementData(contract!)..selected = true, + ); tokenEntities.sort((a, b) => a.token.name.compareTo(b.token.name)); } }); @@ -178,7 +180,9 @@ class _EditWalletTokensViewState extends ConsumerState { if (contracts.isEmpty) { contracts.addAll(DefaultTokens.list); - MainDB.instance.putEthContracts(contracts).then( + MainDB.instance + .putEthContracts(contracts) + .then( (_) => ref.read(priceAnd24hChangeNotifierProvider).updatePrice(), ); } @@ -214,149 +218,135 @@ class _EditWalletTokensViewState extends ConsumerState { if (isDesktop) { return ConditionalParent( condition: !widget.isDesktopPopup, - builder: (child) => DesktopScaffold( - appBar: DesktopAppBar( - isCompactHeight: false, - useSpacers: false, - leading: const AppBarBackButton(), - overlayCenter: Text( - walletName, - style: STextStyles.desktopSubtitleH2(context), - ), - trailing: widget.contractsToMarkSelected == null - ? Padding( - padding: const EdgeInsets.only( - right: 24, - ), - child: SizedBox( - height: 56, - child: TextButton( - style: Theme.of(context) - .extension()! - .getSmallSecondaryEnabledButtonStyle(context), - onPressed: _addToken, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 30, - ), - child: Text( - "Add custom token", - style: - STextStyles.desktopButtonSmallSecondaryEnabled( - context, + builder: + (child) => DesktopScaffold( + appBar: DesktopAppBar( + isCompactHeight: false, + useSpacers: false, + leading: const AppBarBackButton(), + overlayCenter: Text( + walletName, + style: STextStyles.desktopSubtitleH2(context), + ), + trailing: + widget.contractsToMarkSelected == null + ? Padding( + padding: const EdgeInsets.only(right: 24), + child: SizedBox( + height: 56, + child: TextButton( + style: Theme.of(context) + .extension()! + .getSmallSecondaryEnabledButtonStyle(context), + onPressed: _addToken, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 30, + ), + child: Text( + "Add custom token", + style: + STextStyles.desktopButtonSmallSecondaryEnabled( + context, + ), + ), + ), ), ), + ) + : null, + ), + body: SizedBox( + width: 480, + child: Column( + children: [ + const AddTokenText(isDesktop: true), + const SizedBox(height: 16), + Expanded( + child: RoundedWhiteContainer( + radiusMultiplier: 2, + padding: const EdgeInsets.only( + left: 20, + top: 20, + right: 20, + bottom: 0, ), + child: child, ), ), - ) - : null, - ), - body: SizedBox( - width: 480, - child: Column( - children: [ - const AddTokenText( - isDesktop: true, - ), - const SizedBox( - height: 16, - ), - Expanded( - child: RoundedWhiteContainer( - radiusMultiplier: 2, - padding: const EdgeInsets.only( - left: 20, - top: 20, - right: 20, - bottom: 0, + const SizedBox(height: 26), + SizedBox( + height: 70, + width: 480, + child: PrimaryButton( + label: + widget.contractsToMarkSelected != null + ? "Save" + : "Next", + onPressed: onNextPressed, + ), ), - child: child, - ), - ), - const SizedBox( - height: 26, - ), - SizedBox( - height: 70, - width: 480, - child: PrimaryButton( - label: widget.contractsToMarkSelected != null - ? "Save" - : "Next", - onPressed: onNextPressed, - ), - ), - const SizedBox( - height: 32, + const SizedBox(height: 32), + ], ), - ], + ), ), - ), - ), child: ConditionalParent( condition: widget.isDesktopPopup, - builder: (child) => DesktopDialog( - maxHeight: 670, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + builder: + (child) => DesktopDialog( + maxHeight: 670, + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - Padding( - padding: const EdgeInsets.only( - left: 32, - ), - child: Text( - "Edit tokens", - style: STextStyles.desktopH3(context), - ), - ), - const DesktopDialogCloseButton(), - ], - ), - Expanded( - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 32, - vertical: 16, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "Edit tokens", + style: STextStyles.desktopH3(context), + ), + ), + const DesktopDialogCloseButton(), + ], ), - child: child, - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 32, - ), - child: Row( - children: [ - Expanded( - child: SecondaryButton( - label: "Add custom token", - buttonHeight: ButtonHeight.l, - onPressed: _addToken, + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 32, + vertical: 16, ), + child: child, ), - const SizedBox( - width: 16, - ), - Expanded( - child: PrimaryButton( - label: "Done", - buttonHeight: ButtonHeight.l, - onPressed: onNextPressed, - ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 32), + child: Row( + children: [ + Expanded( + child: SecondaryButton( + label: "Add custom token", + buttonHeight: ButtonHeight.l, + onPressed: _addToken, + ), + ), + const SizedBox(width: 16), + Expanded( + child: PrimaryButton( + label: "Done", + buttonHeight: ButtonHeight.l, + onPressed: onNextPressed, + ), + ), + ], ), - ], - ), - ), - const SizedBox( - height: 32, + ), + const SizedBox(height: 32), + ], ), - ], - ), - ), + ), child: Column( children: [ ClipRRect( @@ -373,17 +363,15 @@ class _EditWalletTokensViewState extends ConsumerState { _searchTerm = value; }); }, - style: STextStyles.desktopTextMedium(context).copyWith( - height: 2, - ), + style: STextStyles.desktopTextMedium( + context, + ).copyWith(height: 2), decoration: standardInputDecoration( "Search", _searchFocusNode, context, ).copyWith( - contentPadding: const EdgeInsets.symmetric( - vertical: 10, - ), + contentPadding: const EdgeInsets.symmetric(vertical: 10), prefixIcon: Padding( padding: const EdgeInsets.symmetric( horizontal: 16, @@ -393,40 +381,37 @@ class _EditWalletTokensViewState extends ConsumerState { Assets.svg.search, width: 24, height: 24, - color: Theme.of(context) - .extension()! - .textFieldDefaultSearchIconLeft, + color: + Theme.of(context) + .extension()! + .textFieldDefaultSearchIconLeft, ), ), - suffixIcon: _searchFieldController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 10), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon( - width: 24, - height: 24, + suffixIcon: + _searchFieldController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 10), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(width: 24, height: 24), + onTap: () async { + setState(() { + _searchFieldController.text = ""; + _searchTerm = ""; + }); + }, ), - onTap: () async { - setState(() { - _searchFieldController.text = ""; - _searchTerm = ""; - }); - }, - ), - ], + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Expanded( child: AddTokenList( walletId: widget.walletId, @@ -434,9 +419,7 @@ class _EditWalletTokensViewState extends ConsumerState { addFunction: isDesktop ? null : _addToken, ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), ], ), ), @@ -454,11 +437,7 @@ class _EditWalletTokensViewState extends ConsumerState { ), actions: [ Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 20, - ), + padding: const EdgeInsets.only(top: 10, bottom: 10, right: 20), child: AspectRatio( aspectRatio: 1, child: AppBarIconButton( @@ -468,9 +447,10 @@ class _EditWalletTokensViewState extends ConsumerState { Theme.of(context).extension()!.background, icon: SvgPicture.asset( Assets.svg.circlePlusFilled, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, width: 20, height: 20, ), @@ -480,92 +460,89 @@ class _EditWalletTokensViewState extends ConsumerState { ), ], ), - body: Container( - color: Theme.of(context).extension()!.background, - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - AddTokenText( - isDesktop: false, - walletName: walletName, - ), - const SizedBox( - height: 16, - ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autofocus: isDesktop, - autocorrect: !isDesktop, - enableSuggestions: !isDesktop, - controller: _searchFieldController, - focusNode: _searchFocusNode, - onChanged: (value) => setState(() => _searchTerm = value), - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Search", - _searchFocusNode, - context, - desktopMed: isDesktop, - ).copyWith( - prefixIcon: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 16, - ), - child: SvgPicture.asset( - Assets.svg.search, - width: 16, - height: 16, + body: SafeArea( + child: Container( + color: Theme.of(context).extension()!.background, + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + AddTokenText(isDesktop: false, walletName: walletName), + const SizedBox(height: 16), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autofocus: isDesktop, + autocorrect: !isDesktop, + enableSuggestions: !isDesktop, + controller: _searchFieldController, + focusNode: _searchFocusNode, + onChanged: + (value) => setState(() => _searchTerm = value), + style: STextStyles.field(context), + decoration: standardInputDecoration( + "Search", + _searchFocusNode, + context, + desktopMed: isDesktop, + ).copyWith( + prefixIcon: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 16, + ), + child: SvgPicture.asset( + Assets.svg.search, + width: 16, + height: 16, + ), ), - ), - suffixIcon: _searchFieldController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _searchFieldController.text = ""; - _searchTerm = ""; - }); - }, + suffixIcon: + _searchFieldController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _searchFieldController.text = + ""; + _searchTerm = ""; + }); + }, + ), + ], ), - ], - ), - ), - ) - : null, + ), + ) + : null, + ), ), ), - ), - const SizedBox( - height: 10, - ), - Expanded( - child: AddTokenList( - walletId: widget.walletId, - items: filter(_searchTerm, tokenEntities), - addFunction: _addToken, + const SizedBox(height: 10), + Expanded( + child: AddTokenList( + walletId: widget.walletId, + items: filter(_searchTerm, tokenEntities), + addFunction: _addToken, + ), ), - ), - const SizedBox( - height: 16, - ), - PrimaryButton( - label: widget.contractsToMarkSelected != null - ? "Save" - : "Next", - onPressed: onNextPressed, - ), - ], + const SizedBox(height: 16), + PrimaryButton( + label: + widget.contractsToMarkSelected != null + ? "Save" + : "Next", + onPressed: onNextPressed, + ), + ], + ), ), ), ), diff --git a/lib/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart b/lib/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart index 748f5074e..ef4248d0b 100644 --- a/lib/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart +++ b/lib/pages/add_wallet_views/add_wallet_view/add_wallet_view.dart @@ -61,9 +61,7 @@ class _AddWalletViewState extends ConsumerState { String _searchTerm = ""; - final _coinsTestnet = [ - ...AppConfig.coins.where((e) => e.network.isTestNet), - ]; + final _coinsTestnet = [...AppConfig.coins.where((e) => e.network.isTestNet)]; final _coins = [ ...AppConfig.coins.where((e) => e.network == CryptoCurrencyNetwork.main), ]; @@ -98,16 +96,17 @@ class _AddWalletViewState extends ConsumerState { if (isDesktop) { contract = await showDialog( context: context, - builder: (context) => const DesktopDialog( - maxWidth: 580, - maxHeight: 500, - child: AddCustomTokenView(), - ), + builder: + (context) => const DesktopDialog( + maxWidth: 580, + maxHeight: 500, + child: AddCustomTokenView(), + ), ); } else { - contract = await Navigator.of(context).pushNamed( - AddCustomTokenView.routeName, - ); + contract = await Navigator.of( + context, + ).pushNamed(AddCustomTokenView.routeName); } if (contract != null) { @@ -143,7 +142,9 @@ class _AddWalletViewState extends ConsumerState { if (contracts.isEmpty) { contracts.addAll(DefaultTokens.list); - MainDB.instance.putEthContracts(contracts).then( + MainDB.instance + .putEthContracts(contracts) + .then( (value) => ref.read(priceAnd24hChangeNotifierProvider).updatePrice(), ); @@ -184,12 +185,8 @@ class _AddWalletViewState extends ConsumerState { ), body: Column( children: [ - const AddWalletText( - isDesktop: true, - ), - const SizedBox( - height: 16, - ), + const AddWalletText(isDesktop: true), + const SizedBox(height: 16), Expanded( child: SizedBox( width: 480, @@ -219,10 +216,9 @@ class _AddWalletViewState extends ConsumerState { _searchTerm = value; }); }, - style: - STextStyles.desktopTextMedium(context).copyWith( - height: 2, - ), + style: STextStyles.desktopTextMedium( + context, + ).copyWith(height: 2), decoration: standardInputDecoration( "Search", _searchFocusNode, @@ -240,42 +236,44 @@ class _AddWalletViewState extends ConsumerState { Assets.svg.search, width: 24, height: 24, - color: Theme.of(context) - .extension()! - .textFieldDefaultSearchIconLeft, + color: + Theme.of(context) + .extension()! + .textFieldDefaultSearchIconLeft, ), ), - suffixIcon: _searchFieldController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 10), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon( - width: 24, - height: 24, + suffixIcon: + _searchFieldController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only( + right: 10, + ), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon( + width: 24, + height: 24, + ), + onTap: () async { + setState(() { + _searchFieldController + .text = ""; + _searchTerm = ""; + }); + }, ), - onTap: () async { - setState(() { - _searchFieldController.text = - ""; - _searchTerm = ""; - }); - }, - ), - ], + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), Expanded( child: SingleChildScrollView( child: Column( @@ -289,8 +287,10 @@ class _AddWalletViewState extends ConsumerState { if (coinTestnetEntities.isNotEmpty) ExpandingSubListItem( title: "Testnet", - entities: - filter(_searchTerm, coinTestnetEntities), + entities: filter( + _searchTerm, + coinTestnetEntities, + ), initialState: ExpandableState.expanded, animationDurationMultiplier: 0.5, ), @@ -308,27 +308,19 @@ class _AddWalletViewState extends ConsumerState { ), ), ), - const SizedBox( - height: 20, - ), + const SizedBox(height: 20), ], ), ), ), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), const SizedBox( height: 70, width: 480, - child: AddWalletNextButton( - isDesktop: true, - ), - ), - const SizedBox( - height: 32, + child: AddWalletNextButton(isDesktop: true), ), + const SizedBox(height: 32), ], ), ); @@ -344,113 +336,109 @@ class _AddWalletViewState extends ConsumerState { }, ), ), - body: Container( - color: Theme.of(context).extension()!.background, - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const AddWalletText( - isDesktop: false, - ), - const SizedBox( - height: 16, - ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: Semantics( - label: - "Search Text Field. Inputs Text To Search In Wallets.", - excludeSemantics: true, - child: TextField( - autofocus: isDesktop, - autocorrect: !isDesktop, - enableSuggestions: !isDesktop, - controller: _searchFieldController, - focusNode: _searchFocusNode, - onChanged: (value) => - setState(() => _searchTerm = value), - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Search", - _searchFocusNode, - context, - desktopMed: isDesktop, - ).copyWith( - prefixIcon: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 16, - ), - child: SvgPicture.asset( - Assets.svg.search, - width: 16, - height: 16, + body: SafeArea( + child: Container( + color: Theme.of(context).extension()!.background, + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const AddWalletText(isDesktop: false), + const SizedBox(height: 16), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: Semantics( + label: + "Search Text Field. Inputs Text To Search In Wallets.", + excludeSemantics: true, + child: TextField( + autofocus: isDesktop, + autocorrect: !isDesktop, + enableSuggestions: !isDesktop, + controller: _searchFieldController, + focusNode: _searchFocusNode, + onChanged: + (value) => setState(() => _searchTerm = value), + style: STextStyles.field(context), + decoration: standardInputDecoration( + "Search", + _searchFocusNode, + context, + desktopMed: isDesktop, + ).copyWith( + prefixIcon: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 16, + ), + child: SvgPicture.asset( + Assets.svg.search, + width: 16, + height: 16, + ), ), - ), - suffixIcon: _searchFieldController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _searchFieldController.text = ""; - _searchTerm = ""; - }); - }, + suffixIcon: + _searchFieldController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _searchFieldController.text = + ""; + _searchTerm = ""; + }); + }, + ), + ], ), - ], - ), - ), - ) - : null, + ), + ) + : null, + ), ), ), ), - ), - const SizedBox( - height: 10, - ), - Expanded( - child: SingleChildScrollView( - child: Column( - children: [ - ExpandingSubListItem( - title: "Coins", - entities: filter(_searchTerm, coinEntities), - initialState: ExpandableState.expanded, - ), - if (coinTestnetEntities.isNotEmpty) - ExpandingSubListItem( - title: "Testnet", - entities: - filter(_searchTerm, coinTestnetEntities), - initialState: ExpandableState.expanded, - ), - if (tokenEntities.isNotEmpty) + const SizedBox(height: 10), + Expanded( + child: SingleChildScrollView( + child: Column( + children: [ ExpandingSubListItem( - title: "Tokens", - entities: filter(_searchTerm, tokenEntities), + title: "Coins", + entities: filter(_searchTerm, coinEntities), initialState: ExpandableState.expanded, ), - ], + if (coinTestnetEntities.isNotEmpty) + ExpandingSubListItem( + title: "Testnet", + entities: filter( + _searchTerm, + coinTestnetEntities, + ), + initialState: ExpandableState.expanded, + ), + if (tokenEntities.isNotEmpty) + ExpandingSubListItem( + title: "Tokens", + entities: filter(_searchTerm, tokenEntities), + initialState: ExpandableState.expanded, + ), + ], + ), ), ), - ), - const SizedBox( - height: 16, - ), - const AddWalletNextButton( - isDesktop: false, - ), - ], + const SizedBox(height: 16), + const AddWalletNextButton(isDesktop: false), + ], + ), ), ), ), diff --git a/lib/pages/add_wallet_views/frost_ms/new/select_new_frost_import_type_view.dart b/lib/pages/add_wallet_views/frost_ms/new/select_new_frost_import_type_view.dart index d377eff72..e00f679cb 100644 --- a/lib/pages/add_wallet_views/frost_ms/new/select_new_frost_import_type_view.dart +++ b/lib/pages/add_wallet_views/frost_ms/new/select_new_frost_import_type_view.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; + import '../../../../frost_route_generator.dart'; import '../../../../pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart'; import '../../../../themes/stack_colors.dart'; @@ -43,76 +44,77 @@ class _SelectNewFrostImportTypeViewState Widget build(BuildContext context) { return ConditionalParent( condition: Util.isDesktop, - builder: (content) => DesktopScaffold( - appBar: const DesktopAppBar( - leading: AppBarBackButton(), - trailing: ExitToMyStackButton(), - isCompactHeight: false, - ), - body: SizedBox( - width: 480, - child: content, - ), - ), + builder: + (content) => DesktopScaffold( + appBar: const DesktopAppBar( + leading: AppBarBackButton(), + trailing: ExitToMyStackButton(), + isCompactHeight: false, + ), + body: SizedBox(width: 480, child: content), + ), child: ConditionalParent( condition: !Util.isDesktop, - builder: (content) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () { - Navigator.of(context).pop(); - }, - ), - actions: [ - AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - size: 36, - icon: SvgPicture.asset( - Assets.svg.circleQuestion, - width: 20, - height: 20, - colorFilter: ColorFilter.mode( - Theme.of(context) - .extension()! - .topNavIconPrimary, - BlendMode.srcIn, - ), - ), - onPressed: () async { - await showDialog( - context: context, - builder: (_) => const _FrostJoinInfoDialog(), - ); + builder: + (content) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () { + Navigator.of(context).pop(); }, ), - ), - ], - ), - body: Container( - color: Theme.of(context).extension()!.background, - child: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (ctx, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: - BoxConstraints(minHeight: constraints.maxHeight), - child: IntrinsicHeight( - child: content, + actions: [ + AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + size: 36, + icon: SvgPicture.asset( + Assets.svg.circleQuestion, + width: 20, + height: 20, + colorFilter: ColorFilter.mode( + Theme.of( + context, + ).extension()!.topNavIconPrimary, + BlendMode.srcIn, + ), ), + onPressed: () async { + await showDialog( + context: context, + builder: (_) => const _FrostJoinInfoDialog(), + ); + }, ), - ); - }, + ), + ], + ), + body: SafeArea( + child: Container( + color: + Theme.of(context).extension()!.background, + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (ctx, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight(child: content), + ), + ); + }, + ), + ), + ), ), ), ), - ), - ), child: Column( children: [ ..._ImportOption.values.map( @@ -163,9 +165,9 @@ class _SelectNewFrostImportTypeViewState break; } - await Navigator.of(context).pushNamed( - FrostStepScaffold.routeName, - ); + await Navigator.of( + context, + ).pushNamed(FrostStepScaffold.routeName); }, ), ], @@ -232,9 +234,10 @@ class _ImportOptionCardState extends State<_ImportOptionCard> { child: Radio( value: widget.value, groupValue: widget.groupValue, - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, + activeColor: + Theme.of( + context, + ).extension()!.radioButtonIconEnabled, onChanged: (_) => widget.onPressed(), ), ), @@ -257,18 +260,17 @@ class _ImportOptionCardState extends State<_ImportOptionCard> { ), ], ), - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), Row( children: [ Expanded( child: Text( widget.description, style: STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, + color: + Theme.of( + context, + ).extension()!.textSubtitle1, ), ), ), @@ -293,21 +295,14 @@ class _FrostJoinInfoDialog extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - "Join a group", - style: STextStyles.w600_20(context), - ), - const SizedBox( - height: 12, - ), + Text("Join a group", style: STextStyles.w600_20(context)), + const SizedBox(height: 12), Text( "You should select 'Join a new group' if you are creating a brand " "new wallet with other people.", style: STextStyles.w600_16(context), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Text( "You should select 'Join an existing group' if you an existing " "group is being edited and you are being added as a participant.", diff --git a/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart b/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart index 91aa555f6..ec7419d96 100644 --- a/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart +++ b/lib/pages/add_wallet_views/name_your_wallet_view/name_your_wallet_view.dart @@ -110,10 +110,7 @@ class _NameYourWalletViewState extends ConsumerState { coin is ViewOnlyOptionCurrencyInterface ? NewWalletOptionsView.routeName : NewWalletRecoveryPhraseWarningView.routeName, - arguments: Tuple2( - name, - coin, - ), + arguments: Tuple2(name, coin), ), ); break; @@ -122,10 +119,7 @@ class _NameYourWalletViewState extends ConsumerState { unawaited( Navigator.of(context).pushNamed( RestoreOptionsView.routeName, - arguments: Tuple2( - name, - coin, - ), + arguments: Tuple2(name, coin), ), ); break; @@ -145,9 +139,7 @@ class _NameYourWalletViewState extends ConsumerState { .where() .nameProperty() .findAll() - .then( - (values) => namesToExclude.addAll(values), - ); + .then((values) => namesToExclude.addAll(values)); generator = NameGenerator(); addWalletType = widget.addWalletType; coin = widget.coin; @@ -177,10 +169,7 @@ class _NameYourWalletViewState extends ConsumerState { trailing: ExitToMyStackButton(), isCompactHeight: false, ), - body: SizedBox( - width: 480, - child: _content(), - ), + body: SizedBox(width: 480, child: _content()), ); } else { return Background( @@ -192,8 +181,9 @@ class _NameYourWalletViewState extends ConsumerState { onPressed: () { if (textFieldFocusNode.hasFocus) { textFieldFocusNode.unfocus(); - Future.delayed(const Duration(milliseconds: 100)) - .then((value) => Navigator.of(context).pop()); + Future.delayed( + const Duration(milliseconds: 100), + ).then((value) => Navigator.of(context).pop()); } else { if (mounted) { Navigator.of(context).pop(); @@ -202,22 +192,23 @@ class _NameYourWalletViewState extends ConsumerState { }, ), ), - body: Container( - color: Theme.of(context).extension()!.background, - child: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (ctx, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: - BoxConstraints(minHeight: constraints.maxHeight), - child: IntrinsicHeight( - child: _content(), + body: SafeArea( + child: Container( + color: Theme.of(context).extension()!.background, + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (ctx, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight(child: _content()), ), - ), - ); - }, + ); + }, + ), ), ), ), @@ -227,284 +218,251 @@ class _NameYourWalletViewState extends ConsumerState { } Widget _content() => Column( - crossAxisAlignment: - isDesktop ? CrossAxisAlignment.center : CrossAxisAlignment.stretch, - children: [ - if (isDesktop) - const Spacer( - flex: 10, - ), - if (!isDesktop) - const Spacer( - flex: 1, - ), - if (!isDesktop) - CoinImage( - coin: coin, - height: 100, - width: 100, - ), - SizedBox( - height: isDesktop ? 0 : 16, - ), - Text( - "Name your ${coin.prettyName} ${coin is FrostCurrency ? "multisig " : ""}wallet", - textAlign: TextAlign.center, - style: isDesktop + crossAxisAlignment: + isDesktop ? CrossAxisAlignment.center : CrossAxisAlignment.stretch, + children: [ + if (isDesktop) const Spacer(flex: 10), + if (!isDesktop) const Spacer(flex: 1), + if (!isDesktop) CoinImage(coin: coin, height: 100, width: 100), + SizedBox(height: isDesktop ? 0 : 16), + Text( + "Name your ${coin.prettyName} ${coin is FrostCurrency ? "multisig " : ""}wallet", + textAlign: TextAlign.center, + style: + isDesktop ? STextStyles.desktopH2(context) : STextStyles.pageTitleH1(context), - ), - SizedBox( - height: isDesktop ? 16 : 8, - ), - Text( - "Enter a label for your wallet (e.g. ${coin is FrostCurrency ? "Multisig" : "Savings"})", - textAlign: TextAlign.center, - style: isDesktop + ), + SizedBox(height: isDesktop ? 16 : 8), + Text( + "Enter a label for your wallet (e.g. ${coin is FrostCurrency ? "Multisig" : "Savings"})", + textAlign: TextAlign.center, + style: + isDesktop ? STextStyles.desktopSubtitleH2(context) : STextStyles.subtitle(context), - ), - SizedBox( - height: isDesktop ? 40 : 16, - ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - onChanged: (string) { - if (string.isEmpty) { - if (_nextEnabled) { - setState(() { - _nextEnabled = false; - _showDiceIcon = true; - }); - } - } else { - if (!_nextEnabled) { - setState(() { - _nextEnabled = true; - _showDiceIcon = false; - }); - } - } - }, - focusNode: textFieldFocusNode, - controller: textEditingController, - style: isDesktop - ? STextStyles.desktopTextMedium(context).copyWith( - height: 2, - ) + ), + SizedBox(height: isDesktop ? 40 : 16), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, + onChanged: (string) { + if (string.isEmpty) { + if (_nextEnabled) { + setState(() { + _nextEnabled = false; + _showDiceIcon = true; + }); + } + } else { + if (!_nextEnabled) { + setState(() { + _nextEnabled = true; + _showDiceIcon = false; + }); + } + } + }, + focusNode: textFieldFocusNode, + controller: textEditingController, + style: + isDesktop + ? STextStyles.desktopTextMedium(context).copyWith(height: 2) : STextStyles.field(context), - decoration: standardInputDecoration( - "Enter wallet name", - textFieldFocusNode, - context, - ).copyWith( - suffixIcon: Padding( - padding: EdgeInsets.only(right: isDesktop ? 6 : 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - key: const Key("genRandomWalletNameButtonKey"), - child: _showDiceIcon + decoration: standardInputDecoration( + "Enter wallet name", + textFieldFocusNode, + context, + ).copyWith( + suffixIcon: Padding( + padding: EdgeInsets.only(right: isDesktop ? 6 : 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + key: const Key("genRandomWalletNameButtonKey"), + child: + _showDiceIcon ? Semantics( - label: - "Generate Random Wallet Name Button. Generates A Random Name For Wallet.", - excludeSemantics: true, - child: DiceIcon( - width: isDesktop ? 20 : 17, - height: isDesktop ? 20 : 17, - ), - ) + label: + "Generate Random Wallet Name Button. Generates A Random Name For Wallet.", + excludeSemantics: true, + child: DiceIcon( + width: isDesktop ? 20 : 17, + height: isDesktop ? 20 : 17, + ), + ) : Semantics( - label: - "Clear Wallet Name Field Button. Clears the wallet name field.", - excludeSemantics: true, - child: XIcon( - width: isDesktop ? 21 : 18, - height: isDesktop ? 21 : 18, - ), + label: + "Clear Wallet Name Field Button. Clears the wallet name field.", + excludeSemantics: true, + child: XIcon( + width: isDesktop ? 21 : 18, + height: isDesktop ? 21 : 18, ), - onTap: () async { - if (_showDiceIcon) { - textEditingController.text = - await _generateRandomWalletName(); - setState(() { - _nextEnabled = true; - _showDiceIcon = false; - }); - } else { - textEditingController.text = ""; - setState(() { - _nextEnabled = false; - _showDiceIcon = true; - }); - } - }, - ), - ], + ), + onTap: () async { + if (_showDiceIcon) { + textEditingController.text = + await _generateRandomWalletName(); + setState(() { + _nextEnabled = true; + _showDiceIcon = false; + }); + } else { + textEditingController.text = ""; + setState(() { + _nextEnabled = false; + _showDiceIcon = true; + }); + } + }, ), - ), + ], ), ), ), ), - SizedBox( - height: isDesktop ? 16 : 8, - ), - GestureDetector( - onTap: () async { - textEditingController.text = await _generateRandomWalletName(); - setState(() { - _nextEnabled = true; - _showDiceIcon = false; - }); - }, - child: RoundedWhiteContainer( - child: Center( - child: Text( - "Roll the dice to pick a random name.", - style: isDesktop + ), + ), + SizedBox(height: isDesktop ? 16 : 8), + GestureDetector( + onTap: () async { + textEditingController.text = await _generateRandomWalletName(); + setState(() { + _nextEnabled = true; + _showDiceIcon = false; + }); + }, + child: RoundedWhiteContainer( + child: Center( + child: Text( + "Roll the dice to pick a random name.", + style: + isDesktop ? STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, - ) + color: + Theme.of( + context, + ).extension()!.textSubtitle1, + ) : STextStyles.itemSubtitle(context), - ), - ), ), ), - if (!isDesktop) - const Spacer( - flex: 4, - ), - if (isDesktop) - const SizedBox( - height: 32, - ), - if (widget.coin is FrostCurrency) - if (widget.addWalletType == AddWalletType.Restore) - PrimaryButton( - label: "Next", - enabled: _nextEnabled, - onPressed: () async { - final name = textEditingController.text; + ), + ), + if (!isDesktop) const Spacer(flex: 4), + if (isDesktop) const SizedBox(height: 32), + if (widget.coin is FrostCurrency) + if (widget.addWalletType == AddWalletType.Restore) + PrimaryButton( + label: "Next", + enabled: _nextEnabled, + onPressed: () async { + final name = textEditingController.text; - await Navigator.of(context).pushNamed( - RestoreFrostMsWalletView.routeName, - arguments: ( - walletName: name, - frostCurrency: coin, - ), - ); - }, - ), - if (widget.coin is FrostCurrency && - widget.addWalletType == AddWalletType.New) - Column( - children: [ - PrimaryButton( - label: "Create new group", - enabled: _nextEnabled, - onPressed: () async { - final name = textEditingController.text; + await Navigator.of(context).pushNamed( + RestoreFrostMsWalletView.routeName, + arguments: (walletName: name, frostCurrency: coin), + ); + }, + ), + if (widget.coin is FrostCurrency && + widget.addWalletType == AddWalletType.New) + Column( + children: [ + PrimaryButton( + label: "Create new group", + enabled: _nextEnabled, + onPressed: () async { + final name = textEditingController.text; - await Navigator.of(context).pushNamed( - CreateNewFrostMsWalletView.routeName, - arguments: ( - walletName: name, - frostCurrency: coin, - ), - ); - }, - ), - const SizedBox( - height: 12, - ), - SecondaryButton( - label: "Join group", - enabled: _nextEnabled, - onPressed: () async { - final name = textEditingController.text; + await Navigator.of(context).pushNamed( + CreateNewFrostMsWalletView.routeName, + arguments: (walletName: name, frostCurrency: coin), + ); + }, + ), + const SizedBox(height: 12), + SecondaryButton( + label: "Join group", + enabled: _nextEnabled, + onPressed: () async { + final name = textEditingController.text; - await Navigator.of(context).pushNamed( - SelectNewFrostImportTypeView.routeName, - arguments: ( - walletName: name, - frostCurrency: coin, - ), - ); - }, - ), - // SecondaryButton( - // label: "Import multisig config", - // enabled: _nextEnabled, - // onPressed: () async { - // final name = textEditingController.text; - // - // await Navigator.of(context).pushNamed( - // ImportNewFrostMsWalletView.routeName, - // arguments: ( - // walletName: name, - // coin: coin, - // ), - // ); - // }, - // ), - // const SizedBox( - // height: 12, - // ), - // SecondaryButton( - // label: "Import resharer config", - // enabled: _nextEnabled, - // onPressed: () async { - // final name = textEditingController.text; - // - // await Navigator.of(context).pushNamed( - // NewImportResharerConfigView.routeName, - // arguments: ( - // walletName: name, - // coin: coin, - // ), - // ); - // }, - // ), - ], + await Navigator.of(context).pushNamed( + SelectNewFrostImportTypeView.routeName, + arguments: (walletName: name, frostCurrency: coin), + ); + }, ), - if (widget.coin is! FrostCurrency) - ConstrainedBox( - constraints: BoxConstraints( - minWidth: isDesktop ? 480 : 0, - minHeight: isDesktop ? 70 : 0, - ), - child: TextButton( - onPressed: _nextEnabled ? _nextPressed : null, - style: _nextEnabled + // SecondaryButton( + // label: "Import multisig config", + // enabled: _nextEnabled, + // onPressed: () async { + // final name = textEditingController.text; + // + // await Navigator.of(context).pushNamed( + // ImportNewFrostMsWalletView.routeName, + // arguments: ( + // walletName: name, + // coin: coin, + // ), + // ); + // }, + // ), + // const SizedBox( + // height: 12, + // ), + // SecondaryButton( + // label: "Import resharer config", + // enabled: _nextEnabled, + // onPressed: () async { + // final name = textEditingController.text; + // + // await Navigator.of(context).pushNamed( + // NewImportResharerConfigView.routeName, + // arguments: ( + // walletName: name, + // coin: coin, + // ), + // ); + // }, + // ), + ], + ), + if (widget.coin is! FrostCurrency) + ConstrainedBox( + constraints: BoxConstraints( + minWidth: isDesktop ? 480 : 0, + minHeight: isDesktop ? 70 : 0, + ), + child: TextButton( + onPressed: _nextEnabled ? _nextPressed : null, + style: + _nextEnabled ? Theme.of(context) .extension()! .getPrimaryEnabledButtonStyle(context) : Theme.of(context) .extension()! .getPrimaryDisabledButtonStyle(context), - child: Text( - "Next", - style: isDesktop + child: Text( + "Next", + style: + isDesktop ? _nextEnabled ? STextStyles.desktopButtonEnabled(context) : STextStyles.desktopButtonDisabled(context) : STextStyles.button(context), - ), - ), - ), - if (isDesktop) - const Spacer( - flex: 15, ), - ], - ); + ), + ), + if (isDesktop) const Spacer(flex: 15), + ], + ); } diff --git a/lib/pages/address_book_views/address_book_view.dart b/lib/pages/address_book_views/address_book_view.dart index 852803f6f..64af27507 100644 --- a/lib/pages/address_book_views/address_book_view.dart +++ b/lib/pages/address_book_views/address_book_view.dart @@ -15,7 +15,6 @@ import 'package:flutter_svg/svg.dart'; import '../../app_config.dart'; import '../../models/isar/models/blockchain_data/address.dart'; import '../../models/isar/models/contact_entry.dart'; -import '../../providers/db/main_db_provider.dart'; import '../../providers/global/address_book_service_provider.dart'; import '../../providers/providers.dart'; import '../../providers/ui/address_book_providers/address_book_filter_provider.dart'; @@ -38,11 +37,7 @@ import 'subviews/add_address_book_entry_view.dart'; import 'subviews/address_book_filter_view.dart'; class AddressBookView extends ConsumerStatefulWidget { - const AddressBookView({ - super.key, - this.coin, - this.filterTerm, - }); + const AddressBookView({super.key, this.coin, this.filterTerm}); static const String routeName = "/addressBook"; @@ -67,9 +62,7 @@ class _AddressBookViewState extends ConsumerState { if (widget.coin == null) { final coins = [...AppConfig.coins]; - coins.removeWhere( - (e) => e is Firo && e.network.isTestNet, - ); + coins.removeWhere((e) => e is Firo && e.network.isTestNet); final bool showTestNet = ref.read(prefsChangeNotifierProvider).showTestNetCoins; @@ -77,7 +70,9 @@ class _AddressBookViewState extends ConsumerState { if (showTestNet) { ref.read(addressBookFilterProvider).addAll(coins, false); } else { - ref.read(addressBookFilterProvider).addAll( + ref + .read(addressBookFilterProvider) + .addAll( coins.where((e) => e.network != CryptoCurrencyNetwork.test), false, ); @@ -132,8 +127,9 @@ class _AddressBookViewState extends ConsumerState { @override Widget build(BuildContext context) { debugPrint("BUILD: $runtimeType"); - final contacts = - ref.watch(addressBookServiceProvider.select((value) => value.contacts)); + final contacts = ref.watch( + addressBookServiceProvider.select((value) => value.contacts), + ); final isDesktop = Util.isDesktop; return ConditionalParent( @@ -166,21 +162,23 @@ class _AddressBookViewState extends ConsumerState { key: const Key("addressBookFilterViewButton"), size: 36, shadows: const [], - color: Theme.of(context) - .extension()! - .background, + color: + Theme.of( + context, + ).extension()!.background, icon: SvgPicture.asset( Assets.svg.filter, - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, width: 20, height: 20, ), onPressed: () { - Navigator.of(context).pushNamed( - AddressBookFilterView.routeName, - ); + Navigator.of( + context, + ).pushNamed(AddressBookFilterView.routeName); }, ), ), @@ -197,56 +195,60 @@ class _AddressBookViewState extends ConsumerState { key: const Key("addressBookAddNewContactViewButton"), size: 36, shadows: const [], - color: Theme.of(context) - .extension()! - .background, + color: + Theme.of( + context, + ).extension()!.background, icon: SvgPicture.asset( Assets.svg.plus, - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, width: 20, height: 20, ), onPressed: () { - Navigator.of(context).pushNamed( - AddAddressBookEntryView.routeName, - ); + Navigator.of( + context, + ).pushNamed(AddAddressBookEntryView.routeName); }, ), ), ), ], ), - body: LayoutBuilder( - builder: (builderContext, constraints) { - return Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, - ), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: - MediaQuery.of(context).size.height - 271, + body: SafeArea( + child: LayoutBuilder( + builder: (builderContext, constraints) { + return Padding( + padding: const EdgeInsets.only( + left: 12, + top: 12, + right: 12, + ), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: + MediaQuery.of(context).size.height - 271, + ), + child: child, ), - child: child, ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ); @@ -258,66 +260,63 @@ class _AddressBookViewState extends ConsumerState { borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), - child: !isDesktop - ? TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - controller: _searchController, - focusNode: _searchFocusNode, - onChanged: (value) { - setState(() { - _searchTerm = value; - }); - }, - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Search", - _searchFocusNode, - context, - ).copyWith( - prefixIcon: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 16, - ), - child: SvgPicture.asset( - Assets.svg.search, - width: 16, - height: 16, + child: + !isDesktop + ? TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, + controller: _searchController, + focusNode: _searchFocusNode, + onChanged: (value) { + setState(() { + _searchTerm = value; + }); + }, + style: STextStyles.field(context), + decoration: standardInputDecoration( + "Search", + _searchFocusNode, + context, + ).copyWith( + prefixIcon: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 16, + ), + child: SvgPicture.asset( + Assets.svg.search, + width: 16, + height: 16, + ), ), - ), - suffixIcon: _searchController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _searchController.text = ""; - _searchTerm = ""; - }); - }, + suffixIcon: + _searchController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _searchController.text = ""; + _searchTerm = ""; + }); + }, + ), + ], ), - ], - ), - ), - ) - : null, - ), - ) - : null, + ), + ) + : null, + ), + ) + : null, ), if (!isDesktop) const SizedBox(height: 16), - Text( - "Favorites", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 12, - ), + Text("Favorites", style: STextStyles.smallMed12(context)), + const SizedBox(height: 12), if (contacts.isNotEmpty) RoundedWhiteContainer( padding: EdgeInsets.all(!isDesktop ? 0 : 15), @@ -325,15 +324,16 @@ class _AddressBookViewState extends ConsumerState { children: [ ...contacts .where( - (element) => element.addressesSorted - .where( - (e) => ref.watch( - addressBookFilterProvider.select( - (value) => value.coins.contains(e.coin), - ), - ), - ) - .isNotEmpty, + (element) => + element.addressesSorted + .where( + (e) => ref.watch( + addressBookFilterProvider.select( + (value) => value.coins.contains(e.coin), + ), + ), + ) + .isNotEmpty, ) .where( (e) => @@ -361,16 +361,9 @@ class _AddressBookViewState extends ConsumerState { ), ), ), - const SizedBox( - height: 16, - ), - Text( - "All contacts", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 16), + Text("All contacts", style: STextStyles.smallMed12(context)), + const SizedBox(height: 12), if (contacts.isNotEmpty) Column( children: [ @@ -382,15 +375,17 @@ class _AddressBookViewState extends ConsumerState { children: [ ...contacts .where( - (element) => element.addressesSorted - .where( - (e) => ref.watch( - addressBookFilterProvider.select( - (value) => value.coins.contains(e.coin), - ), - ), - ) - .isNotEmpty, + (element) => + element.addressesSorted + .where( + (e) => ref.watch( + addressBookFilterProvider.select( + (value) => + value.coins.contains(e.coin), + ), + ), + ) + .isNotEmpty, ) .where( (e) => ref @@ -399,8 +394,9 @@ class _AddressBookViewState extends ConsumerState { ) .map( (e) => AddressBookCard( - key: - Key("desktopContactCard_${e.customId}_key"), + key: Key( + "desktopContactCard_${e.customId}_key", + ), contactId: e.customId, ), ), diff --git a/lib/pages/address_book_views/subviews/add_address_book_entry_view.dart b/lib/pages/address_book_views/subviews/add_address_book_entry_view.dart index 66b4b1aa9..22ecb4407 100644 --- a/lib/pages/address_book_views/subviews/add_address_book_entry_view.dart +++ b/lib/pages/address_book_views/subviews/add_address_book_entry_view.dart @@ -163,18 +163,20 @@ class _AddAddressBookEntryViewState key: const Key("addAddressBookEntryFavoriteButtonKey"), size: 36, shadows: const [], - color: Theme.of(context) - .extension()! - .background, + color: + Theme.of( + context, + ).extension()!.background, icon: SvgPicture.asset( Assets.svg.star, - color: _isFavorite - ? Theme.of(context) - .extension()! - .favoriteStarActive - : Theme.of(context) - .extension()! - .favoriteStarInactive, + color: + _isFavorite + ? Theme.of( + context, + ).extension()!.favoriteStarActive + : Theme.of(context) + .extension()! + .favoriteStarInactive, width: 20, height: 20, ), @@ -188,7 +190,7 @@ class _AddAddressBookEntryViewState ), ], ), - body: child, + body: SafeArea(child: child), ), ); }, @@ -252,155 +254,160 @@ class _AddAddressBookEntryViewState if (!isDesktop) const SizedBox(height: 4), isDesktop ? Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - SizedBox( - height: 56, - width: 56, - child: MouseRegion( - cursor: SystemMouseCursors.click, - child: GestureDetector( - onTap: () { - if (_selectedEmoji != null) { - setState(() { - _selectedEmoji = null; - }); - return; - } + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox( + height: 56, + width: 56, + child: MouseRegion( + cursor: SystemMouseCursors.click, + child: GestureDetector( + onTap: () { + if (_selectedEmoji != null) { + setState(() { + _selectedEmoji = null; + }); + return; + } - showDialog( - context: context, - builder: (context) { - return const DesktopDialog( - maxHeight: 700, - maxWidth: 600, - child: Padding( - padding: EdgeInsets.only( - left: 32, - right: 20, - top: 32, - bottom: 32, - ), - child: EmojiSelectSheet(), + showDialog( + context: context, + builder: (context) { + return const DesktopDialog( + maxHeight: 700, + maxWidth: 600, + child: Padding( + padding: EdgeInsets.only( + left: 32, + right: 20, + top: 32, + bottom: 32, ), - ); - }, - ).then((value) { - if (value is Emoji) { - setState(() { - _selectedEmoji = value; - }); - } - }); - }, - child: Stack( - children: [ - Container( - height: 56, - width: 56, - decoration: BoxDecoration( - borderRadius: - BorderRadius.circular(100), - color: Theme.of(context) - .extension()! - .textFieldActiveBG, + child: EmojiSelectSheet(), ), - child: Center( - child: _selectedEmoji == null - ? SvgPicture.asset( + ); + }, + ).then((value) { + if (value is Emoji) { + setState(() { + _selectedEmoji = value; + }); + } + }); + }, + child: Stack( + children: [ + Container( + height: 56, + width: 56, + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(100), + color: + Theme.of(context) + .extension()! + .textFieldActiveBG, + ), + child: Center( + child: + _selectedEmoji == null + ? SvgPicture.asset( Assets.svg.user, height: 30, width: 30, ) - : Text( + : Text( _selectedEmoji!.char, - style: STextStyles - .pageTitleH1( - context, - ), + style: + STextStyles.pageTitleH1( + context, + ), ), - ), ), - Align( - alignment: Alignment.bottomRight, - child: Container( - height: 14, - width: 14, - decoration: BoxDecoration( - borderRadius: - BorderRadius.circular( - 14, - ), - color: Theme.of(context) - .extension()! - .accentColorDark, - ), - child: Center( - child: _selectedEmoji == null - ? SvgPicture.asset( + ), + Align( + alignment: Alignment.bottomRight, + child: Container( + height: 14, + width: 14, + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(14), + color: + Theme.of(context) + .extension< + StackColors + >()! + .accentColorDark, + ), + child: Center( + child: + _selectedEmoji == null + ? SvgPicture.asset( Assets.svg.plus, - color: Theme.of( - context, - ) - .extension< - StackColors>()! - .textWhite, + color: + Theme.of(context) + .extension< + StackColors + >()! + .textWhite, width: 12, height: 12, ) - : SvgPicture.asset( + : SvgPicture.asset( Assets.svg.thickX, - color: Theme.of( - context, - ) - .extension< - StackColors>()! - .textWhite, + color: + Theme.of(context) + .extension< + StackColors + >()! + .textWhite, width: 8, height: 8, ), - ), ), ), - ], - ), + ), + ], ), ), ), - const SizedBox(width: 8), - SizedBox( - width: isDesktop ? 450 : null, - child: ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autocorrect: - Util.isDesktop ? false : true, - enableSuggestions: - Util.isDesktop ? false : true, - controller: nameController, - focusNode: nameFocusNode, - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Enter contact name", - nameFocusNode, + ), + const SizedBox(width: 8), + SizedBox( + width: isDesktop ? 450 : null, + child: ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autocorrect: + Util.isDesktop ? false : true, + enableSuggestions: + Util.isDesktop ? false : true, + controller: nameController, + focusNode: nameFocusNode, + style: STextStyles.field(context), + decoration: standardInputDecoration( + "Enter contact name", + nameFocusNode, + context, + ).copyWith( + labelStyle: STextStyles.fieldLabel( context, - ).copyWith( - labelStyle: - STextStyles.fieldLabel(context), - suffixIcon: ref - .read( - contactNameIsNotEmptyStateProvider - .state, - ) - .state - ? Padding( + ), + suffixIcon: + ref + .read( + contactNameIsNotEmptyStateProvider + .state, + ) + .state + ? Padding( padding: const EdgeInsets.only( - right: 0, - ), + right: 0, + ), child: UnconstrainedBox( child: Row( children: [ @@ -417,143 +424,153 @@ class _AddAddressBookEntryViewState ), ), ) - : null, - ), - onChanged: (newValue) { - ref - .read( - contactNameIsNotEmptyStateProvider - .state, - ) - .state = newValue.isNotEmpty; - }, + : null, ), + onChanged: (newValue) { + ref + .read( + contactNameIsNotEmptyStateProvider + .state, + ) + .state = newValue.isNotEmpty; + }, ), ), - ], - ) + ), + ], + ) : Column( - children: [ - GestureDetector( - onTap: () { - if (_selectedEmoji != null) { + children: [ + GestureDetector( + onTap: () { + if (_selectedEmoji != null) { + setState(() { + _selectedEmoji = null; + }); + return; + } + + showModalBottomSheet( + backgroundColor: Colors.transparent, + context: context, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(20), + ), + ), + builder: (_) => const EmojiSelectSheet(), + ).then((value) { + if (value is Emoji) { setState(() { - _selectedEmoji = null; + _selectedEmoji = value; }); - return; } - - showModalBottomSheet( - backgroundColor: Colors.transparent, - context: context, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical( - top: Radius.circular(20), - ), - ), - builder: (_) => - const EmojiSelectSheet(), - ).then((value) { - if (value is Emoji) { - setState(() { - _selectedEmoji = value; - }); - } - }); - }, - child: SizedBox( - height: 48, - width: 48, - child: Stack( - children: [ - Container( - height: 48, - width: 48, - decoration: BoxDecoration( - borderRadius: - BorderRadius.circular(24), - color: Theme.of(context) - .extension()! - .textFieldActiveBG, + }); + }, + child: SizedBox( + height: 48, + width: 48, + child: Stack( + children: [ + Container( + height: 48, + width: 48, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular( + 24, ), - child: Center( - child: _selectedEmoji == null - ? SvgPicture.asset( + color: + Theme.of(context) + .extension()! + .textFieldActiveBG, + ), + child: Center( + child: + _selectedEmoji == null + ? SvgPicture.asset( Assets.svg.user, height: 24, width: 24, ) - : Text( + : Text( _selectedEmoji!.char, - style: STextStyles - .pageTitleH1(context), + style: + STextStyles.pageTitleH1( + context, + ), ), - ), ), - Align( - alignment: Alignment.bottomRight, - child: Container( - height: 14, - width: 14, - decoration: BoxDecoration( - borderRadius: - BorderRadius.circular(14), - color: Theme.of(context) - .extension()! - .accentColorDark, - ), - child: Center( - child: _selectedEmoji == null - ? SvgPicture.asset( + ), + Align( + alignment: Alignment.bottomRight, + child: Container( + height: 14, + width: 14, + decoration: BoxDecoration( + borderRadius: + BorderRadius.circular(14), + color: + Theme.of(context) + .extension()! + .accentColorDark, + ), + child: Center( + child: + _selectedEmoji == null + ? SvgPicture.asset( Assets.svg.plus, - color: Theme.of(context) - .extension< - StackColors>()! - .textWhite, + color: + Theme.of(context) + .extension< + StackColors + >()! + .textWhite, width: 12, height: 12, ) - : SvgPicture.asset( + : SvgPicture.asset( Assets.svg.thickX, - color: Theme.of(context) - .extension< - StackColors>()! - .textWhite, + color: + Theme.of(context) + .extension< + StackColors + >()! + .textWhite, width: 8, height: 8, ), - ), ), ), - ], - ), + ), + ], ), ), - const SizedBox(height: 8), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autocorrect: - Util.isDesktop ? false : true, - enableSuggestions: - Util.isDesktop ? false : true, - controller: nameController, - focusNode: nameFocusNode, - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Enter contact name", - nameFocusNode, - context, - ).copyWith( - suffixIcon: ref - .read( - contactNameIsNotEmptyStateProvider - .state, - ) - .state - ? Padding( + ), + const SizedBox(height: 8), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: + Util.isDesktop ? false : true, + controller: nameController, + focusNode: nameFocusNode, + style: STextStyles.field(context), + decoration: standardInputDecoration( + "Enter contact name", + nameFocusNode, + context, + ).copyWith( + suffixIcon: + ref + .read( + contactNameIsNotEmptyStateProvider + .state, + ) + .state + ? Padding( padding: const EdgeInsets.only( right: 0, ), @@ -573,34 +590,29 @@ class _AddAddressBookEntryViewState ), ), ) - : null, - ), - onChanged: (newValue) { - ref - .read( - contactNameIsNotEmptyStateProvider - .state, - ) - .state = newValue.isNotEmpty; - }, + : null, ), + onChanged: (newValue) { + ref + .read( + contactNameIsNotEmptyStateProvider + .state, + ) + .state = newValue.isNotEmpty; + }, ), - ], - ), + ), + ], + ), const SizedBox(height: 8), - if (forms.length <= 1) - const SizedBox( - height: 8, - ), + if (forms.length <= 1) const SizedBox(height: 8), if (forms.length <= 1) forms[0], if (forms.length > 1) for (int i = 0; i < forms.length; i++) Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -617,15 +629,11 @@ class _AddAddressBookEntryViewState ), ], ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), forms[i], ], ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), CustomTextButton( onTap: () { _addForm(); @@ -644,9 +652,7 @@ class _AddAddressBookEntryViewState // style: STextStyles.largeMedium14(context), // ), // ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), const Spacer(), Row( children: [ @@ -668,18 +674,17 @@ class _AddAddressBookEntryViewState }, ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: Builder( builder: (context) { - final bool nameExists = ref - .watch( - contactNameIsNotEmptyStateProvider - .state, - ) - .state; + final bool nameExists = + ref + .watch( + contactNameIsNotEmptyStateProvider + .state, + ) + .state; final bool validForms = ref.watch( validContactStateProvider( @@ -697,55 +702,62 @@ class _AddAddressBookEntryViewState buttonHeight: isDesktop ? ButtonHeight.m : null, enabled: shouldEnableSave, - onPressed: shouldEnableSave - ? () async { - if (FocusScope.of(context) - .hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration( - milliseconds: 75, - ), - ); - } - final List - entries = []; - for (int i = 0; + onPressed: + shouldEnableSave + ? () async { + if (FocusScope.of( + context, + ).hasFocus) { + FocusScope.of( + context, + ).unfocus(); + await Future.delayed( + const Duration( + milliseconds: 75, + ), + ); + } + final List + entries = []; + for ( + int i = 0; i < forms.length; - i++) { - entries.add( - ref - .read( - addressEntryDataProvider( - forms[i].id, - ), - ) - .buildAddressEntry(), - ); - } - final ContactEntry contact = - ContactEntry( - emojiChar: _selectedEmoji?.char, - name: nameController.text, - addresses: entries, - isFavorite: _isFavorite, - customId: const Uuid().v1(), - ); + i++ + ) { + entries.add( + ref + .read( + addressEntryDataProvider( + forms[i].id, + ), + ) + .buildAddressEntry(), + ); + } + final ContactEntry contact = + ContactEntry( + emojiChar: + _selectedEmoji?.char, + name: nameController.text, + addresses: entries, + isFavorite: _isFavorite, + customId: const Uuid().v1(), + ); - if (await ref - .read( - addressBookServiceProvider, - ) - .addContact(contact)) { - if (mounted) { - Navigator.of(context).pop(); + if (await ref + .read( + addressBookServiceProvider, + ) + .addContact(contact)) { + if (mounted) { + Navigator.of(context).pop(); + } + // TODO show success notification + } else { + // TODO show error notification } - // TODO show success notification - } else { - // TODO show error notification } - } - : null, + : null, ); }, ), diff --git a/lib/pages/address_book_views/subviews/add_new_contact_address_view.dart b/lib/pages/address_book_views/subviews/add_new_contact_address_view.dart index fc59eca68..2954c4d3f 100644 --- a/lib/pages/address_book_views/subviews/add_new_contact_address_view.dart +++ b/lib/pages/address_book_views/subviews/add_new_contact_address_view.dart @@ -68,61 +68,67 @@ class _AddNewContactAddressViewState @override Widget build(BuildContext context) { final contact = ref.watch( - addressBookServiceProvider - .select((value) => value.getContactById(contactId)), + addressBookServiceProvider.select( + (value) => value.getContactById(contactId), + ), ); final isDesktop = Util.isDesktop; return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed(const Duration(milliseconds: 75)); - } - if (mounted) { - Navigator.of(context).pop(); - } - }, - ), - title: Text( - "Add new address", - style: STextStyles.navBarTitle(context), - ), - ), - body: LayoutBuilder( - builder: (context, constraints) { - return Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 75), + ); + } + if (mounted) { + Navigator.of(context).pop(); + } + }, ), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: child, + title: Text( + "Add new address", + style: STextStyles.navBarTitle(context), + ), + ), + body: SafeArea( + child: LayoutBuilder( + builder: (context, constraints) { + return Padding( + padding: const EdgeInsets.only( + left: 12, + top: 12, + right: 12, ), - ), - ), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: child, + ), + ), + ), + ), + ); + }, ), - ); - }, + ), + ), ), - ), - ), child: Column( children: [ Row( @@ -132,31 +138,28 @@ class _AddNewContactAddressViewState width: 48, decoration: BoxDecoration( borderRadius: BorderRadius.circular(24), - color: Theme.of(context) - .extension()! - .textFieldActiveBG, + color: + Theme.of( + context, + ).extension()!.textFieldActiveBG, ), child: Center( - child: contact.emojiChar == null - ? SvgPicture.asset( - Assets.svg.user, - height: 24, - width: 24, - ) - : Text( - contact.emojiChar!, - style: STextStyles.pageTitleH1(context), - ), + child: + contact.emojiChar == null + ? SvgPicture.asset( + Assets.svg.user, + height: 24, + width: 24, + ) + : Text( + contact.emojiChar!, + style: STextStyles.pageTitleH1(context), + ), ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), if (isDesktop) - Text( - contact.name, - style: STextStyles.pageTitleH2(context), - ), + Text(contact.name, style: STextStyles.pageTitleH2(context)), if (!isDesktop) Expanded( child: FittedBox( @@ -169,17 +172,13 @@ class _AddNewContactAddressViewState ), ], ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), NewContactAddressEntryForm( id: 0, barcodeScanner: barcodeScanner, clipboard: clipboard, ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), const Spacer(), Row( children: [ @@ -200,9 +199,7 @@ class _AddNewContactAddressViewState }, ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: PrimaryButton( label: "Save", @@ -222,8 +219,9 @@ class _AddNewContactAddressViewState ref.read(addressEntryDataProvider(0)).buildAddressEntry(), ); - final ContactEntry editedContact = - contact.copyWith(addresses: entries); + final ContactEntry editedContact = contact.copyWith( + addresses: entries, + ); if (await ref .read(addressBookServiceProvider) diff --git a/lib/pages/address_book_views/subviews/address_book_filter_view.dart b/lib/pages/address_book_views/subviews/address_book_filter_view.dart index 9feaa0a37..47d14c8bb 100644 --- a/lib/pages/address_book_views/subviews/address_book_filter_view.dart +++ b/lib/pages/address_book_views/subviews/address_book_filter_view.dart @@ -42,9 +42,7 @@ class _AddressBookFilterViewState extends ConsumerState { @override void initState() { final coins = [...AppConfig.coins]; - coins.removeWhere( - (e) => e is Firo && e.network.isTestNet, - ); + coins.removeWhere((e) => e is Firo && e.network.isTestNet); final showTestNet = ref.read(prefsChangeNotifierProvider).showTestNetCoins; @@ -81,45 +79,43 @@ class _AddressBookFilterViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(12), - child: LayoutBuilder( - builder: (builderContext, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( - child: Text( - "Only selected cryptocurrency addresses will be displayed.", - style: STextStyles.itemSubtitle(context), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(12), + child: LayoutBuilder( + builder: (builderContext, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedWhiteContainer( + child: Text( + "Only selected cryptocurrency addresses will be displayed.", + style: STextStyles.itemSubtitle(context), + ), ), - ), - const SizedBox( - height: 12, - ), - Text( - "Select cryptocurrency", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 12, - ), - child, - ], + const SizedBox(height: 12), + Text( + "Select cryptocurrency", + style: STextStyles.smallMed12(context), + ), + const SizedBox(height: 12), + child, + ], + ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), @@ -157,8 +153,9 @@ class _AddressBookFilterViewState extends ConsumerState { child: Column( children: [ Padding( - padding: - const EdgeInsets.symmetric(horizontal: 32), + padding: const EdgeInsets.symmetric( + horizontal: 32, + ), child: child, ), ], @@ -170,8 +167,10 @@ class _AddressBookFilterViewState extends ConsumerState { ), ), Padding( - padding: - const EdgeInsets.symmetric(horizontal: 32, vertical: 32), + padding: const EdgeInsets.symmetric( + horizontal: 32, + vertical: 32, + ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -234,8 +233,9 @@ class _AddressBookFilterViewState extends ConsumerState { child: Checkbox( value: ref .watch( - addressBookFilterProvider - .select((value) => value.coins), + addressBookFilterProvider.select( + (value) => value.coins, + ), ) .contains(coin), onChanged: (value) { @@ -254,9 +254,7 @@ class _AddressBookFilterViewState extends ConsumerState { }, ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -264,9 +262,7 @@ class _AddressBookFilterViewState extends ConsumerState { coin.prettyName, style: STextStyles.largeMedium14(context), ), - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), Text( coin.ticker, style: STextStyles.itemSubtitle(context), diff --git a/lib/pages/address_book_views/subviews/contact_details_view.dart b/lib/pages/address_book_views/subviews/contact_details_view.dart index b343c3092..0ee0e6b93 100644 --- a/lib/pages/address_book_views/subviews/contact_details_view.dart +++ b/lib/pages/address_book_views/subviews/contact_details_view.dart @@ -62,24 +62,26 @@ class _ContactDetailsViewState extends ConsumerState { List> _cachedTransactions = []; Future>> - _filteredTransactionsByContact() async { - final contact = - ref.read(addressBookServiceProvider).getContactById(_contactId); + _filteredTransactionsByContact() async { + final contact = ref + .read(addressBookServiceProvider) + .getContactById(_contactId); // TODO: optimise - final transactions = await ref - .read(mainDBProvider) - .isar - .transactions - .where() - .filter() - .anyOf( - contact.addresses.map((e) => e.address), - (q, String e) => q.address((q) => q.valueEqualTo(e)), - ) - .sortByTimestampDesc() - .findAll(); + final transactions = + await ref + .read(mainDBProvider) + .isar + .transactions + .where() + .filter() + .anyOf( + contact.addresses.map((e) => e.address), + (q, String e) => q.address((q) => q.valueEqualTo(e)), + ) + .sortByTimestampDesc() + .findAll(); final List> result = []; @@ -111,8 +113,9 @@ class _ContactDetailsViewState extends ConsumerState { debugPrint("BUILD: $runtimeType"); final _contact = ref.watch( - addressBookServiceProvider - .select((value) => value.getContactById(_contactId)), + addressBookServiceProvider.select( + (value) => value.getContactById(_contactId), + ), ); return Background( @@ -130,11 +133,7 @@ class _ContactDetailsViewState extends ConsumerState { ), actions: [ Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 10, - ), + padding: const EdgeInsets.only(top: 10, bottom: 10, right: 10), child: AspectRatio( aspectRatio: 1, child: AppBarIconButton( @@ -144,20 +143,23 @@ class _ContactDetailsViewState extends ConsumerState { color: Theme.of(context).extension()!.background, icon: SvgPicture.asset( Assets.svg.star, - color: _contact.isFavorite - ? Theme.of(context) - .extension()! - .favoriteStarActive - : Theme.of(context) - .extension()! - .favoriteStarInactive, + color: + _contact.isFavorite + ? Theme.of( + context, + ).extension()!.favoriteStarActive + : Theme.of( + context, + ).extension()!.favoriteStarInactive, width: 20, height: 20, ), onPressed: () { final bool isFavorite = _contact.isFavorite; - ref.read(addressBookServiceProvider).editContact( + ref + .read(addressBookServiceProvider) + .editContact( _contact.copyWith(isFavorite: !isFavorite), ); }, @@ -165,11 +167,7 @@ class _ContactDetailsViewState extends ConsumerState { ), ), Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 10, - ), + padding: const EdgeInsets.only(top: 10, bottom: 10, right: 10), child: AspectRatio( aspectRatio: 1, child: AppBarIconButton( @@ -179,9 +177,10 @@ class _ContactDetailsViewState extends ConsumerState { color: Theme.of(context).extension()!.background, icon: SvgPicture.asset( Assets.svg.trash, - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, width: 20, height: 20, ), @@ -190,43 +189,44 @@ class _ContactDetailsViewState extends ConsumerState { context: context, useSafeArea: true, barrierDismissible: true, - builder: (_) => StackDialog( - title: "Delete ${_contact.name}?", - message: "Contact will be deleted permanently!", - leftButton: TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - child: Text( - "Cancel", - style: STextStyles.itemSubtitle12(context), - ), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - child: Text( - "Delete", - style: STextStyles.button(context), + builder: + (_) => StackDialog( + title: "Delete ${_contact.name}?", + message: "Contact will be deleted permanently!", + leftButton: TextButton( + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle(context), + child: Text( + "Cancel", + style: STextStyles.itemSubtitle12(context), + ), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + rightButton: TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + child: Text( + "Delete", + style: STextStyles.button(context), + ), + onPressed: () { + ref + .read(addressBookServiceProvider) + .removeContact(_contact.customId); + Navigator.of(context).pop(); + Navigator.of(context).pop(); + showFloatingFlushBar( + type: FlushBarType.success, + message: "${_contact.name} deleted", + context: context, + ); + }, + ), ), - onPressed: () { - ref - .read(addressBookServiceProvider) - .removeContact(_contact.customId); - Navigator.of(context).pop(); - Navigator.of(context).pop(); - showFloatingFlushBar( - type: FlushBarType.success, - message: "${_contact.name} deleted", - context: context, - ); - }, - ), - ), ); }, ), @@ -234,308 +234,292 @@ class _ContactDetailsViewState extends ConsumerState { ), ], ), - body: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, - ), - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox( - height: 12, - ), - Row( - children: [ - Container( - height: 48, - width: 48, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(24), - color: Theme.of(context) - .extension()! - .textFieldActiveBG, - ), - child: Center( - child: _contact.emojiChar == null - ? SvgPicture.asset( - Assets.svg.user, - height: 24, - width: 24, - ) - : Text( - _contact.emojiChar!, - style: STextStyles.pageTitleH1(context), - ), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 12), + Row( + children: [ + Container( + height: 48, + width: 48, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(24), + color: + Theme.of( + context, + ).extension()!.textFieldActiveBG, + ), + child: Center( + child: + _contact.emojiChar == null + ? SvgPicture.asset( + Assets.svg.user, + height: 24, + width: 24, + ) + : Text( + _contact.emojiChar!, + style: STextStyles.pageTitleH1(context), + ), + ), ), - ), - const SizedBox( - width: 16, - ), - FittedBox( - fit: BoxFit.scaleDown, - child: Text( - _contact.name, - textAlign: TextAlign.left, - style: STextStyles.pageTitleH2(context), + const SizedBox(width: 16), + FittedBox( + fit: BoxFit.scaleDown, + child: Text( + _contact.name, + textAlign: TextAlign.left, + style: STextStyles.pageTitleH2(context), + ), ), - ), - const Spacer(), - TextButton( - onPressed: () { - Navigator.of(context).pushNamed( - EditContactNameEmojiView.routeName, - arguments: _contact.customId, - ); - }, - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context)! - .copyWith( - minimumSize: MaterialStateProperty.all( - const Size(46, 32), + const Spacer(), + TextButton( + onPressed: () { + Navigator.of(context).pushNamed( + EditContactNameEmojiView.routeName, + arguments: _contact.customId, + ); + }, + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle(context)! + .copyWith( + minimumSize: MaterialStateProperty.all( + const Size(46, 32), + ), ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12), + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.pencil, + width: 10, + height: 10, + color: + Theme.of(context) + .extension()! + .accentColorDark, + ), + const SizedBox(width: 4), + Text( + "Edit", + style: STextStyles.buttonSmall(context), + ), + ], ), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 12), - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.pencil, - width: 10, - height: 10, - color: Theme.of(context) - .extension()! - .accentColorDark, - ), - const SizedBox( - width: 4, - ), - Text( - "Edit", - style: STextStyles.buttonSmall(context), - ), - ], ), ), - ), - ], - ), - const SizedBox( - height: 24, - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Addresses", - style: STextStyles.itemSubtitle(context), - ), - CustomTextButton( - text: "Add new", - onTap: () { - Navigator.of(context).pushNamed( - AddNewContactAddressView.routeName, - arguments: _contact.customId, - ); - }, - ), - ], - ), - const SizedBox( - height: 12, - ), - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: Column( + ], + ), + const SizedBox(height: 24), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - ..._contact.addressesSorted.map( - (e) => Padding( - padding: const EdgeInsets.all(12), - child: Row( - children: [ - SvgPicture.file( - File( - ref.watch(coinIconProvider(e.coin)), + Text( + "Addresses", + style: STextStyles.itemSubtitle(context), + ), + CustomTextButton( + text: "Add new", + onTap: () { + Navigator.of(context).pushNamed( + AddNewContactAddressView.routeName, + arguments: _contact.customId, + ); + }, + ), + ], + ), + const SizedBox(height: 12), + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: Column( + children: [ + ..._contact.addressesSorted.map( + (e) => Padding( + padding: const EdgeInsets.all(12), + child: Row( + children: [ + SvgPicture.file( + File(ref.watch(coinIconProvider(e.coin))), + height: 24, ), - height: 24, - ), - const SizedBox( - width: 12, - ), - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "${e.label} (${e.coin.ticker})", - style: - STextStyles.itemSubtitle12(context), - ), - const SizedBox( - height: 2, - ), - FittedBox( - fit: BoxFit.scaleDown, - child: Text( - e.address, - style: - STextStyles.itemSubtitle(context) - .copyWith( - fontSize: 8, + const SizedBox(width: 12), + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "${e.label} (${e.coin.ticker})", + style: STextStyles.itemSubtitle12( + context, ), ), - ), - ], + const SizedBox(height: 2), + FittedBox( + fit: BoxFit.scaleDown, + child: Text( + e.address, + style: STextStyles.itemSubtitle( + context, + ).copyWith(fontSize: 8), + ), + ), + ], + ), ), - ), - GestureDetector( - onTap: () { - ref - .read(addressEntryDataProvider(0)) - .address = e.address; - ref - .read(addressEntryDataProvider(0)) - .addressLabel = e.label; - ref.read(addressEntryDataProvider(0)).coin = - e.coin; + GestureDetector( + onTap: () { + ref + .read(addressEntryDataProvider(0)) + .address = e.address; + ref + .read(addressEntryDataProvider(0)) + .addressLabel = e.label; + ref + .read(addressEntryDataProvider(0)) + .coin = e.coin; - Navigator.of(context).pushNamed( - EditContactAddressView.routeName, - arguments: Tuple2(_contact.customId, e), - ); - }, - child: RoundedContainer( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - padding: const EdgeInsets.all(6), - child: SvgPicture.asset( - Assets.svg.pencil, - width: 14, - height: 14, - color: Theme.of(context) - .extension()! - .accentColorDark, + Navigator.of(context).pushNamed( + EditContactAddressView.routeName, + arguments: Tuple2(_contact.customId, e), + ); + }, + child: RoundedContainer( + color: + Theme.of(context) + .extension()! + .textFieldDefaultBG, + padding: const EdgeInsets.all(6), + child: SvgPicture.asset( + Assets.svg.pencil, + width: 14, + height: 14, + color: + Theme.of(context) + .extension()! + .accentColorDark, + ), ), ), - ), - const SizedBox( - width: 4, - ), - GestureDetector( - onTap: () { - clipboard.setData( - ClipboardData(text: e.address), - ); - showFloatingFlushBar( - type: FlushBarType.info, - message: "Copied to clipboard", - iconAsset: Assets.svg.copy, - context: context, - ); - }, - child: RoundedContainer( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - padding: const EdgeInsets.all(6), - child: SvgPicture.asset( - Assets.svg.copy, - width: 16, - height: 16, - color: Theme.of(context) - .extension()! - .accentColorDark, + const SizedBox(width: 4), + GestureDetector( + onTap: () { + clipboard.setData( + ClipboardData(text: e.address), + ); + showFloatingFlushBar( + type: FlushBarType.info, + message: "Copied to clipboard", + iconAsset: Assets.svg.copy, + context: context, + ); + }, + child: RoundedContainer( + color: + Theme.of(context) + .extension()! + .textFieldDefaultBG, + padding: const EdgeInsets.all(6), + child: SvgPicture.asset( + Assets.svg.copy, + width: 16, + height: 16, + color: + Theme.of(context) + .extension()! + .accentColorDark, + ), ), ), - ), - ], + ], + ), ), ), - ), - ], + ], + ), ), - ), - const SizedBox( - height: 24, - ), - Text( - "Transaction history", - style: STextStyles.itemSubtitle(context), - ), - const SizedBox( - height: 12, - ), - FutureBuilder( - future: _filteredTransactionsByContact(), - builder: ( - _, - AsyncSnapshot>> snapshot, - ) { - if (snapshot.connectionState == ConnectionState.done && - snapshot.hasData) { - _cachedTransactions = snapshot.data!; + const SizedBox(height: 24), + Text( + "Transaction history", + style: STextStyles.itemSubtitle(context), + ), + const SizedBox(height: 12), + FutureBuilder( + future: _filteredTransactionsByContact(), + builder: ( + _, + AsyncSnapshot>> + snapshot, + ) { + if (snapshot.connectionState == ConnectionState.done && + snapshot.hasData) { + _cachedTransactions = snapshot.data!; - if (_cachedTransactions.isNotEmpty) { - return RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: Column( - children: [ - ..._cachedTransactions.map( - (e) => TransactionCard( - key: Key( - "contactDetailsTransaction_${e.item1}_${e.item2.txid}_cardKey", + if (_cachedTransactions.isNotEmpty) { + return RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: Column( + children: [ + ..._cachedTransactions.map( + (e) => TransactionCard( + key: Key( + "contactDetailsTransaction_${e.item1}_${e.item2.txid}_cardKey", + ), + transaction: e.item2, + walletId: e.item1, ), - transaction: e.item2, - walletId: e.item1, ), + ], + ), + ); + } else { + return RoundedWhiteContainer( + child: Center( + child: Text( + "No transactions found", + style: STextStyles.itemSubtitle(context), ), - ], - ), - ); - } else { - return RoundedWhiteContainer( - child: Center( - child: Text( - "No transactions found", - style: STextStyles.itemSubtitle(context), ), - ), - ); - } - } else { - // TODO: proper loading animation - if (_cachedTransactions.isEmpty) { - return const LoadingIndicator(); + ); + } } else { - return RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: Column( - children: [ - ..._cachedTransactions.map( - (e) => TransactionCard( - key: Key( - "contactDetailsTransaction_${e.item1}_${e.item2.txid}_cardKey", + // TODO: proper loading animation + if (_cachedTransactions.isEmpty) { + return const LoadingIndicator(); + } else { + return RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: Column( + children: [ + ..._cachedTransactions.map( + (e) => TransactionCard( + key: Key( + "contactDetailsTransaction_${e.item1}_${e.item2.txid}_cardKey", + ), + transaction: e.item2, + walletId: e.item1, ), - transaction: e.item2, - walletId: e.item1, ), - ), - ], - ), - ); + ], + ), + ); + } } - } - }, - ), - const SizedBox( - height: 16, - ), - ], + }, + ), + const SizedBox(height: 16), + ], + ), ), ), ), diff --git a/lib/pages/address_book_views/subviews/edit_contact_address_view.dart b/lib/pages/address_book_views/subviews/edit_contact_address_view.dart index 1d5ebd21c..774fac6be 100644 --- a/lib/pages/address_book_views/subviews/edit_contact_address_view.dart +++ b/lib/pages/address_book_views/subviews/edit_contact_address_view.dart @@ -62,9 +62,7 @@ class _EditContactAddressViewState Future save(ContactEntry contact) async { if (FocusScope.of(context).hasFocus) { FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 75), - ); + await Future.delayed(const Duration(milliseconds: 75)); } final List entries = contact.addresses.toList(); @@ -108,61 +106,67 @@ class _EditContactAddressViewState @override Widget build(BuildContext context) { final contact = ref.watch( - addressBookServiceProvider - .select((value) => value.getContactById(contactId)), + addressBookServiceProvider.select( + (value) => value.getContactById(contactId), + ), ); final bool isDesktop = Util.isDesktop; return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed(const Duration(milliseconds: 75)); - } - if (mounted) { - Navigator.of(context).pop(); - } - }, - ), - title: Text( - "Edit address", - style: STextStyles.navBarTitle(context), - ), - ), - body: LayoutBuilder( - builder: (context, constraints) { - return Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 75), + ); + } + if (mounted) { + Navigator.of(context).pop(); + } + }, ), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: child, + title: Text( + "Edit address", + style: STextStyles.navBarTitle(context), + ), + ), + body: SafeArea( + child: LayoutBuilder( + builder: (context, constraints) { + return Padding( + padding: const EdgeInsets.only( + left: 12, + top: 12, + right: 12, ), - ), - ), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: child, + ), + ), + ), + ), + ); + }, ), - ); - }, + ), + ), ), - ), - ), child: Column( children: [ Row( @@ -172,31 +176,28 @@ class _EditContactAddressViewState width: 48, decoration: BoxDecoration( borderRadius: BorderRadius.circular(24), - color: Theme.of(context) - .extension()! - .textFieldActiveBG, + color: + Theme.of( + context, + ).extension()!.textFieldActiveBG, ), child: Center( - child: contact.emojiChar == null - ? SvgPicture.asset( - Assets.svg.user, - height: 24, - width: 24, - ) - : Text( - contact.emojiChar!, - style: STextStyles.pageTitleH1(context), - ), + child: + contact.emojiChar == null + ? SvgPicture.asset( + Assets.svg.user, + height: 24, + width: 24, + ) + : Text( + contact.emojiChar!, + style: STextStyles.pageTitleH1(context), + ), ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), if (isDesktop) - Text( - contact.name, - style: STextStyles.pageTitleH2(context), - ), + Text(contact.name, style: STextStyles.pageTitleH2(context)), if (!isDesktop) Expanded( child: FittedBox( @@ -209,23 +210,18 @@ class _EditContactAddressViewState ), ], ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), NewContactAddressEntryForm( id: 0, barcodeScanner: barcodeScanner, clipboard: clipboard, ), - const SizedBox( - height: 24, - ), + const SizedBox(height: 24), ConditionalParent( condition: isDesktop, - builder: (child) => MouseRegion( - cursor: SystemMouseCursors.click, - child: child, - ), + builder: + (child) => + MouseRegion(cursor: SystemMouseCursors.click, child: child), child: GestureDetector( onTap: () async { // delete address @@ -240,11 +236,13 @@ class _EditContactAddressViewState //Deleting an entry directly from _addresses gives error // "Cannot remove from a fixed-length list", so we remove the // entry from a copy - final tempAddresses = - List.from(_addresses); + final tempAddresses = List.from( + _addresses, + ); tempAddresses.remove(entry); - final ContactEntry editedContact = - contact.copyWith(addresses: tempAddresses); + final ContactEntry editedContact = contact.copyWith( + addresses: tempAddresses, + ); if (await ref .read(addressBookServiceProvider) .editContact(editedContact)) { @@ -254,16 +252,11 @@ class _EditContactAddressViewState // TODO show error notification } }, - child: Text( - "Delete address", - style: STextStyles.link(context), - ), + child: Text("Delete address", style: STextStyles.link(context)), ), ), const Spacer(), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), Row( children: [ Expanded( @@ -283,9 +276,7 @@ class _EditContactAddressViewState }, ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: PrimaryButton( label: "Save", diff --git a/lib/pages/address_book_views/subviews/edit_contact_name_emoji_view.dart b/lib/pages/address_book_views/subviews/edit_contact_name_emoji_view.dart index a552aca29..412da64d6 100644 --- a/lib/pages/address_book_views/subviews/edit_contact_name_emoji_view.dart +++ b/lib/pages/address_book_views/subviews/edit_contact_name_emoji_view.dart @@ -33,10 +33,7 @@ import '../../../widgets/stack_text_field.dart'; import '../../../widgets/textfield_icon_button.dart'; class EditContactNameEmojiView extends ConsumerStatefulWidget { - const EditContactNameEmojiView({ - super.key, - required this.contactId, - }); + const EditContactNameEmojiView({super.key, required this.contactId}); static const String routeName = "/editContactNameEmoji"; @@ -63,8 +60,9 @@ class _EditContactNameEmojiViewState nameFocusNode = FocusNode(); WidgetsBinding.instance.addPostFrameCallback((timeStamp) { - final contact = - ref.read(addressBookServiceProvider).getContactById(contactId); + final contact = ref + .read(addressBookServiceProvider) + .getContactById(contactId); nameController.text = contact.name; setState(() { @@ -84,8 +82,9 @@ class _EditContactNameEmojiViewState @override Widget build(BuildContext context) { final contact = ref.watch( - addressBookServiceProvider - .select((value) => value.getContactById(contactId)), + addressBookServiceProvider.select( + (value) => value.getContactById(contactId), + ), ); final isDesktop = Util.isDesktop; @@ -93,53 +92,58 @@ class _EditContactNameEmojiViewState return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed(const Duration(milliseconds: 75)); - } - if (mounted) { - Navigator.of(context).pop(); - } - }, - ), - title: Text( - "Edit contact", - style: STextStyles.navBarTitle(context), - ), - ), - body: LayoutBuilder( - builder: (context, constraints) { - return Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 75), + ); + } + if (mounted) { + Navigator.of(context).pop(); + } + }, ), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: child, + title: Text( + "Edit contact", + style: STextStyles.navBarTitle(context), + ), + ), + body: SafeArea( + child: LayoutBuilder( + builder: (context, constraints) { + return Padding( + padding: const EdgeInsets.only( + left: 12, + top: 12, + right: 12, ), - ), - ), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: child, + ), + ), + ), + ), + ); + }, ), - ); - }, + ), + ), ), - ), - ), child: Column( children: [ Row( @@ -208,23 +212,26 @@ class _EditContactNameEmojiViewState width: emojiSize, decoration: BoxDecoration( borderRadius: BorderRadius.circular(emojiSize / 2), - color: Theme.of(context) - .extension()! - .textFieldActiveBG, + color: + Theme.of( + context, + ).extension()!.textFieldActiveBG, ), child: Center( - child: _selectedEmoji == null - ? SvgPicture.asset( - Assets.svg.user, - height: emojiSize / 2, - width: emojiSize / 2, - ) - : Text( - _selectedEmoji!.char, - style: isDesktop - ? STextStyles.desktopH3(context) - : STextStyles.pageTitleH1(context), - ), + child: + _selectedEmoji == null + ? SvgPicture.asset( + Assets.svg.user, + height: emojiSize / 2, + width: emojiSize / 2, + ) + : Text( + _selectedEmoji!.char, + style: + isDesktop + ? STextStyles.desktopH3(context) + : STextStyles.pageTitleH1(context), + ), ), ), Align( @@ -234,28 +241,32 @@ class _EditContactNameEmojiViewState width: 14, decoration: BoxDecoration( borderRadius: BorderRadius.circular(14), - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), child: Center( - child: _selectedEmoji == null - ? SvgPicture.asset( - Assets.svg.plus, - color: Theme.of(context) - .extension()! - .textWhite, - width: 12, - height: 12, - ) - : SvgPicture.asset( - Assets.svg.thickX, - color: Theme.of(context) - .extension()! - .textWhite, - width: 8, - height: 8, - ), + child: + _selectedEmoji == null + ? SvgPicture.asset( + Assets.svg.plus, + color: + Theme.of( + context, + ).extension()!.textWhite, + width: 12, + height: 12, + ) + : SvgPicture.asset( + Assets.svg.thickX, + color: + Theme.of( + context, + ).extension()!.textWhite, + width: 8, + height: 8, + ), ), ), ), @@ -263,10 +274,7 @@ class _EditContactNameEmojiViewState ), ), ), - if (isDesktop) - const SizedBox( - width: 8, - ), + if (isDesktop) const SizedBox(width: 8), if (isDesktop) Expanded( child: ClipRRect( @@ -285,35 +293,33 @@ class _EditContactNameEmojiViewState nameFocusNode, context, ).copyWith( - suffixIcon: nameController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - nameController.text = ""; - }); - }, - ), - ], + suffixIcon: + nameController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + nameController.text = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), ), ], ), - if (!isDesktop) - const SizedBox( - height: 8, - ), + if (!isDesktop) const SizedBox(height: 8), if (!isDesktop) ClipRRect( borderRadius: BorderRadius.circular( @@ -331,32 +337,31 @@ class _EditContactNameEmojiViewState nameFocusNode, context, ).copyWith( - suffixIcon: nameController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - nameController.text = ""; - }); - }, - ), - ], + suffixIcon: + nameController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + nameController.text = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), const Spacer(), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), Row( children: [ Expanded( @@ -376,9 +381,7 @@ class _EditContactNameEmojiViewState }, ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: PrimaryButton( label: "Save", @@ -398,9 +401,9 @@ class _EditContactNameEmojiViewState _selectedEmoji == null ? null : _selectedEmoji!.char, ); unawaited( - ref.read(addressBookServiceProvider).editContact( - editedContact, - ), + ref + .read(addressBookServiceProvider) + .editContact(editedContact), ); if (mounted) { Navigator.of(context).pop(); diff --git a/lib/pages/buy_view/buy_order_details.dart b/lib/pages/buy_view/buy_order_details.dart index 7021309a2..30b6060d8 100644 --- a/lib/pages/buy_view/buy_order_details.dart +++ b/lib/pages/buy_view/buy_order_details.dart @@ -29,10 +29,7 @@ import '../../widgets/desktop/primary_button.dart'; import '../../widgets/rounded_white_container.dart'; class BuyOrderDetailsView extends ConsumerStatefulWidget { - const BuyOrderDetailsView({ - super.key, - required this.order, - }); + const BuyOrderDetailsView({super.key, required this.order}); final SimplexOrder order; @@ -74,29 +71,31 @@ Provider: Simplex style: STextStyles.navBarTitle(context), ), ), - body: LayoutBuilder( - builder: (builderContext, constraints) { - return Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, - ), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: child, + body: SafeArea( + child: LayoutBuilder( + builder: (builderContext, constraints) { + return Padding( + padding: const EdgeInsets.only( + left: 12, + top: 12, + right: 12, + ), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: child, + ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ); @@ -104,21 +103,13 @@ Provider: Simplex child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Text( - "Simplex order", - style: STextStyles.pageTitleH1(context), - ), - const SizedBox( - height: 16, - ), + Text("Simplex order", style: STextStyles.pageTitleH1(context)), + const SizedBox(height: 16), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Purchase ID", - style: STextStyles.label(context), - ), + Text("Purchase ID", style: STextStyles.label(context)), Text( widget.order.paymentId, style: STextStyles.label(context).copyWith( @@ -128,17 +119,12 @@ Provider: Simplex ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "User ID", - style: STextStyles.label(context), - ), + Text("User ID", style: STextStyles.label(context)), Text( widget.order.userId, style: STextStyles.label(context).copyWith( @@ -148,17 +134,12 @@ Provider: Simplex ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Quote ID", - style: STextStyles.label(context), - ), + Text("Quote ID", style: STextStyles.label(context)), Text( widget.order.quote.id, style: STextStyles.label(context).copyWith( @@ -168,17 +149,12 @@ Provider: Simplex ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Quoted cost", - style: STextStyles.label(context), - ), + Text("Quoted cost", style: STextStyles.label(context)), Text( "${widget.order.quote.youPayFiatPrice.toStringAsFixed(2)} ${widget.order.quote.fiat.ticker.toUpperCase()}", style: STextStyles.label(context).copyWith( @@ -188,9 +164,7 @@ Provider: Simplex ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), // RoundedWhiteContainer( // child: Row( // mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -215,10 +189,7 @@ Provider: Simplex child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Quoted amount", - style: STextStyles.label(context), - ), + Text("Quoted amount", style: STextStyles.label(context)), Text( "${widget.order.quote.youReceiveCryptoAmount} ${widget.order.quote.crypto.ticker.toUpperCase()}", style: STextStyles.label(context).copyWith( @@ -228,9 +199,7 @@ Provider: Simplex ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -248,32 +217,23 @@ Provider: Simplex ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Provider", - style: STextStyles.label(context), - ), + Text("Provider", style: STextStyles.label(context)), SizedBox( width: 64, height: 32, child: SvgPicture.asset( - Assets.buy.simplexLogo( - ref.watch(themeProvider).brightness, - ), + Assets.buy.simplexLogo(ref.watch(themeProvider).brightness), ), ), ], ), ), - const SizedBox( - height: 24, - ), + const SizedBox(height: 24), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -307,18 +267,15 @@ Provider: Simplex Assets.svg.copy, width: 20, height: 20, - color: Theme.of(context) - .extension()! - .buttonTextSecondary, - ), - const SizedBox( - width: 10, + color: + Theme.of( + context, + ).extension()!.buttonTextSecondary, ), + const SizedBox(width: 10), Text( "Copy to clipboard", - style: STextStyles.desktopButtonSecondaryEnabled( - context, - ), + style: STextStyles.desktopButtonSecondaryEnabled(context), ), ], ), diff --git a/lib/pages/buy_view/buy_quote_preview.dart b/lib/pages/buy_view/buy_quote_preview.dart index 7d736e3a6..8137bce71 100644 --- a/lib/pages/buy_view/buy_quote_preview.dart +++ b/lib/pages/buy_view/buy_quote_preview.dart @@ -14,8 +14,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:intl/intl.dart'; + import '../../models/buy/response_objects/quote.dart'; -import 'sub_widgets/buy_warning_popup.dart'; import '../../themes/stack_colors.dart'; import '../../themes/theme_providers.dart'; import '../../utilities/assets.dart'; @@ -26,12 +26,10 @@ import '../../widgets/conditional_parent.dart'; import '../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../widgets/desktop/primary_button.dart'; import '../../widgets/rounded_white_container.dart'; +import 'sub_widgets/buy_warning_popup.dart'; class BuyQuotePreviewView extends ConsumerStatefulWidget { - const BuyQuotePreviewView({ - super.key, - required this.quote, - }); + const BuyQuotePreviewView({super.key, required this.quote}); final SimplexQuote quote; @@ -48,9 +46,7 @@ class _BuyQuotePreviewViewState extends ConsumerState { Future _buyWarning() async { await showDialog( context: context, - builder: (context) => BuyWarningPopup( - quote: widget.quote, - ), + builder: (context) => BuyWarningPopup(quote: widget.quote), ); } @@ -76,29 +72,31 @@ class _BuyQuotePreviewViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: LayoutBuilder( - builder: (builderContext, constraints) { - return Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, - ), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: child, + body: SafeArea( + child: LayoutBuilder( + builder: (builderContext, constraints) { + return Padding( + padding: const EdgeInsets.only( + left: 12, + top: 12, + right: 12, + ), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: child, + ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ); @@ -110,17 +108,12 @@ class _BuyQuotePreviewViewState extends ConsumerState { "Buy ${widget.quote.crypto.ticker.toUpperCase()}", style: STextStyles.pageTitleH1(context), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "You pay", - style: STextStyles.label(context), - ), + Text("You pay", style: STextStyles.label(context)), Text( "${format.simpleCurrencySymbol(widget.quote.fiat.ticker.toUpperCase())}${widget.quote.youPayFiatPrice.toStringAsFixed(2)} ${widget.quote.fiat.ticker.toUpperCase()}", style: STextStyles.label(context).copyWith( @@ -130,9 +123,7 @@ class _BuyQuotePreviewViewState extends ConsumerState { ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), // RoundedWhiteContainer( // child: Row( // mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -157,10 +148,7 @@ class _BuyQuotePreviewViewState extends ConsumerState { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "You receive", - style: STextStyles.label(context), - ), + Text("You receive", style: STextStyles.label(context)), Text( "${widget.quote.youReceiveCryptoAmount} ${widget.quote.crypto.ticker.toUpperCase()}", style: STextStyles.label(context).copyWith( @@ -170,9 +158,7 @@ class _BuyQuotePreviewViewState extends ConsumerState { ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -190,17 +176,12 @@ class _BuyQuotePreviewViewState extends ConsumerState { ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Quote ID", - style: STextStyles.label(context), - ), + Text("Quote ID", style: STextStyles.label(context)), Text( widget.quote.id, style: STextStyles.label(context).copyWith( @@ -210,37 +191,25 @@ class _BuyQuotePreviewViewState extends ConsumerState { ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Provider", - style: STextStyles.label(context), - ), + Text("Provider", style: STextStyles.label(context)), SizedBox( width: 64, height: 32, child: SvgPicture.asset( - Assets.buy.simplexLogo( - ref.watch(themeProvider).brightness, - ), + Assets.buy.simplexLogo(ref.watch(themeProvider).brightness), ), ), ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), const Spacer(), - PrimaryButton( - label: "Buy", - onPressed: _buyWarning, - ), + PrimaryButton(label: "Buy", onPressed: _buyWarning), ], ), ); diff --git a/lib/pages/buy_view/sub_widgets/crypto_selection_view.dart b/lib/pages/buy_view/sub_widgets/crypto_selection_view.dart index 432a3435a..089b492af 100644 --- a/lib/pages/buy_view/sub_widgets/crypto_selection_view.dart +++ b/lib/pages/buy_view/sub_widgets/crypto_selection_view.dart @@ -32,10 +32,7 @@ import '../../../widgets/stack_text_field.dart'; import '../../../widgets/textfield_icon_button.dart'; class CryptoSelectionView extends ConsumerStatefulWidget { - const CryptoSelectionView({ - super.key, - required this.coins, - }); + const CryptoSelectionView({super.key, required this.coins}); final List coins; @@ -122,11 +119,11 @@ class _CryptoSelectionViewState extends ConsumerState { style: STextStyles.pageTitleH2(context), ), ), - body: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: child, ), - child: child, ), ), ); @@ -135,10 +132,7 @@ class _CryptoSelectionViewState extends ConsumerState { crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: isDesktop ? MainAxisSize.min : MainAxisSize.max, children: [ - if (!isDesktop) - const SizedBox( - height: 16, - ), + if (!isDesktop) const SizedBox(height: 16), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -168,39 +162,33 @@ class _CryptoSelectionViewState extends ConsumerState { height: 16, ), ), - suffixIcon: _searchController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _searchController.text = ""; - }); - filter(""); - }, - ), - ], + suffixIcon: + _searchController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _searchController.text = ""; + }); + filter(""); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), - const SizedBox( - height: 10, - ), - Text( - "All coins", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 10), + Text("All coins", style: STextStyles.smallMed12(context)), + const SizedBox(height: 12), Flexible( child: RoundedWhiteContainer( padding: const EdgeInsets.all(0), @@ -226,9 +214,7 @@ class _CryptoSelectionViewState extends ConsumerState { ticker: _coins[index].ticker, ), ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -237,16 +223,16 @@ class _CryptoSelectionViewState extends ConsumerState { _coins[index].name, style: STextStyles.largeMedium14(context), ), - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), Text( _coins[index].ticker.toUpperCase(), - style: STextStyles.smallMed12(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, + style: STextStyles.smallMed12( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textSubtitle1, ), ), ], @@ -297,9 +283,7 @@ class CoinIconForTicker extends ConsumerWidget { try { final coin = AppConfig.getCryptoCurrencyForTicker(ticker)!; return SvgPicture.file( - File( - ref.watch(coinIconProvider(coin)), - ), + File(ref.watch(coinIconProvider(coin))), width: size, height: size, ); diff --git a/lib/pages/buy_view/sub_widgets/fiat_selection_view.dart b/lib/pages/buy_view/sub_widgets/fiat_selection_view.dart index 4fee72444..05bb3a6df 100644 --- a/lib/pages/buy_view/sub_widgets/fiat_selection_view.dart +++ b/lib/pages/buy_view/sub_widgets/fiat_selection_view.dart @@ -28,10 +28,7 @@ import '../../../widgets/stack_text_field.dart'; import '../../../widgets/textfield_icon_button.dart'; class FiatSelectionView extends StatefulWidget { - const FiatSelectionView({ - super.key, - required this.fiats, - }); + const FiatSelectionView({super.key, required this.fiats}); final List fiats; @@ -122,11 +119,11 @@ class _FiatSelectionViewState extends State { style: STextStyles.pageTitleH2(context), ), ), - body: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: child, ), - child: child, ), ), ); @@ -135,10 +132,7 @@ class _FiatSelectionViewState extends State { crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: isDesktop ? MainAxisSize.min : MainAxisSize.max, children: [ - if (!isDesktop) - const SizedBox( - height: 16, - ), + if (!isDesktop) const SizedBox(height: 16), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -168,39 +162,33 @@ class _FiatSelectionViewState extends State { height: 16, ), ), - suffixIcon: _searchController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _searchController.text = ""; - }); - filter(""); - }, - ), - ], + suffixIcon: + _searchController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _searchController.text = ""; + }); + filter(""); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), - const SizedBox( - height: 10, - ), - Text( - "All currencies", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 10), + Text("All currencies", style: STextStyles.smallMed12(context)), + const SizedBox(height: 12), Flexible( child: SingleChildScrollView( child: RoundedWhiteContainer( @@ -212,95 +200,92 @@ class _FiatSelectionViewState extends State { }, defaultVerticalAlignment: TableCellVerticalAlignment.middle, children: [ - ..._fiats.map( - (e) { - return TableRow( - children: [ - TableCell( - verticalAlignment: - TableCellVerticalAlignment.fill, - child: GestureDetector( - onTap: () => Navigator.of(context).pop(e), - child: Container( - color: Colors.transparent, - padding: const EdgeInsets.only(left: 12), - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: - CrossAxisAlignment.stretch, - children: [ - Container( - padding: const EdgeInsets.all(7.5), - decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .currencyListItemBG, - borderRadius: - BorderRadius.circular(4), + ..._fiats.map((e) { + return TableRow( + children: [ + TableCell( + verticalAlignment: TableCellVerticalAlignment.fill, + child: GestureDetector( + onTap: () => Navigator.of(context).pop(e), + child: Container( + color: Colors.transparent, + padding: const EdgeInsets.only(left: 12), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.stretch, + children: [ + Container( + padding: const EdgeInsets.all(7.5), + decoration: BoxDecoration( + color: + Theme.of(context) + .extension()! + .currencyListItemBG, + borderRadius: BorderRadius.circular(4), + ), + child: Text( + format.simpleCurrencySymbol( + e.ticker.toUpperCase(), ), - child: Text( - format.simpleCurrencySymbol( - e.ticker.toUpperCase(), - ), - style: STextStyles.subtitle(context) - .apply( - fontSizeFactor: (1 / - format - .simpleCurrencySymbol( - e.ticker.toUpperCase(), - ) - .length * // Couldn't get pow() working here - format - .simpleCurrencySymbol( - e.ticker.toUpperCase(), - ) - .length), - ), - textAlign: TextAlign.center, + style: STextStyles.subtitle( + context, + ).apply( + fontSizeFactor: + (1 / + format + .simpleCurrencySymbol( + e.ticker.toUpperCase(), + ) + .length * // Couldn't get pow() working here + format + .simpleCurrencySymbol( + e.ticker.toUpperCase(), + ) + .length), ), + textAlign: TextAlign.center, ), - ], - ), + ), + ], ), ), ), - GestureDetector( - onTap: () => Navigator.of(context).pop(e), - child: Container( - color: Colors.transparent, - child: Padding( - padding: const EdgeInsets.all(12), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - e.name, - style: - STextStyles.largeMedium14(context), - ), - const SizedBox( - height: 2, - ), - Text( - e.ticker.toUpperCase(), - style: STextStyles.smallMed12(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, - ), + ), + GestureDetector( + onTap: () => Navigator.of(context).pop(e), + child: Container( + color: Colors.transparent, + child: Padding( + padding: const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + e.name, + style: STextStyles.largeMedium14(context), + ), + const SizedBox(height: 2), + Text( + e.ticker.toUpperCase(), + style: STextStyles.smallMed12( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textSubtitle1, ), - ], - ), + ), + ], ), ), ), - ], - ); - }, - ), + ), + ], + ); + }), ], ), diff --git a/lib/pages/cashfusion/cashfusion_view.dart b/lib/pages/cashfusion/cashfusion_view.dart index 4579dbc52..53da25374 100644 --- a/lib/pages/cashfusion/cashfusion_view.dart +++ b/lib/pages/cashfusion/cashfusion_view.dart @@ -37,10 +37,7 @@ import 'fusion_progress_view.dart'; import 'fusion_rounds_selection_sheet.dart'; class CashFusionView extends ConsumerStatefulWidget { - const CashFusionView({ - super.key, - required this.walletId, - }); + const CashFusionView({super.key, required this.walletId}); static const routeName = "/cashFusionView"; @@ -74,15 +71,16 @@ class _CashFusionViewState extends ConsumerState { ); } catch (e) { if (!e.toString().contains( - "FusionProgressUIState was already set for ${widget.walletId}", - )) { + "FusionProgressUIState was already set for ${widget.walletId}", + )) { rethrow; } } - final int rounds = _option == FusionOption.continuous - ? 0 - : int.parse(fusionRoundController.text); + final int rounds = + _option == FusionOption.continuous + ? 0 + : int.parse(fusionRoundController.text); final newInfo = FusionInfo( host: serverController.text, @@ -94,16 +92,11 @@ class _CashFusionViewState extends ConsumerState { // update user prefs (persistent) ref.read(prefsChangeNotifierProvider).setFusionServerInfo(coin, newInfo); - unawaited( - fusionWallet.fuse( - fusionInfo: newInfo, - ), - ); + unawaited(fusionWallet.fuse(fusionInfo: newInfo)); - await Navigator.of(context).pushNamed( - FusionProgressView.routeName, - arguments: widget.walletId, - ); + await Navigator.of( + context, + ).pushNamed(FusionProgressView.routeName, arguments: widget.walletId); } @override @@ -118,8 +111,9 @@ class _CashFusionViewState extends ConsumerState { coin = ref.read(pWalletCoin(widget.walletId)); - final info = - ref.read(prefsChangeNotifierProvider).getFusionServerInfo(coin); + final info = ref + .read(prefsChangeNotifierProvider) + .getFusionServerInfo(coin); serverController.text = info.host; portController.text = info.port.toString(); @@ -156,10 +150,7 @@ class _CashFusionViewState extends ConsumerState { appBar: AppBar( automaticallyImplyLeading: false, leading: const AppBarBackButton(), - title: Text( - "Fusion", - style: STextStyles.navBarTitle(context), - ), + title: Text("Fusion", style: STextStyles.navBarTitle(context)), titleSpacing: 0, actions: [ AspectRatio( @@ -170,9 +161,10 @@ class _CashFusionViewState extends ConsumerState { Assets.svg.circleQuestion, width: 20, height: 20, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, ), onPressed: () async { //' TODO show about? @@ -181,225 +173,89 @@ class _CashFusionViewState extends ConsumerState { ), ], ), - body: LayoutBuilder( - builder: (builderContext, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - RoundedWhiteContainer( - child: Text( - "Fusion helps anonymize your coins by mixing them.", - style: STextStyles.w500_12(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, + body: SafeArea( + child: LayoutBuilder( + builder: (builderContext, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + RoundedWhiteContainer( + child: Text( + "Fusion helps anonymize your coins by mixing them.", + style: STextStyles.w500_12(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textSubtitle1, + ), ), ), - ), - const SizedBox( - height: 16, - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Server settings", - style: STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark3, + const SizedBox(height: 16), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Server settings", + style: STextStyles.w500_14(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark3, + ), + ), + CustomTextButton( + text: "Default", + onTap: () { + final def = + kFusionServerInfoDefaults[coin]!; + serverController.text = def.host; + portController.text = def.port.toString(); + fusionRoundController.text = + def.rounds.toString(); + _option = FusionOption.continuous; + setState(() { + _enableSSLCheckbox = def.ssl; + }); + }, ), + ], + ), + const SizedBox(height: 12), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - CustomTextButton( - text: "Default", - onTap: () { - final def = kFusionServerInfoDefaults[coin]!; - serverController.text = def.host; - portController.text = def.port.toString(); - fusionRoundController.text = - def.rounds.toString(); - _option = FusionOption.continuous; + child: TextField( + autocorrect: false, + enableSuggestions: false, + controller: serverController, + focusNode: serverFocusNode, + onChanged: (value) { setState(() { - _enableSSLCheckbox = def.ssl; + _enableStartButton = + value.isNotEmpty && + portController.text.isNotEmpty && + fusionRoundController.text.isNotEmpty; }); }, - ), - ], - ), - const SizedBox( - height: 12, - ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autocorrect: false, - enableSuggestions: false, - controller: serverController, - focusNode: serverFocusNode, - onChanged: (value) { - setState(() { - _enableStartButton = value.isNotEmpty && - portController.text.isNotEmpty && - fusionRoundController.text.isNotEmpty; - }); - }, - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Server", - serverFocusNode, - context, - desktopMed: true, - ), - ), - ), - const SizedBox( - height: 10, - ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autocorrect: false, - enableSuggestions: false, - controller: portController, - focusNode: portFocusNode, - inputFormatters: [ - FilteringTextInputFormatter.digitsOnly, - ], - keyboardType: TextInputType.number, - onChanged: (value) { - setState(() { - _enableStartButton = value.isNotEmpty && - serverController.text.isNotEmpty && - fusionRoundController.text.isNotEmpty; - }); - }, - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Port", - portFocusNode, - context, - ), - ), - ), - const SizedBox( - height: 10, - ), - GestureDetector( - onTap: () { - setState(() { - _enableSSLCheckbox = !_enableSSLCheckbox; - }); - }, - child: Container( - color: Colors.transparent, - child: Row( - children: [ - SizedBox( - width: 20, - height: 20, - child: Checkbox( - materialTapTargetSize: - MaterialTapTargetSize.shrinkWrap, - value: _enableSSLCheckbox, - onChanged: (newValue) { - setState( - () { - _enableSSLCheckbox = - !_enableSSLCheckbox; - }, - ); - }, - ), - ), - const SizedBox( - width: 12, - ), - Text( - "Use SSL", - style: STextStyles.itemSubtitle12(context), - ), - ], - ), - ), - ), - const SizedBox( - height: 16, - ), - Text( - "Rounds of fusion", - style: STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark3, - ), - ), - const SizedBox( - height: 12, - ), - RoundedContainer( - onPressed: () async { - final option = - await showModalBottomSheet( - backgroundColor: Colors.transparent, - context: context, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical( - top: Radius.circular(20), - ), + style: STextStyles.field(context), + decoration: standardInputDecoration( + "Server", + serverFocusNode, + context, + desktopMed: true, ), - builder: (_) { - return FusionRoundCountSelectSheet( - currentOption: _option, - ); - }, - ); - if (option != null) { - setState(() { - _option = option; - }); - } - }, - color: Theme.of(context) - .extension()! - .textFieldActiveBG, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - _option.name.capitalize(), - style: STextStyles.w500_12(context), - ), - SvgPicture.asset( - Assets.svg.chevronDown, - width: 12, - color: Theme.of(context) - .extension()! - .textSubtitle1, - ), - ], ), ), - ), - if (_option == FusionOption.custom) - const SizedBox( - height: 10, - ), - if (_option == FusionOption.custom) + const SizedBox(height: 10), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -407,45 +263,176 @@ class _CashFusionViewState extends ConsumerState { child: TextField( autocorrect: false, enableSuggestions: false, - controller: fusionRoundController, - focusNode: fusionRoundFocusNode, + controller: portController, + focusNode: portFocusNode, inputFormatters: [ FilteringTextInputFormatter.digitsOnly, ], keyboardType: TextInputType.number, onChanged: (value) { setState(() { - _enableStartButton = value.isNotEmpty && + _enableStartButton = + value.isNotEmpty && serverController.text.isNotEmpty && - portController.text.isNotEmpty; + fusionRoundController.text.isNotEmpty; }); }, style: STextStyles.field(context), decoration: standardInputDecoration( - "Number of fusions", - fusionRoundFocusNode, + "Port", + portFocusNode, context, - ).copyWith( - labelText: "Enter number of fusions..", ), ), ), - const SizedBox( - height: 16, - ), - const Spacer(), - PrimaryButton( - label: "Start", - enabled: _enableStartButton, - onPressed: _startFusion, - ), - ], + const SizedBox(height: 10), + GestureDetector( + onTap: () { + setState(() { + _enableSSLCheckbox = !_enableSSLCheckbox; + }); + }, + child: Container( + color: Colors.transparent, + child: Row( + children: [ + SizedBox( + width: 20, + height: 20, + child: Checkbox( + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + value: _enableSSLCheckbox, + onChanged: (newValue) { + setState(() { + _enableSSLCheckbox = + !_enableSSLCheckbox; + }); + }, + ), + ), + const SizedBox(width: 12), + Text( + "Use SSL", + style: STextStyles.itemSubtitle12( + context, + ), + ), + ], + ), + ), + ), + const SizedBox(height: 16), + Text( + "Rounds of fusion", + style: STextStyles.w500_14(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark3, + ), + ), + const SizedBox(height: 12), + RoundedContainer( + onPressed: () async { + final option = + await showModalBottomSheet( + backgroundColor: Colors.transparent, + context: context, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(20), + ), + ), + builder: (_) { + return FusionRoundCountSelectSheet( + currentOption: _option, + ); + }, + ); + if (option != null) { + setState(() { + _option = option; + }); + } + }, + color: + Theme.of( + context, + ).extension()!.textFieldActiveBG, + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 8, + ), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + _option.name.capitalize(), + style: STextStyles.w500_12(context), + ), + SvgPicture.asset( + Assets.svg.chevronDown, + width: 12, + color: + Theme.of(context) + .extension()! + .textSubtitle1, + ), + ], + ), + ), + ), + if (_option == FusionOption.custom) + const SizedBox(height: 10), + if (_option == FusionOption.custom) + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autocorrect: false, + enableSuggestions: false, + controller: fusionRoundController, + focusNode: fusionRoundFocusNode, + inputFormatters: [ + FilteringTextInputFormatter.digitsOnly, + ], + keyboardType: TextInputType.number, + onChanged: (value) { + setState(() { + _enableStartButton = + value.isNotEmpty && + serverController.text.isNotEmpty && + portController.text.isNotEmpty; + }); + }, + style: STextStyles.field(context), + decoration: standardInputDecoration( + "Number of fusions", + fusionRoundFocusNode, + context, + ).copyWith( + labelText: "Enter number of fusions..", + ), + ), + ), + const SizedBox(height: 16), + const Spacer(), + PrimaryButton( + label: "Start", + enabled: _enableStartButton, + onPressed: _startFusion, + ), + ], + ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/cashfusion/fusion_progress_view.dart b/lib/pages/cashfusion/fusion_progress_view.dart index 022fa0861..021a8ef69 100644 --- a/lib/pages/cashfusion/fusion_progress_view.dart +++ b/lib/pages/cashfusion/fusion_progress_view.dart @@ -33,10 +33,7 @@ import '../../widgets/rounded_container.dart'; import '../../widgets/stack_dialog.dart'; class FusionProgressView extends ConsumerStatefulWidget { - const FusionProgressView({ - super.key, - required this.walletId, - }); + const FusionProgressView({super.key, required this.walletId}); static const routeName = "/cashFusionProgressView"; @@ -52,23 +49,24 @@ class _FusionProgressViewState extends ConsumerState { final shouldCancel = await showDialog( context: context, barrierDismissible: false, - builder: (_) => StackDialog( - title: "Cancel fusion?", - leftButton: SecondaryButton( - label: "No", - buttonHeight: null, - onPressed: () { - Navigator.of(context).pop(false); - }, - ), - rightButton: PrimaryButton( - label: "Yes", - buttonHeight: null, - onPressed: () { - Navigator.of(context).pop(true); - }, - ), - ), + builder: + (_) => StackDialog( + title: "Cancel fusion?", + leftButton: SecondaryButton( + label: "No", + buttonHeight: null, + onPressed: () { + Navigator.of(context).pop(false); + }, + ), + rightButton: PrimaryButton( + label: "Yes", + buttonHeight: null, + onPressed: () { + Navigator.of(context).pop(true); + }, + ), + ), ); if (shouldCancel == true && mounted) { @@ -113,9 +111,10 @@ class _FusionProgressViewState extends ConsumerState { final bool _failed = ref.watch(fusionProgressUIStateProvider(widget.walletId)).failed; - final int _fusionRoundsCompleted = ref - .watch(fusionProgressUIStateProvider(widget.walletId)) - .fusionRoundsCompleted; + final int _fusionRoundsCompleted = + ref + .watch(fusionProgressUIStateProvider(widget.walletId)) + .fusionRoundsCompleted; WakelockPlus.enable(); @@ -124,28 +123,28 @@ class _FusionProgressViewState extends ConsumerState { return await _requestAndProcessCancel(); }, child: Background( - child: SafeArea( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - automaticallyImplyLeading: false, - leading: AppBarBackButton( - onPressed: () async { - if (await _requestAndProcessCancel()) { - if (mounted) { - Navigator.of(context).pop(); - } + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + automaticallyImplyLeading: false, + leading: AppBarBackButton( + onPressed: () async { + if (await _requestAndProcessCancel()) { + if (mounted) { + Navigator.of(context).pop(); } - }, - ), - title: Text( - "Fusion progress", - style: STextStyles.navBarTitle(context), - ), - titleSpacing: 0, + } + }, ), - body: LayoutBuilder( + title: Text( + "Fusion progress", + style: STextStyles.navBarTitle(context), + ), + titleSpacing: 0, + ), + body: SafeArea( + child: LayoutBuilder( builder: (builderContext, constraints) { return SingleChildScrollView( child: ConstrainedBox( @@ -160,64 +159,57 @@ class _FusionProgressViewState extends ConsumerState { children: [ if (_fusionRoundsCompleted == 0) RoundedContainer( - color: Theme.of(context) - .extension()! - .snackBarBackError, + color: + Theme.of(context) + .extension()! + .snackBarBackError, child: Text( "Do not close this window. If you exit, " "the process will be canceled.", - style: - STextStyles.smallMed14(context).copyWith( - color: Theme.of(context) - .extension()! - .snackBarTextError, + style: STextStyles.smallMed14( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .snackBarTextError, ), textAlign: TextAlign.center, ), ), if (_fusionRoundsCompleted > 0) RoundedContainer( - color: Theme.of(context) - .extension()! - .snackBarBackInfo, + color: + Theme.of(context) + .extension()! + .snackBarBackInfo, child: Text( "Fusion rounds completed: $_fusionRoundsCompleted", style: STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .snackBarTextInfo, + color: + Theme.of(context) + .extension()! + .snackBarTextInfo, ), textAlign: TextAlign.center, ), ), - const SizedBox( - height: 20, - ), - FusionProgress( - walletId: widget.walletId, - ), + const SizedBox(height: 20), + FusionProgress(walletId: widget.walletId), const Spacer(), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), if (_succeeded) PrimaryButton( label: "Fuse again", onPressed: _fuseAgain, ), - if (_succeeded) - const SizedBox( - height: 16, - ), + if (_succeeded) const SizedBox(height: 16), if (_failed) PrimaryButton( label: "Try again", onPressed: _fuseAgain, ), - if (_failed) - const SizedBox( - height: 16, - ), + if (_failed) const SizedBox(height: 16), SecondaryButton( label: "Cancel", onPressed: () async { @@ -247,8 +239,9 @@ class _FusionProgressViewState extends ConsumerState { final fusionWallet = ref.read(pWallets).getWallet(widget.walletId) as CashFusionInterface; - final fusionInfo = - ref.read(prefsChangeNotifierProvider).getFusionServerInfo(coin); + final fusionInfo = ref + .read(prefsChangeNotifierProvider) + .getFusionServerInfo(coin); try { fusionWallet.uiState = ref.read( @@ -256,8 +249,8 @@ class _FusionProgressViewState extends ConsumerState { ); } catch (e) { if (!e.toString().contains( - "FusionProgressUIState was already set for ${widget.walletId}", - )) { + "FusionProgressUIState was already set for ${widget.walletId}", + )) { rethrow; } } diff --git a/lib/pages/churning/churning_progress_view.dart b/lib/pages/churning/churning_progress_view.dart index 55319738a..a214640c6 100644 --- a/lib/pages/churning/churning_progress_view.dart +++ b/lib/pages/churning/churning_progress_view.dart @@ -19,10 +19,7 @@ import '../../widgets/stack_dialog.dart'; import 'churn_error_dialog.dart'; class ChurningProgressView extends ConsumerStatefulWidget { - const ChurningProgressView({ - super.key, - required this.walletId, - }); + const ChurningProgressView({super.key, required this.walletId}); static const routeName = "/churningProgressView"; @@ -37,23 +34,24 @@ class _ChurningProgressViewState extends ConsumerState { final shouldCancel = await showDialog( context: context, barrierDismissible: false, - builder: (_) => StackDialog( - title: "Cancel churning?", - leftButton: SecondaryButton( - label: "No", - buttonHeight: null, - onPressed: () { - Navigator.of(context).pop(false); - }, - ), - rightButton: PrimaryButton( - label: "Yes", - buttonHeight: null, - onPressed: () { - Navigator.of(context).pop(true); - }, - ), - ), + builder: + (_) => StackDialog( + title: "Cancel churning?", + leftButton: SecondaryButton( + label: "No", + buttonHeight: null, + onPressed: () { + Navigator.of(context).pop(false); + }, + ), + rightButton: PrimaryButton( + label: "Yes", + buttonHeight: null, + onPressed: () { + Navigator.of(context).pop(true); + }, + ), + ), ); if (shouldCancel == true && mounted) { @@ -102,10 +100,11 @@ class _ChurningProgressViewState extends ConsumerState { if (context.mounted) { showDialog( context: context, - builder: (context) => ChurnErrorDialog( - error: n.toString(), - walletId: widget.walletId, - ), + builder: + (context) => ChurnErrorDialog( + error: n.toString(), + walletId: widget.walletId, + ), ); } } @@ -117,28 +116,28 @@ class _ChurningProgressViewState extends ConsumerState { return await _requestAndProcessCancel(); }, child: Background( - child: SafeArea( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - automaticallyImplyLeading: false, - leading: AppBarBackButton( - onPressed: () async { - if (await _requestAndProcessCancel()) { - if (context.mounted) { - Navigator.of(context).pop(); - } + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + automaticallyImplyLeading: false, + leading: AppBarBackButton( + onPressed: () async { + if (await _requestAndProcessCancel()) { + if (context.mounted) { + Navigator.of(context).pop(); } - }, - ), - title: Text( - "Churning progress", - style: STextStyles.navBarTitle(context), - ), - titleSpacing: 0, + } + }, + ), + title: Text( + "Churning progress", + style: STextStyles.navBarTitle(context), ), - body: LayoutBuilder( + titleSpacing: 0, + ), + body: SafeArea( + child: LayoutBuilder( builder: (builderContext, constraints) { return SingleChildScrollView( child: ConstrainedBox( @@ -153,91 +152,85 @@ class _ChurningProgressViewState extends ConsumerState { children: [ if (_roundsCompleted == 0) RoundedContainer( - color: Theme.of(context) - .extension()! - .snackBarBackError, + color: + Theme.of(context) + .extension()! + .snackBarBackError, child: Text( "Do not close this window. If you exit, " "the process will be canceled.", - style: - STextStyles.smallMed14(context).copyWith( - color: Theme.of(context) - .extension()! - .snackBarTextError, + style: STextStyles.smallMed14( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .snackBarTextError, ), textAlign: TextAlign.center, ), ), if (_roundsCompleted > 0) RoundedContainer( - color: Theme.of(context) - .extension()! - .snackBarBackInfo, + color: + Theme.of(context) + .extension()! + .snackBarBackInfo, child: Text( "Churning rounds completed: $_roundsCompleted", style: STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .snackBarTextInfo, + color: + Theme.of(context) + .extension()! + .snackBarTextInfo, ), textAlign: TextAlign.center, ), ), - const SizedBox( - height: 20, - ), + const SizedBox(height: 20), const MoneroChanDance(), - const SizedBox( - height: 20, - ), + const SizedBox(height: 20), ProgressItem( iconAsset: Assets.svg.alertCircle, - label: "Waiting for balance to unlock ${ref.watch( - pChurningService(widget.walletId) - .select((s) => s.confirmsInfo), - ) ?? ""}", + label: + "Waiting for balance to unlock ${ref.watch(pChurningService(widget.walletId).select((s) => s.confirmsInfo)) ?? ""}", status: ref.watch( - pChurningService(widget.walletId) - .select((s) => s.waitingForUnlockedBalance), + pChurningService( + widget.walletId, + ).select((s) => s.waitingForUnlockedBalance), ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), ProgressItem( iconAsset: Assets.svg.churn, label: "Creating churn transaction", status: ref.watch( - pChurningService(widget.walletId) - .select((s) => s.makingChurnTransaction), + pChurningService( + widget.walletId, + ).select((s) => s.makingChurnTransaction), ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), ProgressItem( iconAsset: Assets.svg.checkCircle, label: "Complete", status: ref.watch( - pChurningService(widget.walletId) - .select((s) => s.completedStatus), + pChurningService( + widget.walletId, + ).select((s) => s.completedStatus), ), ), const Spacer(), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), if (_succeeded) PrimaryButton( label: "Churn again", - onPressed: ref - .read(pChurningService(widget.walletId)) - .churn, - ), - if (_succeeded) - const SizedBox( - height: 16, + onPressed: + ref + .read(pChurningService(widget.walletId)) + .churn, ), + if (_succeeded) const SizedBox(height: 16), SecondaryButton( label: "Cancel", onPressed: () async { diff --git a/lib/pages/churning/churning_view.dart b/lib/pages/churning/churning_view.dart index d59042e5e..6b23ed8f7 100644 --- a/lib/pages/churning/churning_view.dart +++ b/lib/pages/churning/churning_view.dart @@ -23,10 +23,7 @@ import 'churning_progress_view.dart'; import 'churning_rounds_selection_sheet.dart'; class ChurningView extends ConsumerStatefulWidget { - const ChurningView({ - super.key, - required this.walletId, - }); + const ChurningView({super.key, required this.walletId}); static const routeName = "/churnView"; @@ -47,16 +44,16 @@ class _ChurnViewState extends ConsumerState { Future _startChurn() async { final churningService = ref.read(pChurningService(widget.walletId)); - final int rounds = _option == ChurnOption.continuous - ? 0 - : int.parse(churningRoundController.text); + final int rounds = + _option == ChurnOption.continuous + ? 0 + : int.parse(churningRoundController.text); churningService.rounds = rounds; - await Navigator.of(context).pushNamed( - ChurningProgressView.routeName, - arguments: widget.walletId, - ); + await Navigator.of( + context, + ).pushNamed(ChurningProgressView.routeName, arguments: widget.walletId); } @override @@ -86,61 +83,58 @@ class _ChurnViewState extends ConsumerState { @override Widget build(BuildContext context) { return Background( - child: SafeArea( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - automaticallyImplyLeading: false, - leading: const AppBarBackButton(), - title: Text( - "Churn", - style: STextStyles.navBarTitle(context), - ), - titleSpacing: 0, - actions: [ - AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - size: 36, - icon: SvgPicture.asset( - Assets.svg.circleQuestion, - width: 20, - height: 20, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, - ), - onPressed: () async { - await showDialog( - context: context, - builder: (context) => const StackOkDialog( - title: "What is churning?", - message: "Churning in a Monero wallet involves" - " sending Monero to oneself in multiple" - " transactions, which can enhance privacy" - " by making it harder for observers to " - "link your transactions. This process" - " re-mixes the funds within the network," - " helping obscure transaction history. " - "Churning is optional and mainly beneficial" - " in scenarios where maximum privacy is" - " desired or if you received the Monero from" - " a source from which you'd like to disassociate.", - ), - ); - }, + child: Scaffold( + backgroundColor: Theme.of(context).extension()!.background, + appBar: AppBar( + automaticallyImplyLeading: false, + leading: const AppBarBackButton(), + title: Text("Churn", style: STextStyles.navBarTitle(context)), + titleSpacing: 0, + actions: [ + AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + size: 36, + icon: SvgPicture.asset( + Assets.svg.circleQuestion, + width: 20, + height: 20, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, ), + onPressed: () async { + await showDialog( + context: context, + builder: + (context) => const StackOkDialog( + title: "What is churning?", + message: + "Churning in a Monero wallet involves" + " sending Monero to oneself in multiple" + " transactions, which can enhance privacy" + " by making it harder for observers to " + "link your transactions. This process" + " re-mixes the funds within the network," + " helping obscure transaction history. " + "Churning is optional and mainly beneficial" + " in scenarios where maximum privacy is" + " desired or if you received the Monero from" + " a source from which you'd like to disassociate.", + ), + ); + }, ), - ], - ), - body: LayoutBuilder( + ), + ], + ), + body: SafeArea( + child: LayoutBuilder( builder: (builderContext, constraints) { return SingleChildScrollView( child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), + constraints: BoxConstraints(minHeight: constraints.maxHeight), child: IntrinsicHeight( child: Padding( padding: const EdgeInsets.all(16), @@ -151,55 +145,52 @@ class _ChurnViewState extends ConsumerState { child: Text( "Churning helps anonymize your coins by mixing them.", style: STextStyles.w500_12(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, + color: + Theme.of( + context, + ).extension()!.textSubtitle1, ), ), ), - const SizedBox( - height: 16, - ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), + const SizedBox(height: 16), Text( "Configuration", style: STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark3, + color: + Theme.of( + context, + ).extension()!.textDark3, ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), RoundedContainer( onPressed: () async { final option = await showModalBottomSheet( - backgroundColor: Colors.transparent, - context: context, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical( - top: Radius.circular(20), - ), - ), - builder: (_) { - return ChurnRoundCountSelectSheet( - currentOption: _option, + backgroundColor: Colors.transparent, + context: context, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(20), + ), + ), + builder: (_) { + return ChurnRoundCountSelectSheet( + currentOption: _option, + ); + }, ); - }, - ); if (option != null) { setState(() { _option = option; }); } }, - color: Theme.of(context) - .extension()! - .textFieldActiveBG, + color: + Theme.of( + context, + ).extension()!.textFieldActiveBG, child: Padding( padding: const EdgeInsets.symmetric(vertical: 8), child: Row( @@ -213,18 +204,17 @@ class _ChurnViewState extends ConsumerState { SvgPicture.asset( Assets.svg.chevronDown, width: 12, - color: Theme.of(context) - .extension()! - .textSubtitle1, + color: + Theme.of(context) + .extension()! + .textSubtitle1, ), ], ), ), ), if (_option == ChurnOption.custom) - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), if (_option == ChurnOption.custom) ClipRRect( borderRadius: BorderRadius.circular( @@ -254,23 +244,20 @@ class _ChurnViewState extends ConsumerState { ), ), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), CheckboxTextButton( label: "Pause on errors", - initialValue: !ref - .read(pChurningService(widget.walletId)) - .ignoreErrors, + initialValue: + !ref + .read(pChurningService(widget.walletId)) + .ignoreErrors, onChanged: (value) { ref .read(pChurningService(widget.walletId)) .ignoreErrors = !value; }, ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), const Spacer(), PrimaryButton( label: "Start", diff --git a/lib/pages/exchange_view/choose_from_stack_view.dart b/lib/pages/exchange_view/choose_from_stack_view.dart index 73d79f647..d4cc11dac 100644 --- a/lib/pages/exchange_view/choose_from_stack_view.dart +++ b/lib/pages/exchange_view/choose_from_stack_view.dart @@ -10,6 +10,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; + import '../../providers/providers.dart'; import '../../themes/stack_colors.dart'; import '../../utilities/constants.dart'; @@ -23,10 +24,7 @@ import '../../widgets/wallet_info_row/sub_widgets/wallet_info_row_balance.dart'; import '../../widgets/wallet_info_row/sub_widgets/wallet_info_row_coin_icon.dart'; class ChooseFromStackView extends ConsumerStatefulWidget { - const ChooseFromStackView({ - super.key, - required this.coin, - }); + const ChooseFromStackView({super.key, required this.coin}); final CryptoCurrency coin; @@ -48,12 +46,13 @@ class _ChooseFromStackViewState extends ConsumerState { @override Widget build(BuildContext context) { - final walletIds = ref - .watch(pWallets) - .wallets - .where((e) => e.info.coin == coin) - .map((e) => e.walletId) - .toList(); + final walletIds = + ref + .watch(pWallets) + .wallets + .where((e) => e.info.coin == coin) + .map((e) => e.walletId) + .toList(); return Background( child: Scaffold( @@ -65,80 +64,84 @@ class _ChooseFromStackViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: walletIds.isEmpty - ? Column( - children: [ - RoundedWhiteContainer( - child: Center( - child: Text( - "No ${coin.ticker.toUpperCase()} wallets", - style: STextStyles.itemSubtitle(context), - ), - ), - ), - ], - ) - : ListView.builder( - itemCount: walletIds.length, - itemBuilder: (context, index) { - final walletId = walletIds[index]; - - return Padding( - padding: const EdgeInsets.symmetric(vertical: 5.0), - child: RawMaterialButton( - splashColor: Theme.of(context) - .extension()! - .highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: + walletIds.isEmpty + ? Column( + children: [ + RoundedWhiteContainer( + child: Center( + child: Text( + "No ${coin.ticker.toUpperCase()} wallets", + style: STextStyles.itemSubtitle(context), + ), ), ), - padding: const EdgeInsets.all(0), - // color: Theme.of(context).extension()!.popupBG, - elevation: 0, - onPressed: () async { - if (mounted) { - Navigator.of(context).pop(walletId); - } - }, - child: RoundedWhiteContainer( - // color: Colors.transparent, - child: Row( - children: [ - WalletInfoCoinIcon(coin: coin), - const SizedBox( - width: 12, + ], + ) + : ListView.builder( + itemCount: walletIds.length, + itemBuilder: (context, index) { + final walletId = walletIds[index]; + + return Padding( + padding: const EdgeInsets.symmetric(vertical: 5.0), + child: RawMaterialButton( + splashColor: + Theme.of( + context, + ).extension()!.highlight, + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - Expanded( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - ref.watch(pWalletName(walletId)), - style: STextStyles.titleBold12(context), - overflow: TextOverflow.ellipsis, + ), + padding: const EdgeInsets.all(0), + // color: Theme.of(context).extension()!.popupBG, + elevation: 0, + onPressed: () async { + if (mounted) { + Navigator.of(context).pop(walletId); + } + }, + child: RoundedWhiteContainer( + // color: Colors.transparent, + child: Row( + children: [ + WalletInfoCoinIcon(coin: coin), + const SizedBox(width: 12), + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + ref.watch(pWalletName(walletId)), + style: STextStyles.titleBold12( + context, + ), + overflow: TextOverflow.ellipsis, + ), + const SizedBox(height: 2), + WalletInfoRowBalance( + walletId: walletIds[index], + ), + ], ), - const SizedBox( - height: 2, - ), - WalletInfoRowBalance( - walletId: walletIds[index], - ), - ], - ), + ), + ], ), - ], + ), ), - ), - ), - ); - }, - ), + ); + }, + ), + ), ), ), ); diff --git a/lib/pages/exchange_view/confirm_change_now_send.dart b/lib/pages/exchange_view/confirm_change_now_send.dart index d28bc8277..69e77f13c 100644 --- a/lib/pages/exchange_view/confirm_change_now_send.dart +++ b/lib/pages/exchange_view/confirm_change_now_send.dart @@ -295,25 +295,31 @@ class _ConfirmChangeNowSendViewState style: STextStyles.navBarTitle(context), ), ), - body: LayoutBuilder( - builder: (builderContext, constraints) { - return Padding( - padding: const EdgeInsets.only(left: 12, top: 12, right: 12), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: child, + body: SafeArea( + child: LayoutBuilder( + builder: (builderContext, constraints) { + return Padding( + padding: const EdgeInsets.only( + left: 12, + top: 12, + right: 12, + ), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: child, + ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ); diff --git a/lib/pages/exchange_view/edit_trade_note_view.dart b/lib/pages/exchange_view/edit_trade_note_view.dart index db918be65..1406d87e3 100644 --- a/lib/pages/exchange_view/edit_trade_note_view.dart +++ b/lib/pages/exchange_view/edit_trade_note_view.dart @@ -10,6 +10,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; + import '../../providers/exchange/trade_note_service_provider.dart'; import '../../themes/stack_colors.dart'; import '../../utilities/constants.dart'; @@ -79,86 +80,94 @@ class _EditNoteViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(12), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - controller: _noteController, - style: STextStyles.field(context), - focusNode: noteFieldFocusNode, - onChanged: (_) => setState(() {}), - decoration: standardInputDecoration( - "Note", - noteFieldFocusNode, - context, - ).copyWith( - suffixIcon: _noteController.text.isNotEmpty - ? Padding( - padding: - const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _noteController.text = ""; - }); - }, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(12), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: + Util.isDesktop ? false : true, + controller: _noteController, + style: STextStyles.field(context), + focusNode: noteFieldFocusNode, + onChanged: (_) => setState(() {}), + decoration: standardInputDecoration( + "Note", + noteFieldFocusNode, + context, + ).copyWith( + suffixIcon: + _noteController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only( + right: 0, + ), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _noteController.text = + ""; + }); + }, + ), + ], ), - ], - ), - ), - ) - : null, + ), + ) + : null, + ), ), ), - ), - const Spacer(), - TextButton( - onPressed: () async { - await ref.read(tradeNoteServiceProvider).set( - tradeId: widget.tradeId, - note: _noteController.text, - ); - if (mounted) { - Navigator.of(context).pop(); - } - }, - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - child: Text( - "Save", - style: STextStyles.button(context), + const Spacer(), + TextButton( + onPressed: () async { + await ref + .read(tradeNoteServiceProvider) + .set( + tradeId: widget.tradeId, + note: _noteController.text, + ); + if (mounted) { + Navigator.of(context).pop(); + } + }, + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + child: Text( + "Save", + style: STextStyles.button(context), + ), ), - ), - ], + ], + ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart b/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart index 5801cf869..5c51ac134 100644 --- a/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart +++ b/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart @@ -262,186 +262,191 @@ class _ExchangeCurrencySelectionViewState ), ); }, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: isDesktop ? MainAxisSize.min : MainAxisSize.max, - children: [ - if (!isDesktop) const SizedBox(height: 16), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autofocus: isDesktop, - autocorrect: !isDesktop, - enableSuggestions: !isDesktop, - controller: _searchController, - focusNode: _searchFocusNode, - onChanged: (value) => setState(() => _searchString = value), - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Search", - _searchFocusNode, - context, - desktopMed: isDesktop, - ).copyWith( - prefixIcon: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 16, - ), - child: SvgPicture.asset( - Assets.svg.search, - width: 16, - height: 16, + child: SafeArea( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: isDesktop ? MainAxisSize.min : MainAxisSize.max, + children: [ + if (!isDesktop) const SizedBox(height: 16), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autofocus: isDesktop, + autocorrect: !isDesktop, + enableSuggestions: !isDesktop, + controller: _searchController, + focusNode: _searchFocusNode, + onChanged: (value) => setState(() => _searchString = value), + style: STextStyles.field(context), + decoration: standardInputDecoration( + "Search", + _searchFocusNode, + context, + desktopMed: isDesktop, + ).copyWith( + prefixIcon: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 16, + ), + child: SvgPicture.asset( + Assets.svg.search, + width: 16, + height: 16, + ), ), - ), - suffixIcon: - _searchController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _searchController.text = ""; - _searchString = ""; - }); - }, - ), - ], + suffixIcon: + _searchController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _searchController.text = ""; + _searchString = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, + ), ), ), - ), - const SizedBox(height: 20), - Flexible( - child: Builder( - builder: (context) { - final coins = AppConfig.coins.where( - (e) => - e.ticker.toLowerCase() != - widget.pairedTicker?.toLowerCase(), - ); - - final items = filter(_searchString); - - final walletCoins = - items - .where( - (currency) => - coins - .where( - (coin) => - coin.ticker.toLowerCase() == - currency.ticker.toLowerCase(), - ) - .isNotEmpty, - ) - .toList(); - - // sort alphabetically by name - items.sort((a, b) => a.name.compareTo(b.name)); - - // reverse sort walletCoins to prepare for next step - walletCoins.sort((a, b) => b.name.compareTo(a.name)); - - // insert wallet coins at beginning - for (final c in walletCoins) { - items.remove(c); - items.insert(0, c); - } - - return RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: ListView.builder( - shrinkWrap: true, - primary: isDesktop ? false : null, - itemCount: items.length, - itemBuilder: (builderContext, index) { - final bool hasImageUrl = items[index].image.startsWith( - "http", - ); - return Padding( - padding: const EdgeInsets.symmetric(vertical: 4), - child: GestureDetector( - onTap: () { - Navigator.of(context).pop(items[index]); - }, - child: RoundedWhiteContainer( - child: Row( - children: [ - SizedBox( - width: 24, - height: 24, - child: - AppConfig.isStackCoin(items[index].ticker) - ? CoinIconForTicker( - ticker: items[index].ticker, - size: 24, - ) - // ? getIconForTicker( - // items[index].ticker, - // size: 24, - // ) - : hasImageUrl - ? SvgPicture.network( - items[index].image, - width: 24, - height: 24, - placeholderBuilder: - (_) => const LoadingIndicator(), - ) - : const SizedBox( - width: 24, - height: 24, + const SizedBox(height: 20), + Flexible( + child: Builder( + builder: (context) { + final coins = AppConfig.coins.where( + (e) => + e.ticker.toLowerCase() != + widget.pairedTicker?.toLowerCase(), + ); + + final items = filter(_searchString); + + final walletCoins = + items + .where( + (currency) => + coins + .where( + (coin) => + coin.ticker.toLowerCase() == + currency.ticker.toLowerCase(), + ) + .isNotEmpty, + ) + .toList(); + + // sort alphabetically by name + items.sort((a, b) => a.name.compareTo(b.name)); + + // reverse sort walletCoins to prepare for next step + walletCoins.sort((a, b) => b.name.compareTo(a.name)); + + // insert wallet coins at beginning + for (final c in walletCoins) { + items.remove(c); + items.insert(0, c); + } + + return RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: ListView.builder( + shrinkWrap: true, + primary: isDesktop ? false : null, + itemCount: items.length, + itemBuilder: (builderContext, index) { + final bool hasImageUrl = items[index].image.startsWith( + "http", + ); + return Padding( + padding: const EdgeInsets.symmetric(vertical: 4), + child: GestureDetector( + onTap: () { + Navigator.of(context).pop(items[index]); + }, + child: RoundedWhiteContainer( + child: Row( + children: [ + SizedBox( + width: 24, + height: 24, + child: + AppConfig.isStackCoin( + items[index].ticker, + ) + ? CoinIconForTicker( + ticker: items[index].ticker, + size: 24, + ) + // ? getIconForTicker( + // items[index].ticker, + // size: 24, + // ) + : hasImageUrl + ? SvgPicture.network( + items[index].image, + width: 24, + height: 24, + placeholderBuilder: + (_) => + const LoadingIndicator(), + ) + : const SizedBox( + width: 24, + height: 24, + ), + ), + const SizedBox(width: 10), + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + items[index].name, + style: STextStyles.largeMedium14( + context, ), - ), - const SizedBox(width: 10), - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - items[index].name, - style: STextStyles.largeMedium14( - context, ), - ), - const SizedBox(height: 2), - Text( - items[index].ticker.toUpperCase(), - style: STextStyles.smallMed12( - context, - ).copyWith( - color: - Theme.of(context) - .extension()! - .textSubtitle1, + const SizedBox(height: 2), + Text( + items[index].ticker.toUpperCase(), + style: STextStyles.smallMed12( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textSubtitle1, + ), ), - ), - ], + ], + ), ), - ), - ], + ], + ), ), ), - ), - ); - }, - ), - ); - }, + ); + }, + ), + ); + }, + ), ), - ), - ], + ], + ), ), ); } diff --git a/lib/pages/exchange_view/exchange_step_views/step_1_view.dart b/lib/pages/exchange_view/exchange_step_views/step_1_view.dart index 8e582dab9..96c168a8d 100644 --- a/lib/pages/exchange_view/exchange_step_views/step_1_view.dart +++ b/lib/pages/exchange_view/exchange_step_views/step_1_view.dart @@ -66,159 +66,157 @@ class _Step1ViewState extends State { } }, ), - title: Text( - "Swap", - style: STextStyles.navBarTitle(context), - ), + title: Text("Swap", style: STextStyles.navBarTitle(context)), ), - body: LayoutBuilder( - builder: (context, constraints) { - final width = MediaQuery.of(context).size.width - 32; - return Padding( - padding: const EdgeInsets.all(12), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - StepRow( - count: 4, - current: 0, - width: width, - ), - const SizedBox( - height: 14, - ), - Text( - "Confirm amount", - style: STextStyles.pageTitleH1(context), - ), - const SizedBox( - height: 8, - ), - Text( - "Network fees and other exchange charges are included in the rate.", - style: STextStyles.itemSubtitle(context), - ), - const SizedBox( - height: 24, - ), - RoundedWhiteContainer( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "You send", - style: STextStyles.itemSubtitle(context) - .copyWith( - color: Theme.of(context) - .extension()! - .infoItemText, + body: SafeArea( + child: LayoutBuilder( + builder: (context, constraints) { + final width = MediaQuery.of(context).size.width - 32; + return Padding( + padding: const EdgeInsets.all(12), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + StepRow(count: 4, current: 0, width: width), + const SizedBox(height: 14), + Text( + "Confirm amount", + style: STextStyles.pageTitleH1(context), + ), + const SizedBox(height: 8), + Text( + "Network fees and other exchange charges are included in the rate.", + style: STextStyles.itemSubtitle(context), + ), + const SizedBox(height: 24), + RoundedWhiteContainer( + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "You send", + style: STextStyles.itemSubtitle( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .infoItemText, + ), ), - ), - Text( - "${model.sendAmount.toStringAsFixed(8)} ${model.sendTicker.toUpperCase()}", - style: STextStyles.itemSubtitle12(context) - .copyWith( - color: Theme.of(context) - .extension()! - .infoItemText, + Text( + "${model.sendAmount.toStringAsFixed(8)} ${model.sendTicker.toUpperCase()}", + style: STextStyles.itemSubtitle12( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .infoItemText, + ), ), - ), - ], + ], + ), ), - ), - const SizedBox( - height: 12, - ), - RoundedWhiteContainer( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "You receive", - style: STextStyles.itemSubtitle(context) - .copyWith( - color: Theme.of(context) - .extension()! - .infoItemText, + const SizedBox(height: 12), + RoundedWhiteContainer( + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "You receive", + style: STextStyles.itemSubtitle( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .infoItemText, + ), ), - ), - Text( - "~${model.receiveAmount.toStringAsFixed(8)} ${model.receiveTicker.toUpperCase()}", - style: STextStyles.itemSubtitle12(context) - .copyWith( - color: Theme.of(context) - .extension()! - .infoItemText, + Text( + "~${model.receiveAmount.toStringAsFixed(8)} ${model.receiveTicker.toUpperCase()}", + style: STextStyles.itemSubtitle12( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .infoItemText, + ), ), - ), - ], + ], + ), ), - ), - const SizedBox( - height: 12, - ), - RoundedWhiteContainer( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - model.rateType == ExchangeRateType.estimated - ? "Estimated rate" - : "Fixed rate", - style: STextStyles.itemSubtitle(context) - .copyWith( - color: Theme.of(context) - .extension()! - .infoItemLabel, + const SizedBox(height: 12), + RoundedWhiteContainer( + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + model.rateType == ExchangeRateType.estimated + ? "Estimated rate" + : "Fixed rate", + style: STextStyles.itemSubtitle( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .infoItemLabel, + ), ), - ), - Text( - model.rateInfo, - style: STextStyles.itemSubtitle12(context) - .copyWith( - color: Theme.of(context) - .extension()! - .infoItemText, + Text( + model.rateInfo, + style: STextStyles.itemSubtitle12( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .infoItemText, + ), ), - ), - ], + ], + ), ), - ), - const SizedBox( - height: 12, - ), - const Spacer(), - TextButton( - onPressed: () { - Navigator.of(context).pushNamed( - Step2View.routeName, - arguments: model, - ); - }, - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - child: Text( - "Next", - style: STextStyles.button(context), + const SizedBox(height: 12), + const Spacer(), + TextButton( + onPressed: () { + Navigator.of(context).pushNamed( + Step2View.routeName, + arguments: model, + ); + }, + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + child: Text( + "Next", + style: STextStyles.button(context), + ), ), - ), - ], + ], + ), ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ); diff --git a/lib/pages/exchange_view/exchange_step_views/step_2_view.dart b/lib/pages/exchange_view/exchange_step_views/step_2_view.dart index 951c211b9..618bafb05 100644 --- a/lib/pages/exchange_view/exchange_step_views/step_2_view.dart +++ b/lib/pages/exchange_view/exchange_step_views/step_2_view.dart @@ -85,7 +85,8 @@ class _Step2ViewState extends ConsumerState { model.refundAddress = _refundController.text; setState(() { - enableNext = _toController.text.isNotEmpty && + enableNext = + _toController.text.isNotEmpty && _refundController.text.isNotEmpty; }); } else { @@ -93,7 +94,8 @@ class _Step2ViewState extends ConsumerState { model.refundAddress = _refundController.text; setState(() { - enableNext = _toController.text.isNotEmpty && + enableNext = + _toController.text.isNotEmpty && _refundController.text.isNotEmpty; }); } @@ -121,7 +123,8 @@ class _Step2ViewState extends ConsumerState { model.recipientAddress = _toController.text; setState(() { - enableNext = _toController.text.isNotEmpty && + enableNext = + _toController.text.isNotEmpty && (_refundController.text.isNotEmpty || !ref.read(efExchangeProvider).supportsRefundAddress); }); @@ -130,7 +133,8 @@ class _Step2ViewState extends ConsumerState { model.recipientAddress = _toController.text; setState(() { - enableNext = _toController.text.isNotEmpty && + enableNext = + _toController.text.isNotEmpty && (_refundController.text.isNotEmpty || !!ref.read(efExchangeProvider).supportsRefundAddress); }); @@ -165,9 +169,9 @@ class _Step2ViewState extends ConsumerState { .getWallet(tuple.item1) .getCurrentReceivingAddress() .then((value) { - _toController.text = value!.value; - model.recipientAddress = _toController.text; - }); + _toController.text = value!.value; + model.recipientAddress = _toController.text; + }); } else { if (model.sendTicker.toUpperCase() == tuple.item2.ticker.toUpperCase()) { @@ -176,9 +180,9 @@ class _Step2ViewState extends ConsumerState { .getWallet(tuple.item1) .getCurrentReceivingAddress() .then((value) { - _refundController.text = value!.value; - model.refundAddress = _refundController.text; - }); + _refundController.text = value!.value; + model.refundAddress = _refundController.text; + }); } } } @@ -216,303 +220,45 @@ class _Step2ViewState extends ConsumerState { } }, ), - title: Text( - "Swap", - style: STextStyles.navBarTitle(context), - ), + title: Text("Swap", style: STextStyles.navBarTitle(context)), ), - body: LayoutBuilder( - builder: (context, constraints) { - final width = MediaQuery.of(context).size.width - 32; - return Padding( - padding: const EdgeInsets.all(12), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - StepRow( - count: 4, - current: 1, - width: width, - ), - const SizedBox( - height: 14, - ), - Text( - "Exchange details", - style: STextStyles.pageTitleH1(context), - ), - const SizedBox( - height: 8, - ), - Text( - "Enter your recipient and refund addresses", - style: STextStyles.itemSubtitle(context), - ), - const SizedBox( - height: 24, - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Recipient Wallet", - style: STextStyles.smallMed12(context), - ), - if (AppConfig.isStackCoin(model.receiveTicker)) - CustomTextButton( - text: "Choose from ${AppConfig.prefix}", - onTap: () { - try { - final coin = AppConfig.coins.firstWhere( - (e) => - e.ticker.toLowerCase() == - model.receiveTicker.toLowerCase(), - ); - - Navigator.of(context) - .pushNamed( - ChooseFromStackView.routeName, - arguments: coin, - ) - .then((value) async { - if (value is String) { - final wallet = ref - .read(pWallets) - .getWallet(value); - - _toController.text = wallet.info.name; - model.recipientAddress = (await wallet - .getCurrentReceivingAddress()) - ?.value ?? - wallet - .info.cachedReceivingAddress; - - setState(() { - enableNext = - _toController.text.isNotEmpty && - (_refundController - .text.isNotEmpty || - !supportsRefund); - }); - } - }); - } catch (e, s) { - Logging.instance.e( - "", - error: e, - stackTrace: s, - ); - } - }, - ), - ], - ), - const SizedBox( - height: 4, - ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - onTap: () {}, - key: const Key( - "recipientExchangeStep2ViewAddressFieldKey", - ), - controller: _toController, - readOnly: false, - autocorrect: false, - enableSuggestions: false, - // inputFormatters: [ - // FilteringTextInputFormatter.allow(RegExp("[a-zA-Z0-9]{34}")), - // ], - toolbarOptions: const ToolbarOptions( - copy: false, - cut: false, - paste: true, - selectAll: false, - ), - focusNode: _toFocusNode, - style: STextStyles.field(context), - onChanged: (value) { - model.recipientAddress = _toController.text; - setState(() { - enableNext = _toController.text.isNotEmpty && - (_refundController.text.isNotEmpty || - !supportsRefund); - }); - }, - decoration: standardInputDecoration( - "Enter the ${model.receiveTicker.toUpperCase()} payout address", - _toFocusNode, - context, - ).copyWith( - contentPadding: const EdgeInsets.only( - left: 16, - top: 6, - bottom: 8, - right: 5, - ), - suffixIcon: Padding( - padding: _toController.text.isEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceAround, - children: [ - _toController.text.isNotEmpty - ? TextFieldIconButton( - key: const Key( - "sendViewClearAddressFieldButtonKey", - ), - onTap: () { - _toController.text = ""; - model.recipientAddress = - _toController.text; - - setState(() { - enableNext = _toController - .text.isNotEmpty && - (_refundController.text - .isNotEmpty || - !supportsRefund); - }); - }, - child: const XIcon(), - ) - : TextFieldIconButton( - key: const Key( - "sendViewPasteAddressFieldButtonKey", - ), - onTap: () async { - final ClipboardData? data = - await clipboard.getData( - Clipboard.kTextPlain, - ); - if (data?.text != null && - data!.text!.isNotEmpty) { - final content = - data.text!.trim(); - - _toController.text = - content; - model.recipientAddress = - _toController.text; - - setState(() { - enableNext = _toController - .text - .isNotEmpty && - (_refundController - .text - .isNotEmpty || - !supportsRefund); - }); - } - }, - child: - _toController.text.isEmpty - ? const ClipboardIcon() - : const XIcon(), - ), - if (_toController.text.isEmpty) - TextFieldIconButton( - key: const Key( - "sendViewAddressBookButtonKey", - ), - onTap: () { - ref - .read( - exchangeFlowIsActiveStateProvider - .state, - ) - .state = true; - Navigator.of(context) - .pushNamed( - AddressBookView.routeName, - ) - .then((_) { - ref - .read( - exchangeFlowIsActiveStateProvider - .state, - ) - .state = false; - - final address = ref - .read( - exchangeFromAddressBookAddressStateProvider - .state, - ) - .state; - if (address.isNotEmpty) { - _toController.text = address; - model.recipientAddress = - _toController.text; - ref - .read( - exchangeFromAddressBookAddressStateProvider - .state, - ) - .state = ""; - } - setState(() { - enableNext = _toController - .text.isNotEmpty && - (_refundController.text - .isNotEmpty || - !supportsRefund); - }); - }); - }, - child: const AddressBookIcon(), - ), - if (_toController.text.isEmpty) - TextFieldIconButton( - key: const Key( - "sendViewScanQrButtonKey", - ), - onTap: _onToQrTapped, - child: const QrCodeIcon(), - ), - ], - ), - ), - ), - ), + body: SafeArea( + child: LayoutBuilder( + builder: (context, constraints) { + final width = MediaQuery.of(context).size.width - 32; + return Padding( + padding: const EdgeInsets.all(12), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + StepRow(count: 4, current: 1, width: width), + const SizedBox(height: 14), + Text( + "Exchange details", + style: STextStyles.pageTitleH1(context), ), - ), - const SizedBox( - height: 6, - ), - RoundedWhiteContainer( - child: Text( - "This is the wallet where your ${model.receiveTicker.toUpperCase()} will be sent to.", - style: STextStyles.label(context), + const SizedBox(height: 8), + Text( + "Enter your recipient and refund addresses", + style: STextStyles.itemSubtitle(context), ), - ), - const SizedBox( - height: 24, - ), - if (supportsRefund) + const SizedBox(height: 24), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - "Refund Wallet (required)", + "Recipient Wallet", style: STextStyles.smallMed12(context), ), - if (AppConfig.isStackCoin(model.sendTicker)) + if (AppConfig.isStackCoin(model.receiveTicker)) CustomTextButton( text: "Choose from ${AppConfig.prefix}", onTap: () { @@ -520,36 +266,45 @@ class _Step2ViewState extends ConsumerState { final coin = AppConfig.coins.firstWhere( (e) => e.ticker.toLowerCase() == - model.sendTicker.toLowerCase(), + model.receiveTicker.toLowerCase(), ); Navigator.of(context) .pushNamed( - ChooseFromStackView.routeName, - arguments: coin, - ) + ChooseFromStackView.routeName, + arguments: coin, + ) .then((value) async { - if (value is String) { - final wallet = ref - .read(pWallets) - .getWallet(value); - - _refundController.text = - wallet.info.name; - model.refundAddress = (await wallet - .getCurrentReceivingAddress())! - .value; - } - setState(() { - enableNext = - _toController.text.isNotEmpty && - _refundController - .text.isNotEmpty; - }); - }); + if (value is String) { + final wallet = ref + .read(pWallets) + .getWallet(value); + + _toController.text = + wallet.info.name; + model.recipientAddress = + (await wallet + .getCurrentReceivingAddress()) + ?.value ?? + wallet + .info + .cachedReceivingAddress; + + setState(() { + enableNext = + _toController + .text + .isNotEmpty && + (_refundController + .text + .isNotEmpty || + !supportsRefund); + }); + } + }); } catch (e, s) { - Logging.instance.i( - "$e\n$s", + Logging.instance.e( + "", error: e, stackTrace: s, ); @@ -558,20 +313,17 @@ class _Step2ViewState extends ConsumerState { ), ], ), - if (supportsRefund) - const SizedBox( - height: 4, - ), - if (supportsRefund) + const SizedBox(height: 4), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), child: TextField( + onTap: () {}, key: const Key( - "refundExchangeStep2ViewAddressFieldKey", + "recipientExchangeStep2ViewAddressFieldKey", ), - controller: _refundController, + controller: _toController, readOnly: false, autocorrect: false, enableSuggestions: false, @@ -584,19 +336,20 @@ class _Step2ViewState extends ConsumerState { paste: true, selectAll: false, ), - focusNode: _refundFocusNode, + focusNode: _toFocusNode, style: STextStyles.field(context), onChanged: (value) { - model.refundAddress = _refundController.text; + model.recipientAddress = _toController.text; setState(() { enableNext = _toController.text.isNotEmpty && - _refundController.text.isNotEmpty; + (_refundController.text.isNotEmpty || + !supportsRefund); }); }, decoration: standardInputDecoration( - "Enter ${model.sendTicker.toUpperCase()} refund address", - _refundFocusNode, + "Enter the ${model.receiveTicker.toUpperCase()} payout address", + _toFocusNode, context, ).copyWith( contentPadding: const EdgeInsets.only( @@ -606,16 +359,272 @@ class _Step2ViewState extends ConsumerState { right: 5, ), suffixIcon: Padding( - padding: _refundController.text.isEmpty - ? const EdgeInsets.only(right: 16) - : const EdgeInsets.only(right: 0), + padding: + _toController.text.isEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), child: UnconstrainedBox( child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ - _refundController.text.isNotEmpty + _toController.text.isNotEmpty ? TextFieldIconButton( + key: const Key( + "sendViewClearAddressFieldButtonKey", + ), + onTap: () { + _toController.text = ""; + model.recipientAddress = + _toController.text; + + setState(() { + enableNext = + _toController + .text + .isNotEmpty && + (_refundController + .text + .isNotEmpty || + !supportsRefund); + }); + }, + child: const XIcon(), + ) + : TextFieldIconButton( + key: const Key( + "sendViewPasteAddressFieldButtonKey", + ), + onTap: () async { + final ClipboardData? data = + await clipboard.getData( + Clipboard.kTextPlain, + ); + if (data?.text != null && + data!.text!.isNotEmpty) { + final content = + data.text!.trim(); + + _toController.text = + content; + model.recipientAddress = + _toController.text; + + setState(() { + enableNext = + _toController + .text + .isNotEmpty && + (_refundController + .text + .isNotEmpty || + !supportsRefund); + }); + } + }, + child: + _toController.text.isEmpty + ? const ClipboardIcon() + : const XIcon(), + ), + if (_toController.text.isEmpty) + TextFieldIconButton( + key: const Key( + "sendViewAddressBookButtonKey", + ), + onTap: () { + ref + .read( + exchangeFlowIsActiveStateProvider + .state, + ) + .state = true; + Navigator.of( + context, + ).pushNamed(AddressBookView.routeName).then(( + _, + ) { + ref + .read( + exchangeFlowIsActiveStateProvider + .state, + ) + .state = false; + + final address = + ref + .read( + exchangeFromAddressBookAddressStateProvider + .state, + ) + .state; + if (address.isNotEmpty) { + _toController.text = + address; + model.recipientAddress = + _toController.text; + ref + .read( + exchangeFromAddressBookAddressStateProvider + .state, + ) + .state = ""; + } + setState(() { + enableNext = + _toController + .text + .isNotEmpty && + (_refundController + .text + .isNotEmpty || + !supportsRefund); + }); + }); + }, + child: const AddressBookIcon(), + ), + if (_toController.text.isEmpty) + TextFieldIconButton( + key: const Key( + "sendViewScanQrButtonKey", + ), + onTap: _onToQrTapped, + child: const QrCodeIcon(), + ), + ], + ), + ), + ), + ), + ), + ), + const SizedBox(height: 6), + RoundedWhiteContainer( + child: Text( + "This is the wallet where your ${model.receiveTicker.toUpperCase()} will be sent to.", + style: STextStyles.label(context), + ), + ), + const SizedBox(height: 24), + if (supportsRefund) + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Refund Wallet (required)", + style: STextStyles.smallMed12(context), + ), + if (AppConfig.isStackCoin(model.sendTicker)) + CustomTextButton( + text: "Choose from ${AppConfig.prefix}", + onTap: () { + try { + final coin = AppConfig.coins + .firstWhere( + (e) => + e.ticker.toLowerCase() == + model.sendTicker + .toLowerCase(), + ); + + Navigator.of(context) + .pushNamed( + ChooseFromStackView.routeName, + arguments: coin, + ) + .then((value) async { + if (value is String) { + final wallet = ref + .read(pWallets) + .getWallet(value); + + _refundController.text = + wallet.info.name; + model.refundAddress = + (await wallet + .getCurrentReceivingAddress())! + .value; + } + setState(() { + enableNext = + _toController + .text + .isNotEmpty && + _refundController + .text + .isNotEmpty; + }); + }); + } catch (e, s) { + Logging.instance.i( + "$e\n$s", + error: e, + stackTrace: s, + ); + } + }, + ), + ], + ), + if (supportsRefund) const SizedBox(height: 4), + if (supportsRefund) + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + key: const Key( + "refundExchangeStep2ViewAddressFieldKey", + ), + controller: _refundController, + readOnly: false, + autocorrect: false, + enableSuggestions: false, + // inputFormatters: [ + // FilteringTextInputFormatter.allow(RegExp("[a-zA-Z0-9]{34}")), + // ], + toolbarOptions: const ToolbarOptions( + copy: false, + cut: false, + paste: true, + selectAll: false, + ), + focusNode: _refundFocusNode, + style: STextStyles.field(context), + onChanged: (value) { + model.refundAddress = + _refundController.text; + setState(() { + enableNext = + _toController.text.isNotEmpty && + _refundController.text.isNotEmpty; + }); + }, + decoration: standardInputDecoration( + "Enter ${model.sendTicker.toUpperCase()} refund address", + _refundFocusNode, + context, + ).copyWith( + contentPadding: const EdgeInsets.only( + left: 16, + top: 6, + bottom: 8, + right: 5, + ), + suffixIcon: Padding( + padding: + _refundController.text.isEmpty + ? const EdgeInsets.only(right: 16) + : const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceAround, + children: [ + _refundController.text.isNotEmpty + ? TextFieldIconButton( key: const Key( "sendViewClearAddressFieldButtonKey", ), @@ -625,27 +634,30 @@ class _Step2ViewState extends ConsumerState { _refundController.text; setState(() { - enableNext = _toController + enableNext = + _toController .text .isNotEmpty && _refundController - .text.isNotEmpty; + .text + .isNotEmpty; }); }, child: const XIcon(), ) - : TextFieldIconButton( + : TextFieldIconButton( key: const Key( "sendViewPasteAddressFieldButtonKey", ), onTap: () async { final ClipboardData? data = await clipboard.getData( - Clipboard.kTextPlain, - ); + Clipboard.kTextPlain, + ); if (data?.text != null && data! - .text!.isNotEmpty) { + .text! + .isNotEmpty) { final content = data.text!.trim(); @@ -656,7 +668,8 @@ class _Step2ViewState extends ConsumerState { .text; setState(() { - enableNext = _toController + enableNext = + _toController .text .isNotEmpty && _refundController @@ -665,131 +678,139 @@ class _Step2ViewState extends ConsumerState { }); } }, - child: _refundController - .text.isEmpty - ? const ClipboardIcon() - : const XIcon(), + child: + _refundController + .text + .isEmpty + ? const ClipboardIcon() + : const XIcon(), ), - if (_refundController.text.isEmpty) - TextFieldIconButton( - key: const Key( - "sendViewAddressBookButtonKey", - ), - onTap: () { - ref - .read( - exchangeFlowIsActiveStateProvider - .state, - ) - .state = true; - Navigator.of(context) - .pushNamed( - AddressBookView.routeName, - ) - .then((_) { + if (_refundController.text.isEmpty) + TextFieldIconButton( + key: const Key( + "sendViewAddressBookButtonKey", + ), + onTap: () { ref .read( exchangeFlowIsActiveStateProvider .state, ) - .state = false; - final address = ref - .read( - exchangeFromAddressBookAddressStateProvider - .state, + .state = true; + Navigator.of(context) + .pushNamed( + AddressBookView + .routeName, ) - .state; - if (address.isNotEmpty) { - _refundController.text = - address; - model.refundAddress = - _refundController.text; - } - setState(() { - enableNext = _toController - .text.isNotEmpty && - _refundController - .text.isNotEmpty; - }); - }); - }, - child: const AddressBookIcon(), - ), - if (_refundController.text.isEmpty) - TextFieldIconButton( - key: const Key( - "sendViewScanQrButtonKey", + .then((_) { + ref + .read( + exchangeFlowIsActiveStateProvider + .state, + ) + .state = false; + final address = + ref + .read( + exchangeFromAddressBookAddressStateProvider + .state, + ) + .state; + if (address + .isNotEmpty) { + _refundController + .text = address; + model.refundAddress = + _refundController + .text; + } + setState(() { + enableNext = + _toController + .text + .isNotEmpty && + _refundController + .text + .isNotEmpty; + }); + }); + }, + child: const AddressBookIcon(), ), - onTap: _onRefundQrTapped, - child: const QrCodeIcon(), - ), - ], + if (_refundController.text.isEmpty) + TextFieldIconButton( + key: const Key( + "sendViewScanQrButtonKey", + ), + onTap: _onRefundQrTapped, + child: const QrCodeIcon(), + ), + ], + ), ), ), ), ), ), - ), - if (supportsRefund) - const SizedBox( - height: 6, - ), - if (supportsRefund) - RoundedWhiteContainer( - child: Text( - "In case something goes wrong during the exchange, we might need a refund address so we can return your coins back to you.", - style: STextStyles.label(context), + if (supportsRefund) const SizedBox(height: 6), + if (supportsRefund) + RoundedWhiteContainer( + child: Text( + "In case something goes wrong during the exchange, we might need a refund address so we can return your coins back to you.", + style: STextStyles.label(context), + ), ), - ), - const SizedBox( - height: 16, - ), - const Spacer(), - Row( - children: [ - Expanded( - child: TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - child: Text( - "Back", - style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .buttonTextSecondary, + const SizedBox(height: 16), + const Spacer(), + Row( + children: [ + Expanded( + child: TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle( + context, + ), + child: Text( + "Back", + style: STextStyles.button( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .buttonTextSecondary, + ), ), ), ), - ), - const SizedBox( - width: 16, - ), - Expanded( - child: PrimaryButton( - label: "Next", - enabled: enableNext, - onPressed: () { - Navigator.of(context).pushNamed( - Step3View.routeName, - arguments: model, - ); - }, + const SizedBox(width: 16), + Expanded( + child: PrimaryButton( + label: "Next", + enabled: enableNext, + onPressed: () { + Navigator.of(context).pushNamed( + Step3View.routeName, + arguments: model, + ); + }, + ), ), - ), - ], - ), - ], + ], + ), + ], + ), ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ); diff --git a/lib/pages/exchange_view/exchange_step_views/step_3_view.dart b/lib/pages/exchange_view/exchange_step_views/step_3_view.dart index 92c713acb..46457ae2a 100644 --- a/lib/pages/exchange_view/exchange_step_views/step_3_view.dart +++ b/lib/pages/exchange_view/exchange_step_views/step_3_view.dart @@ -81,285 +81,293 @@ class _Step3ViewState extends ConsumerState { ), title: Text("Swap", style: STextStyles.navBarTitle(context)), ), - body: LayoutBuilder( - builder: (context, constraints) { - final width = MediaQuery.of(context).size.width - 32; - return Padding( - padding: const EdgeInsets.all(12), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - StepRow(count: 4, current: 2, width: width), - const SizedBox(height: 14), - Text( - "Confirm exchange details", - style: STextStyles.pageTitleH1(context), - ), - const SizedBox(height: 24), - RoundedWhiteContainer( - child: Row( - children: [ - Text( - "You send", - style: STextStyles.itemSubtitle(context), - ), - const Spacer(), - Text( - "${model.sendAmount.toString()} ${model.sendTicker.toUpperCase()}", - style: STextStyles.itemSubtitle12(context), - ), - ], + body: SafeArea( + child: LayoutBuilder( + builder: (context, constraints) { + final width = MediaQuery.of(context).size.width - 32; + return Padding( + padding: const EdgeInsets.all(12), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + StepRow(count: 4, current: 2, width: width), + const SizedBox(height: 14), + Text( + "Confirm exchange details", + style: STextStyles.pageTitleH1(context), ), - ), - const SizedBox(height: 8), - RoundedWhiteContainer( - child: Row( - children: [ - Text( - "You receive", - style: STextStyles.itemSubtitle(context), - ), - const Spacer(), - Text( - "${model.receiveAmount.toString()} ${model.receiveTicker.toUpperCase()}", - style: STextStyles.itemSubtitle12(context), - ), - ], + const SizedBox(height: 24), + RoundedWhiteContainer( + child: Row( + children: [ + Text( + "You send", + style: STextStyles.itemSubtitle(context), + ), + const Spacer(), + Text( + "${model.sendAmount.toString()} ${model.sendTicker.toUpperCase()}", + style: STextStyles.itemSubtitle12(context), + ), + ], + ), ), - ), - const SizedBox(height: 8), - RoundedWhiteContainer( - child: Row( - children: [ - Text( - "Estimated rate", - style: STextStyles.itemSubtitle(context), - ), - const Spacer(), - Text( - model.rateInfo, - style: STextStyles.itemSubtitle12(context), - ), - ], + const SizedBox(height: 8), + RoundedWhiteContainer( + child: Row( + children: [ + Text( + "You receive", + style: STextStyles.itemSubtitle(context), + ), + const Spacer(), + Text( + "${model.receiveAmount.toString()} ${model.receiveTicker.toUpperCase()}", + style: STextStyles.itemSubtitle12(context), + ), + ], + ), ), - ), - const SizedBox(height: 8), - RoundedWhiteContainer( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Recipient ${model.receiveTicker.toUpperCase()} address", - style: STextStyles.itemSubtitle(context), - ), - const SizedBox(height: 4), - Text( - model.recipientAddress!, - style: STextStyles.itemSubtitle12(context), - ), - ], + const SizedBox(height: 8), + RoundedWhiteContainer( + child: Row( + children: [ + Text( + "Estimated rate", + style: STextStyles.itemSubtitle(context), + ), + const Spacer(), + Text( + model.rateInfo, + style: STextStyles.itemSubtitle12(context), + ), + ], + ), ), - ), - if (supportsRefund) const SizedBox(height: 8), - if (supportsRefund) + const SizedBox(height: 8), RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Refund ${model.sendTicker.toUpperCase()} address", + "Recipient ${model.receiveTicker.toUpperCase()} address", style: STextStyles.itemSubtitle(context), ), const SizedBox(height: 4), Text( - model.refundAddress!, + model.recipientAddress!, style: STextStyles.itemSubtitle12(context), ), ], ), ), - const SizedBox(height: 8), - const Spacer(), - Row( - children: [ - Expanded( - child: TextButton( - onPressed: () { - Navigator.of(context).pop(); - }, - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - child: Text( - "Back", - style: STextStyles.button(context).copyWith( - color: - Theme.of(context) - .extension()! - .buttonTextSecondary, + if (supportsRefund) const SizedBox(height: 8), + if (supportsRefund) + RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Refund ${model.sendTicker.toUpperCase()} address", + style: STextStyles.itemSubtitle(context), ), - ), + const SizedBox(height: 4), + Text( + model.refundAddress!, + style: STextStyles.itemSubtitle12( + context, + ), + ), + ], ), ), - const SizedBox(width: 16), - Expanded( - child: TextButton( - onPressed: () async { - unawaited( - showDialog( - context: context, - barrierDismissible: false, - builder: - (_) => WillPopScope( - onWillPop: () async => false, - child: Container( - color: Theme.of(context) - .extension()! - .overlay - .withOpacity(0.6), - child: - const CustomLoadingOverlay( - message: - "Creating a trade", - eventBus: null, - ), - ), - ), + const SizedBox(height: 8), + const Spacer(), + Row( + children: [ + Expanded( + child: TextButton( + onPressed: () { + Navigator.of(context).pop(); + }, + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle( + context, + ), + child: Text( + "Back", + style: STextStyles.button( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .buttonTextSecondary, ), - ); + ), + ), + ), + const SizedBox(width: 16), + Expanded( + child: TextButton( + onPressed: () async { + unawaited( + showDialog( + context: context, + barrierDismissible: false, + builder: + (_) => WillPopScope( + onWillPop: () async => false, + child: Container( + color: Theme.of(context) + .extension()! + .overlay + .withOpacity(0.6), + child: + const CustomLoadingOverlay( + message: + "Creating a trade", + eventBus: null, + ), + ), + ), + ), + ); - final ExchangeResponse response = - await ref - .read(efExchangeProvider) - .createTrade( - from: model.sendTicker, - fromNetwork: model.sendNetwork, - to: model.receiveTicker, - toNetwork: model.receiveNetwork, - fixedRate: - model.rateType != - ExchangeRateType.estimated, - amount: - model.reversed - ? model.receiveAmount - : model.sendAmount, - addressTo: - model.recipientAddress!, - extraId: null, - addressRefund: - supportsRefund - ? model.refundAddress! - : "", - refundExtraId: "", - estimate: model.estimate, - reversed: model.reversed, - ); + final ExchangeResponse response = + await ref + .read(efExchangeProvider) + .createTrade( + from: model.sendTicker, + fromNetwork: model.sendNetwork, + to: model.receiveTicker, + toNetwork: model.receiveNetwork, + fixedRate: + model.rateType != + ExchangeRateType.estimated, + amount: + model.reversed + ? model.receiveAmount + : model.sendAmount, + addressTo: + model.recipientAddress!, + extraId: null, + addressRefund: + supportsRefund + ? model.refundAddress! + : "", + refundExtraId: "", + estimate: model.estimate, + reversed: model.reversed, + ); - if (response.value == null) { - if (context.mounted) { - Navigator.of(context).pop(); + if (response.value == null) { + if (context.mounted) { + Navigator.of(context).pop(); - // TODO: better errors - String? message; - if (response.exception != null) { - message = - response.exception!.toString(); - if (message.startsWith( - "FormatException:", - ) && - message.contains("")) { + // TODO: better errors + String? message; + if (response.exception != null) { message = - "${ref.read(efExchangeProvider).name} server error"; + response.exception!.toString(); + if (message.startsWith( + "FormatException:", + ) && + message.contains("")) { + message = + "${ref.read(efExchangeProvider).name} server error"; + } } - } - unawaited( - showDialog( - context: context, - barrierDismissible: true, - builder: - (_) => StackDialog( - title: - "Failed to create trade", - message: message ?? "", - ), - ), - ); + unawaited( + showDialog( + context: context, + barrierDismissible: true, + builder: + (_) => StackDialog( + title: + "Failed to create trade", + message: message ?? "", + ), + ), + ); + } + return; } - return; - } - - // save trade to hive - await ref - .read(tradesServiceProvider) - .add( - trade: response.value!, - shouldNotifyListeners: true, - ); - String status = response.value!.status; + // save trade to hive + await ref + .read(tradesServiceProvider) + .add( + trade: response.value!, + shouldNotifyListeners: true, + ); - model.trade = response.value!; + String status = response.value!.status; - // extra info if status is waiting - if (status == "Waiting") { - status += " for deposit"; - } + model.trade = response.value!; - if (mounted) { - Navigator.of(context).pop(); - } + // extra info if status is waiting + if (status == "Waiting") { + status += " for deposit"; + } - unawaited( - NotificationApi.showNotification( - changeNowId: model.trade!.tradeId, - title: status, - body: - "Trade ID ${model.trade!.tradeId}", - walletId: "", - iconAssetName: Assets.svg.arrowRotate, - date: model.trade!.timestamp, - shouldWatchForUpdates: true, - coinName: "coinName", - ), - ); + if (mounted) { + Navigator.of(context).pop(); + } - if (mounted) { unawaited( - Navigator.of(context).pushNamed( - Step4View.routeName, - arguments: model, + NotificationApi.showNotification( + changeNowId: model.trade!.tradeId, + title: status, + body: + "Trade ID ${model.trade!.tradeId}", + walletId: "", + iconAssetName: Assets.svg.arrowRotate, + date: model.trade!.timestamp, + shouldWatchForUpdates: true, + coinName: "coinName", ), ); - } - }, - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - child: Text( - "Next", - style: STextStyles.button(context), + + if (mounted) { + unawaited( + Navigator.of(context).pushNamed( + Step4View.routeName, + arguments: model, + ), + ); + } + }, + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + child: Text( + "Next", + style: STextStyles.button(context), + ), ), ), - ), - ], - ), - ], + ], + ), + ], + ), ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ); diff --git a/lib/pages/exchange_view/exchange_step_views/step_4_view.dart b/lib/pages/exchange_view/exchange_step_views/step_4_view.dart index be9c3ac37..72d2ff241 100644 --- a/lib/pages/exchange_view/exchange_step_views/step_4_view.dart +++ b/lib/pages/exchange_view/exchange_step_views/step_4_view.dart @@ -366,186 +366,136 @@ class _Step4ViewState extends ConsumerState { ), title: Text("Swap", style: STextStyles.navBarTitle(context)), ), - body: LayoutBuilder( - builder: (context, constraints) { - final width = MediaQuery.of(context).size.width - 32; - return Padding( - padding: const EdgeInsets.all(12), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - StepRow(count: 4, current: 3, width: width), - const SizedBox(height: 14), - Text( - "Send ${model.sendTicker.toUpperCase()} to the address below", - style: STextStyles.pageTitleH1(context), - ), - const SizedBox(height: 8), - Text( - "Send ${model.sendTicker.toUpperCase()} to the address below. Once it is received, ${model.trade!.exchangeName} will send the ${model.receiveTicker.toUpperCase()} to the recipient address you provided. You can find this trade details and check its status in the list of trades.", - style: STextStyles.itemSubtitle(context), - ), - const SizedBox(height: 12), - RoundedContainer( - color: - Theme.of( - context, - ).extension()!.warningBackground, - child: RichText( - text: TextSpan( - text: - "You must send at least ${model.sendAmount.toString()} ${model.sendTicker}. ", - style: STextStyles.label700(context).copyWith( - color: - Theme.of(context) - .extension()! - .warningForeground, - ), - children: [ - TextSpan( - text: - "If you send less than ${model.sendAmount.toString()} ${model.sendTicker}, your transaction may not be converted and it may not be refunded.", - style: STextStyles.label( - context, - ).copyWith( - color: - Theme.of(context) - .extension()! - .warningForeground, - ), - ), - ], - ), + body: SafeArea( + child: LayoutBuilder( + builder: (context, constraints) { + final width = MediaQuery.of(context).size.width - 32; + return Padding( + padding: const EdgeInsets.all(12), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + StepRow(count: 4, current: 3, width: width), + const SizedBox(height: 14), + Text( + "Send ${model.sendTicker.toUpperCase()} to the address below", + style: STextStyles.pageTitleH1(context), ), - ), - const SizedBox(height: 8), - RoundedWhiteContainer( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + const SizedBox(height: 8), + Text( + "Send ${model.sendTicker.toUpperCase()} to the address below. Once it is received, ${model.trade!.exchangeName} will send the ${model.receiveTicker.toUpperCase()} to the recipient address you provided. You can find this trade details and check its status in the list of trades.", + style: STextStyles.itemSubtitle(context), + ), + const SizedBox(height: 12), + RoundedContainer( + color: + Theme.of(context) + .extension()! + .warningBackground, + child: RichText( + text: TextSpan( + text: + "You must send at least ${model.sendAmount.toString()} ${model.sendTicker}. ", + style: STextStyles.label700( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .warningForeground, + ), children: [ - Text( - "Amount", - style: STextStyles.itemSubtitle( + TextSpan( + text: + "If you send less than ${model.sendAmount.toString()} ${model.sendTicker}, your transaction may not be converted and it may not be refunded.", + style: STextStyles.label( context, - ), - ), - GestureDetector( - onTap: () async { - final data = ClipboardData( - text: model.sendAmount.toString(), - ); - await clipboard.setData(data); - if (context.mounted) { - unawaited( - showFloatingFlushBar( - type: FlushBarType.info, - message: "Copied to clipboard", - context: context, - ), - ); - } - }, - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.copy, - color: - Theme.of(context) - .extension()! - .infoItemIcons, - width: 10, - ), - const SizedBox(width: 4), - Text( - "Copy", - style: STextStyles.link2(context), - ), - ], + ).copyWith( + color: + Theme.of(context) + .extension()! + .warningForeground, ), ), ], ), - const SizedBox(height: 4), - Text( - "${model.sendAmount.toString()} ${model.sendTicker.toUpperCase()}", - style: STextStyles.itemSubtitle12(context), - ), - ], + ), ), - ), - const SizedBox(height: 8), - RoundedWhiteContainer( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - "Send ${model.sendTicker.toUpperCase()} to this address", - style: STextStyles.itemSubtitle( - context, + const SizedBox(height: 8), + RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Amount", + style: STextStyles.itemSubtitle( + context, + ), ), - ), - GestureDetector( - onTap: () async { - final data = ClipboardData( - text: model.trade!.payInAddress, - ); - await clipboard.setData(data); - if (context.mounted) { - unawaited( - showFloatingFlushBar( - type: FlushBarType.info, - message: "Copied to clipboard", - context: context, - ), + GestureDetector( + onTap: () async { + final data = ClipboardData( + text: model.sendAmount.toString(), ); - } - }, - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.copy, - color: - Theme.of(context) - .extension()! - .infoItemIcons, - width: 10, - ), - const SizedBox(width: 4), - Text( - "Copy", - style: STextStyles.link2(context), - ), - ], + await clipboard.setData(data); + if (context.mounted) { + unawaited( + showFloatingFlushBar( + type: FlushBarType.info, + message: + "Copied to clipboard", + context: context, + ), + ); + } + }, + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.copy, + color: + Theme.of(context) + .extension< + StackColors + >()! + .infoItemIcons, + width: 10, + ), + const SizedBox(width: 4), + Text( + "Copy", + style: STextStyles.link2( + context, + ), + ), + ], + ), ), + ], + ), + const SizedBox(height: 4), + Text( + "${model.sendAmount.toString()} ${model.sendTicker.toUpperCase()}", + style: STextStyles.itemSubtitle12( + context, ), - ], - ), - const SizedBox(height: 4), - Text( - model.trade!.payInAddress, - style: STextStyles.itemSubtitle12(context), - ), - ], + ), + ], + ), ), - ), - const SizedBox(height: 6), - if (model.trade!.payInExtraId.isNotEmpty) + const SizedBox(height: 8), RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -555,7 +505,7 @@ class _Step4ViewState extends ConsumerState { MainAxisAlignment.spaceBetween, children: [ Text( - "Memo", + "Send ${model.sendTicker.toUpperCase()} to this address", style: STextStyles.itemSubtitle( context, ), @@ -563,7 +513,7 @@ class _Step4ViewState extends ConsumerState { GestureDetector( onTap: () async { final data = ClipboardData( - text: model.trade!.payInExtraId, + text: model.trade!.payInAddress, ); await clipboard.setData(data); if (context.mounted) { @@ -603,7 +553,7 @@ class _Step4ViewState extends ConsumerState { ), const SizedBox(height: 4), Text( - model.trade!.payInExtraId, + model.trade!.payInAddress, style: STextStyles.itemSubtitle12( context, ), @@ -611,262 +561,337 @@ class _Step4ViewState extends ConsumerState { ], ), ), - if (model.trade!.payInExtraId.isNotEmpty) const SizedBox(height: 6), - RoundedWhiteContainer( - child: Row( - children: [ - Text( - "Trade ID", - style: STextStyles.itemSubtitle(context), - ), - const Spacer(), - Row( + if (model.trade!.payInExtraId.isNotEmpty) + RoundedWhiteContainer( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Memo", + style: STextStyles.itemSubtitle( + context, + ), + ), + GestureDetector( + onTap: () async { + final data = ClipboardData( + text: model.trade!.payInExtraId, + ); + await clipboard.setData(data); + if (context.mounted) { + unawaited( + showFloatingFlushBar( + type: FlushBarType.info, + message: + "Copied to clipboard", + context: context, + ), + ); + } + }, + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.copy, + color: + Theme.of(context) + .extension< + StackColors + >()! + .infoItemIcons, + width: 10, + ), + const SizedBox(width: 4), + Text( + "Copy", + style: STextStyles.link2( + context, + ), + ), + ], + ), + ), + ], + ), + const SizedBox(height: 4), Text( - model.trade!.tradeId, + model.trade!.payInExtraId, style: STextStyles.itemSubtitle12( context, ), ), - const SizedBox(width: 10), - GestureDetector( - onTap: () async { - final data = ClipboardData( - text: model.trade!.tradeId, - ); - await clipboard.setData(data); - if (context.mounted) { - unawaited( - showFloatingFlushBar( - type: FlushBarType.info, - message: "Copied to clipboard", - context: context, - ), - ); - } - }, - child: SvgPicture.asset( - Assets.svg.copy, - color: - Theme.of(context) - .extension()! - .infoItemIcons, - width: 12, - ), - ), ], ), - ], + ), + if (model.trade!.payInExtraId.isNotEmpty) + const SizedBox(height: 6), + RoundedWhiteContainer( + child: Row( + children: [ + Text( + "Trade ID", + style: STextStyles.itemSubtitle(context), + ), + const Spacer(), + Row( + children: [ + Text( + model.trade!.tradeId, + style: STextStyles.itemSubtitle12( + context, + ), + ), + const SizedBox(width: 10), + GestureDetector( + onTap: () async { + final data = ClipboardData( + text: model.trade!.tradeId, + ); + await clipboard.setData(data); + if (context.mounted) { + unawaited( + showFloatingFlushBar( + type: FlushBarType.info, + message: + "Copied to clipboard", + context: context, + ), + ); + } + }, + child: SvgPicture.asset( + Assets.svg.copy, + color: + Theme.of(context) + .extension()! + .infoItemIcons, + width: 12, + ), + ), + ], + ), + ], + ), ), - ), - const SizedBox(height: 6), - RoundedWhiteContainer( - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - "Status", - style: STextStyles.itemSubtitle(context), - ), - Text( - _statusString, - style: STextStyles.itemSubtitle( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .colorForStatus(_statusString), + const SizedBox(height: 6), + RoundedWhiteContainer( + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Status", + style: STextStyles.itemSubtitle(context), ), - ), - ], + Text( + _statusString, + style: STextStyles.itemSubtitle( + context, + ).copyWith( + color: Theme.of(context) + .extension()! + .colorForStatus(_statusString), + ), + ), + ], + ), ), - ), - const Spacer(), - const SizedBox(height: 12), - TextButton( - onPressed: () { - showDialog( - context: context, - barrierDismissible: true, - builder: (_) { - return StackDialogBase( - child: Column( - children: [ - const SizedBox(height: 8), - Center( - child: Text( - "Send ${model.sendTicker} to this address", - style: STextStyles.pageTitleH2( - context, + const Spacer(), + const SizedBox(height: 12), + TextButton( + onPressed: () { + showDialog( + context: context, + barrierDismissible: true, + builder: (_) { + return StackDialogBase( + child: Column( + children: [ + const SizedBox(height: 8), + Center( + child: Text( + "Send ${model.sendTicker} to this address", + style: STextStyles.pageTitleH2( + context, + ), ), ), - ), - const SizedBox(height: 24), - Center( - child: QR( - // TODO: grab coin uri scheme from somewhere - // data: "${coin.uriScheme}:$receivingAddress", - data: model.trade!.payInAddress, - size: - MediaQuery.of( - context, - ).size.width / - 2, + const SizedBox(height: 24), + Center( + child: QR( + // TODO: grab coin uri scheme from somewhere + // data: "${coin.uriScheme}:$receivingAddress", + data: model.trade!.payInAddress, + size: + MediaQuery.of( + context, + ).size.width / + 2, + ), ), - ), - const SizedBox(height: 24), - Row( - children: [ - const Spacer(), - Expanded( - child: TextButton( - onPressed: - () => - Navigator.of( - context, - ).pop(), - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle( + const SizedBox(height: 24), + Row( + children: [ + const Spacer(), + Expanded( + child: TextButton( + onPressed: + () => + Navigator.of( + context, + ).pop(), + style: Theme.of(context) + .extension< + StackColors + >()! + .getSecondaryEnabledButtonStyle( + context, + ), + child: Text( + "Cancel", + style: STextStyles.button( context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .buttonTextSecondary, ), - child: Text( - "Cancel", - style: STextStyles.button( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .buttonTextSecondary, ), ), ), - ), - ], - ), - ], - ), - ); - }, - ); - }, - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - child: Text( - "Show QR Code", - style: STextStyles.button(context), + ], + ), + ], + ), + ); + }, + ); + }, + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + child: Text( + "Show QR Code", + style: STextStyles.button(context), + ), ), - ), - if (isWalletCoin) const SizedBox(height: 12), - if (isWalletCoin) - Builder( - builder: (context) { - String buttonTitle = - "Send from ${AppConfig.appName}"; - - final tuple = - ref - .read( - exchangeSendFromWalletIdStateProvider - .state, - ) - .state; - if (tuple != null && - model.sendTicker.toLowerCase() == - tuple.item2.ticker.toLowerCase()) { - final walletName = + if (isWalletCoin) const SizedBox(height: 12), + if (isWalletCoin) + Builder( + builder: (context) { + String buttonTitle = + "Send from ${AppConfig.appName}"; + + final tuple = ref - .read(pWallets) - .getWallet(tuple.item1) - .info - .name; - buttonTitle = "Send from $walletName"; - } - - return TextButton( - onPressed: - tuple != null && - model.sendTicker - .toLowerCase() == - tuple.item2.ticker - .toLowerCase() - ? () async { - await _confirmSend(tuple); - } - : () { - Navigator.of(context).push( - RouteGenerator.getRoute( - shouldUseMaterialRoute: - RouteGenerator - .useMaterialPageRoute, - builder: ( - BuildContext context, - ) { - final coin = AppConfig.coins - .firstWhere( - (e) => - e.ticker - .toLowerCase() == - model - .trade! - .payInCurrency - .toLowerCase(), - ); - - return SendFromView( - coin: coin, - amount: model.sendAmount - .toAmount( - fractionDigits: - coin.fractionDigits, - ), - address: - model - .trade! - .payInAddress, - trade: model.trade!, - ); - }, - settings: const RouteSettings( - name: - SendFromView.routeName, + .read( + exchangeSendFromWalletIdStateProvider + .state, + ) + .state; + if (tuple != null && + model.sendTicker.toLowerCase() == + tuple.item2.ticker.toLowerCase()) { + final walletName = + ref + .read(pWallets) + .getWallet(tuple.item1) + .info + .name; + buttonTitle = "Send from $walletName"; + } + + return TextButton( + onPressed: + tuple != null && + model.sendTicker + .toLowerCase() == + tuple.item2.ticker + .toLowerCase() + ? () async { + await _confirmSend(tuple); + } + : () { + Navigator.of(context).push( + RouteGenerator.getRoute( + shouldUseMaterialRoute: + RouteGenerator + .useMaterialPageRoute, + builder: ( + BuildContext context, + ) { + final coin = AppConfig + .coins + .firstWhere( + (e) => + e.ticker + .toLowerCase() == + model + .trade! + .payInCurrency + .toLowerCase(), + ); + + return SendFromView( + coin: coin, + amount: model.sendAmount + .toAmount( + fractionDigits: + coin.fractionDigits, + ), + address: + model + .trade! + .payInAddress, + trade: model.trade!, + ); + }, + settings: + const RouteSettings( + name: + SendFromView + .routeName, + ), ), - ), - ); - }, - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle( + ); + }, + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle( + context, + ), + child: Text( + buttonTitle, + style: STextStyles.button( context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .buttonTextSecondary, ), - child: Text( - buttonTitle, - style: STextStyles.button( - context, - ).copyWith( - color: - Theme.of(context) - .extension()! - .buttonTextSecondary, ), - ), - ); - }, - ), - ], + ); + }, + ), + ], + ), ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/exchange_view/send_from_view.dart b/lib/pages/exchange_view/send_from_view.dart index 850623031..bad0a3aac 100644 --- a/lib/pages/exchange_view/send_from_view.dart +++ b/lib/pages/exchange_view/send_from_view.dart @@ -116,7 +116,9 @@ class _SendFromViewState extends ConsumerState { ), title: Text("Send from", style: STextStyles.navBarTitle(context)), ), - body: Padding(padding: const EdgeInsets.all(16), child: child), + body: SafeArea( + child: Padding(padding: const EdgeInsets.all(16), child: child), + ), ), ); }, diff --git a/lib/pages/exchange_view/trade_details_view.dart b/lib/pages/exchange_view/trade_details_view.dart index 8bb6017c2..a0ccd79a5 100644 --- a/lib/pages/exchange_view/trade_details_view.dart +++ b/lib/pages/exchange_view/trade_details_view.dart @@ -226,12 +226,14 @@ class _TradeDetailsViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(12), - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(4), - child: child, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(12), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(4), + child: child, + ), ), ), ), diff --git a/lib/pages/exchange_view/wallet_initiated_exchange_view.dart b/lib/pages/exchange_view/wallet_initiated_exchange_view.dart index bfdb0e647..a2ffe26db 100644 --- a/lib/pages/exchange_view/wallet_initiated_exchange_view.dart +++ b/lib/pages/exchange_view/wallet_initiated_exchange_view.dart @@ -12,9 +12,8 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; + import '../../models/isar/models/isar_models.dart'; -import 'exchange_form.dart'; -import 'sub_widgets/step_row.dart'; import '../../providers/exchange/exchange_form_state_provider.dart'; import '../../providers/global/prefs_provider.dart'; import '../../services/exchange/exchange_data_loading_service.dart'; @@ -25,6 +24,8 @@ import '../../widgets/background.dart'; import '../../widgets/conditional_parent.dart'; import '../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../widgets/custom_loading_overlay.dart'; +import 'exchange_form.dart'; +import 'sub_widgets/step_row.dart'; class WalletInitiatedExchangeView extends ConsumerStatefulWidget { const WalletInitiatedExchangeView({ @@ -110,10 +111,9 @@ class _WalletInitiatedExchangeViewState children: [ child, Material( - color: Theme.of(context) - .extension()! - .overlay - .withOpacity(0.6), + color: Theme.of( + context, + ).extension()!.overlay.withOpacity(0.6), child: const CustomLoadingOverlay( message: "Updating exchange data", subMessage: "This could take a few minutes", @@ -139,62 +139,51 @@ class _WalletInitiatedExchangeViewState } }, ), - title: Text( - "Swap", - style: STextStyles.navBarTitle(context), - ), + title: Text("Swap", style: STextStyles.navBarTitle(context)), ), - body: LayoutBuilder( - builder: (context, constraints) { - final width = MediaQuery.of(context).size.width - 32; - return Padding( - padding: const EdgeInsets.all(12), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - StepRow( - count: 4, - current: 0, - width: width, - ), - const SizedBox( - height: 14, - ), - Text( - "Exchange amount", - style: STextStyles.pageTitleH1(context), - ), - const SizedBox( - height: 8, - ), - Text( - "Network fees and other exchange charges are included in the rate.", - style: STextStyles.itemSubtitle(context), - ), - const SizedBox( - height: 24, - ), - ExchangeForm( - walletId: walletId, - coin: coin, - contract: widget.contract, - ), - ], + body: SafeArea( + child: LayoutBuilder( + builder: (context, constraints) { + final width = MediaQuery.of(context).size.width - 32; + return Padding( + padding: const EdgeInsets.all(12), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + StepRow(count: 4, current: 0, width: width), + const SizedBox(height: 14), + Text( + "Exchange amount", + style: STextStyles.pageTitleH1(context), + ), + const SizedBox(height: 8), + Text( + "Network fees and other exchange charges are included in the rate.", + style: STextStyles.itemSubtitle(context), + ), + const SizedBox(height: 24), + ExchangeForm( + walletId: walletId, + coin: coin, + contract: widget.contract, + ), + ], + ), ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/generic/single_field_edit_view.dart b/lib/pages/generic/single_field_edit_view.dart index 5ffb7196f..ee8ac8b12 100644 --- a/lib/pages/generic/single_field_edit_view.dart +++ b/lib/pages/generic/single_field_edit_view.dart @@ -65,61 +65,58 @@ class _SingleFieldEditViewState extends State { Widget build(BuildContext context) { return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - backgroundColor: - Theme.of(context).extension()!.background, - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed(const Duration(milliseconds: 75)); - } - if (mounted) { - Navigator.of(context).pop(); - } - }, - ), - title: Text( - "Edit ${widget.label}", - style: STextStyles.navBarTitle(context), - ), - ), - body: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: child, - ), + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + backgroundColor: + Theme.of(context).extension()!.background, + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 75), + ); + } + if (mounted) { + Navigator.of(context).pop(); + } + }, + ), + title: Text( + "Edit ${widget.label}", + style: STextStyles.navBarTitle(context), + ), + ), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight(child: child), + ), + ); + }, ), - ); - }, + ), + ), ), ), - ), - ), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - if (!isDesktop) - const SizedBox( - height: 10, - ), + if (!isDesktop) const SizedBox(height: 10), if (isDesktop) Padding( - padding: const EdgeInsets.only( - left: 32, - bottom: 12, - ), + padding: const EdgeInsets.only(left: 32, bottom: 12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -132,11 +129,10 @@ class _SingleFieldEditViewState extends State { ), ), Padding( - padding: isDesktop - ? const EdgeInsets.symmetric( - horizontal: 32, - ) - : const EdgeInsets.all(0), + padding: + isDesktop + ? const EdgeInsets.symmetric(horizontal: 32) + : const EdgeInsets.all(0), child: ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -145,14 +141,16 @@ class _SingleFieldEditViewState extends State { autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, controller: _textController, - style: isDesktop - ? STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, - height: 1.8, - ) - : STextStyles.field(context), + style: + isDesktop + ? STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textFieldActiveText, + height: 1.8, + ) + : STextStyles.field(context), focusNode: _textFocusNode, decoration: standardInputDecoration( widget.label.capitalize(), @@ -160,33 +158,35 @@ class _SingleFieldEditViewState extends State { context, desktopMed: isDesktop, ).copyWith( - contentPadding: isDesktop - ? const EdgeInsets.only( - left: 16, - top: 11, - bottom: 12, - right: 5, - ) - : null, - suffixIcon: _textController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _textController.text = ""; - }); - }, - ), - ], + contentPadding: + isDesktop + ? const EdgeInsets.only( + left: 16, + top: 11, + bottom: 12, + right: 5, + ) + : null, + suffixIcon: + _textController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _textController.text = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), @@ -196,30 +196,27 @@ class _SingleFieldEditViewState extends State { ConditionalParent( condition: isDesktop, - builder: (child) => Padding( - padding: const EdgeInsets.all(32), - child: Row( - children: [ - Expanded( - child: SecondaryButton( - label: "Cancel", - buttonHeight: ButtonHeight.l, - onPressed: () { - if (mounted) { - Navigator.of(context).pop(); - } - }, - ), + builder: + (child) => Padding( + padding: const EdgeInsets.all(32), + child: Row( + children: [ + Expanded( + child: SecondaryButton( + label: "Cancel", + buttonHeight: ButtonHeight.l, + onPressed: () { + if (mounted) { + Navigator.of(context).pop(); + } + }, + ), + ), + const SizedBox(width: 16), + Expanded(child: child), + ], ), - const SizedBox( - width: 16, - ), - Expanded( - child: child, - ), - ], - ), - ), + ), child: PrimaryButton( label: "Save", buttonHeight: isDesktop ? ButtonHeight.l : null, @@ -230,10 +227,7 @@ class _SingleFieldEditViewState extends State { }, ), ), - if (!isDesktop) - const SizedBox( - height: 16, - ), + if (!isDesktop) const SizedBox(height: 16), ], ), ); diff --git a/lib/pages/home_view/home_view.dart b/lib/pages/home_view/home_view.dart index 7619a5d34..d937ac4a7 100644 --- a/lib/pages/home_view/home_view.dart +++ b/lib/pages/home_view/home_view.dart @@ -83,13 +83,14 @@ class _HomeViewState extends ConsumerState { await showDialog( context: context, barrierDismissible: false, - builder: (_) => WillPopScope( - onWillPop: () async { - _exitEnabled = true; - return true; - }, - child: const StackDialog(title: "Tap back again to exit"), - ), + builder: + (_) => WillPopScope( + onWillPop: () async { + _exitEnabled = true; + return true; + }, + child: const StackDialog(title: "Tap back again to exit"), + ), ).timeout( timeout, onTimeout: () { @@ -176,16 +177,17 @@ class _HomeViewState extends ConsumerState { // dirty hack ref.listen( - prefsChangeNotifierProvider.select((value) => value.enableExchange), - (prev, next) { - if (next == false && - mounted && - ref.read(homeViewPageIndexStateProvider) != 0) { - WidgetsBinding.instance.addPostFrameCallback( - (_) => ref.read(homeViewPageIndexStateProvider.state).state = 0, - ); - } - }); + prefsChangeNotifierProvider.select((value) => value.enableExchange), + (prev, next) { + if (next == false && + mounted && + ref.read(homeViewPageIndexStateProvider) != 0) { + WidgetsBinding.instance.addPostFrameCallback( + (_) => ref.read(homeViewPageIndexStateProvider.state).state = 0, + ); + } + }, + ); return WillPopScope( onWillPop: _onWillPop, @@ -202,18 +204,13 @@ class _HomeViewState extends ConsumerState { GestureDetector( onTap: _hiddenOptions, child: RotateIcon( - icon: const AppIcon( - width: 24, - height: 24, - ), + icon: const AppIcon(width: 24, height: 24), curve: Curves.easeInOutCubic, rotationPercent: 1.0, controller: _rotateIconController, ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Text( "My ${AppConfig.prefix}", style: STextStyles.navBarTitle(context), @@ -222,22 +219,11 @@ class _HomeViewState extends ConsumerState { ), actions: [ const Padding( - padding: EdgeInsets.only( - top: 10, - bottom: 10, - right: 10, - ), - child: AspectRatio( - aspectRatio: 1, - child: SmallTorIcon(), - ), + padding: EdgeInsets.only(top: 10, bottom: 10, right: 10), + child: AspectRatio(aspectRatio: 1, child: SmallTorIcon()), ), Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 10, - ), + padding: const EdgeInsets.only(top: 10, bottom: 10, right: 10), child: AspectRatio( aspectRatio: 1, child: AppBarIconButton( @@ -246,65 +232,77 @@ class _HomeViewState extends ConsumerState { key: const Key("walletsViewAlertsButton"), size: 36, shadows: const [], - color: Theme.of(context) - .extension()! - .backgroundAppBar, - icon: ref.watch( - notificationsProvider - .select((value) => value.hasUnreadNotifications), - ) - ? SvgPicture.file( - File( - ref.watch( - themeProvider.select( - (value) => value.assets.bellNew, - ), - ), - ), - width: 20, - height: 20, - color: ref.watch( + color: + Theme.of( + context, + ).extension()!.backgroundAppBar, + icon: + ref.watch( notificationsProvider.select( (value) => value.hasUnreadNotifications, ), ) - ? null - : Theme.of(context) - .extension()! - .topNavIconPrimary, - ) - : SvgPicture.asset( - Assets.svg.bell, - width: 20, - height: 20, - color: ref.watch( - notificationsProvider.select( - (value) => value.hasUnreadNotifications, + ? SvgPicture.file( + File( + ref.watch( + themeProvider.select( + (value) => value.assets.bellNew, + ), + ), ), + width: 20, + height: 20, + color: + ref.watch( + notificationsProvider.select( + (value) => + value.hasUnreadNotifications, + ), + ) + ? null + : Theme.of(context) + .extension()! + .topNavIconPrimary, ) - ? null - : Theme.of(context) - .extension()! - .topNavIconPrimary, - ), + : SvgPicture.asset( + Assets.svg.bell, + width: 20, + height: 20, + color: + ref.watch( + notificationsProvider.select( + (value) => + value.hasUnreadNotifications, + ), + ) + ? null + : Theme.of(context) + .extension()! + .topNavIconPrimary, + ), onPressed: () { // reset unread state ref.refresh(unreadNotificationsStateProvider); - Navigator.of(context) - .pushNamed(NotificationsView.routeName) - .then((_) { - final Set unreadNotificationIds = ref - .read(unreadNotificationsStateProvider.state) - .state; + Navigator.of( + context, + ).pushNamed(NotificationsView.routeName).then((_) { + final Set unreadNotificationIds = + ref + .read(unreadNotificationsStateProvider.state) + .state; if (unreadNotificationIds.isEmpty) return; final List> futures = []; - for (int i = 0; - i < unreadNotificationIds.length - 1; - i++) { + for ( + int i = 0; + i < unreadNotificationIds.length - 1; + i++ + ) { futures.add( - ref.read(notificationsProvider).markAsRead( + ref + .read(notificationsProvider) + .markAsRead( unreadNotificationIds.elementAt(i), false, ), @@ -324,11 +322,7 @@ class _HomeViewState extends ConsumerState { ), ), Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 10, - ), + padding: const EdgeInsets.only(top: 10, bottom: 10, right: 10), child: AspectRatio( aspectRatio: 1, child: AppBarIconButton( @@ -336,89 +330,99 @@ class _HomeViewState extends ConsumerState { key: const Key("walletsViewSettingsButton"), size: 36, shadows: const [], - color: Theme.of(context) - .extension()! - .backgroundAppBar, + color: + Theme.of( + context, + ).extension()!.backgroundAppBar, icon: SvgPicture.asset( Assets.svg.gear, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, width: 20, height: 20, ), onPressed: () { //todo: check if print needed // debugPrint("main view settings tapped"); - Navigator.of(context) - .pushNamed(GlobalSettingsView.routeName); + Navigator.of( + context, + ).pushNamed(GlobalSettingsView.routeName); }, ), ), ), ], ), - body: Column( - children: [ - if (_children.length > 1 && - ref.watch(prefsChangeNotifierProvider).enableExchange) - Container( - decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .backgroundAppBar, - boxShadow: Theme.of(context) - .extension()! - .homeViewButtonBarBoxShadow != - null - ? [ - Theme.of(context) - .extension()! - .homeViewButtonBarBoxShadow!, - ] - : null, - ), - child: const Padding( - padding: EdgeInsets.only( - left: 16, - bottom: 12, - right: 16, - top: 0, + body: SafeArea( + child: Column( + children: [ + if (_children.length > 1 && + ref.watch(prefsChangeNotifierProvider).enableExchange) + Container( + decoration: BoxDecoration( + color: + Theme.of( + context, + ).extension()!.backgroundAppBar, + boxShadow: + Theme.of(context) + .extension()! + .homeViewButtonBarBoxShadow != + null + ? [ + Theme.of(context) + .extension()! + .homeViewButtonBarBoxShadow!, + ] + : null, + ), + child: const Padding( + padding: EdgeInsets.only( + left: 16, + bottom: 12, + right: 16, + top: 0, + ), + child: HomeViewButtonBar(), ), - child: HomeViewButtonBar(), ), - ), - Expanded( - child: Consumer( - builder: (_, _ref, __) { - _ref.listen(homeViewPageIndexStateProvider, - (previous, next) { - if (next is int && next >= 0 && next <= 2) { - // if (next == 1) { - // _exchangeDataLoadingService.loadAll(ref); - // } - // if (next == 2) { - // _buyDataLoadingService.loadAll(ref); - // } - - _lock = true; - _animateToPage(next).then((value) => _lock = false); - } - }); - return PageView( - controller: _pageController, - children: _children, - onPageChanged: (pageIndex) { - if (!_lock) { - ref.read(homeViewPageIndexStateProvider.state).state = - pageIndex; + Expanded( + child: Consumer( + builder: (_, _ref, __) { + _ref.listen(homeViewPageIndexStateProvider, ( + previous, + next, + ) { + if (next is int && next >= 0 && next <= 2) { + // if (next == 1) { + // _exchangeDataLoadingService.loadAll(ref); + // } + // if (next == 2) { + // _buyDataLoadingService.loadAll(ref); + // } + + _lock = true; + _animateToPage(next).then((value) => _lock = false); } - }, - ); - }, + }); + return PageView( + controller: _pageController, + children: _children, + onPageChanged: (pageIndex) { + if (!_lock) { + ref + .read(homeViewPageIndexStateProvider.state) + .state = pageIndex; + } + }, + ); + }, + ), ), - ), - ], + ], + ), ), ), ), diff --git a/lib/pages/intro_view.dart b/lib/pages/intro_view.dart index 7a97eb4a0..ef84551d4 100644 --- a/lib/pages/intro_view.dart +++ b/lib/pages/intro_view.dart @@ -49,145 +49,99 @@ class _IntroViewState extends ConsumerState { @override Widget build(BuildContext context) { debugPrint("BUILD: $runtimeType "); - final stack = - ref.watch(themeProvider.select((value) => value.assets.stack)); + final stack = ref.watch( + themeProvider.select((value) => value.assets.stack), + ); return Background( child: Scaffold( backgroundColor: Theme.of(context).extension()!.background, - body: Center( - child: !isDesktop - ? Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Spacer( - flex: 2, - ), - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - ), - child: ConstrainedBox( - constraints: const BoxConstraints( - maxWidth: 300, + body: SafeArea( + child: Center( + child: + !isDesktop + ? Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Spacer(flex: 2), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 300), + child: SizedBox( + width: isDesktop ? 324 : 266, + height: isDesktop ? 324 : 266, + child: + (stack.endsWith(".png")) + ? Image.file(File(stack)) + : SvgPicture.file( + File(stack), + width: isDesktop ? 324 : 266, + height: isDesktop ? 324 : 266, + ), + ), + ), ), - child: SizedBox( - width: isDesktop ? 324 : 266, - height: isDesktop ? 324 : 266, - child: (stack.endsWith(".png")) - ? Image.file( - File( - stack, - ), - ) - : SvgPicture.file( - File( - stack, - ), - width: isDesktop ? 324 : 266, - height: isDesktop ? 324 : 266, - ), + const Spacer(flex: 1), + AppNameText(isDesktop: isDesktop), + const SizedBox(height: 8), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 48), + child: IntroAboutText(isDesktop: isDesktop), ), - ), - ), - const Spacer( - flex: 1, - ), - AppNameText( - isDesktop: isDesktop, - ), - const SizedBox( - height: 8, - ), - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 48, - ), - child: IntroAboutText( - isDesktop: isDesktop, - ), - ), - const Spacer( - flex: 4, - ), - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 32, - ), - child: PrivacyAndTOSText( - isDesktop: isDesktop, - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - vertical: 16, - ), - child: Row( + const Spacer(flex: 4), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 32), + child: PrivacyAndTOSText(isDesktop: isDesktop), + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 16, + ), + child: Row( + children: [ + Expanded( + child: GetStartedButton(isDesktop: isDesktop), + ), + ], + ), + ), + ], + ) + : SizedBox( + width: 350, + height: 540, + child: Column( children: [ - Expanded( - child: GetStartedButton( - isDesktop: isDesktop, - ), + const Spacer(flex: 2), + const SizedBox( + width: 130, + height: 130, + child: AppIcon(), ), + const Spacer(flex: 42), + AppNameText(isDesktop: isDesktop), + const Spacer(flex: 24), + IntroAboutText(isDesktop: isDesktop), + const Spacer(flex: 42), + GetStartedButton(isDesktop: isDesktop), + if (isDesktop) const SizedBox(height: 20), + if (isDesktop) + SecondaryButton( + label: "Restore from ${AppConfig.prefix} backup", + onPressed: () { + Navigator.of(context).pushNamed( + CreatePasswordView.routeName, + arguments: true, + ); + }, + ), + const Spacer(flex: 65), + PrivacyAndTOSText(isDesktop: isDesktop), ], ), ), - ], - ) - : SizedBox( - width: 350, - height: 540, - child: Column( - children: [ - const Spacer( - flex: 2, - ), - const SizedBox( - width: 130, - height: 130, - child: AppIcon(), - ), - const Spacer( - flex: 42, - ), - AppNameText( - isDesktop: isDesktop, - ), - const Spacer( - flex: 24, - ), - IntroAboutText( - isDesktop: isDesktop, - ), - const Spacer( - flex: 42, - ), - GetStartedButton( - isDesktop: isDesktop, - ), - if (isDesktop) - const SizedBox( - height: 20, - ), - if (isDesktop) - SecondaryButton( - label: "Restore from ${AppConfig.prefix} backup", - onPressed: () { - Navigator.of(context).pushNamed( - CreatePasswordView.routeName, - arguments: true, - ); - }, - ), - const Spacer( - flex: 65, - ), - PrivacyAndTOSText( - isDesktop: isDesktop, - ), - ], - ), - ), + ), ), ), ); @@ -204,11 +158,10 @@ class AppNameText extends StatelessWidget { return Text( AppConfig.appName, textAlign: TextAlign.center, - style: !isDesktop - ? STextStyles.pageTitleH1(context) - : STextStyles.pageTitleH1(context).copyWith( - fontSize: 40, - ), + style: + !isDesktop + ? STextStyles.pageTitleH1(context) + : STextStyles.pageTitleH1(context).copyWith(fontSize: 40), ); } } @@ -223,11 +176,10 @@ class IntroAboutText extends StatelessWidget { return Text( AppConfig.shortDescriptionText, textAlign: TextAlign.center, - style: !isDesktop - ? STextStyles.subtitle(context) - : STextStyles.subtitle(context).copyWith( - fontSize: 24, - ), + style: + !isDesktop + ? STextStyles.subtitle(context) + : STextStyles.subtitle(context).copyWith(fontSize: 24), ); } } @@ -246,29 +198,34 @@ class PrivacyAndTOSText extends StatelessWidget { style: STextStyles.label(context).copyWith(fontSize: fontSize), children: [ const TextSpan( - text: "By using ${AppConfig.appName}, you agree to the "), + text: "By using ${AppConfig.appName}, you agree to the ", + ), TextSpan( text: "Terms of service", style: STextStyles.richLink(context).copyWith(fontSize: fontSize), - recognizer: TapGestureRecognizer() - ..onTap = () { - launchUrl( - Uri.parse("https://stackwallet.com/terms-of-service.html"), - mode: LaunchMode.externalApplication, - ); - }, + recognizer: + TapGestureRecognizer() + ..onTap = () { + launchUrl( + Uri.parse( + "https://stackwallet.com/terms-of-service.html", + ), + mode: LaunchMode.externalApplication, + ); + }, ), const TextSpan(text: " and "), TextSpan( text: "Privacy policy", style: STextStyles.richLink(context).copyWith(fontSize: fontSize), - recognizer: TapGestureRecognizer() - ..onTap = () { - launchUrl( - Uri.parse("https://stackwallet.com/privacy-policy.html"), - mode: LaunchMode.externalApplication, - ); - }, + recognizer: + TapGestureRecognizer() + ..onTap = () { + launchUrl( + Uri.parse("https://stackwallet.com/privacy-policy.html"), + mode: LaunchMode.externalApplication, + ); + }, ), ], ), @@ -285,39 +242,34 @@ class GetStartedButton extends StatelessWidget { Widget build(BuildContext context) { return !isDesktop ? TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), + style: Theme.of( + context, + ).extension()!.getPrimaryEnabledButtonStyle(context), + onPressed: () { + Prefs.instance.externalCalls = true; + Navigator.of( + context, + ).pushNamed(StackPrivacyCalls.routeName, arguments: false); + }, + child: Text("Get started", style: STextStyles.button(context)), + ) + : SizedBox( + width: double.infinity, + height: 70, + child: TextButton( + style: Theme.of( + context, + ).extension()!.getPrimaryEnabledButtonStyle(context), onPressed: () { - Prefs.instance.externalCalls = true; - Navigator.of(context).pushNamed( - StackPrivacyCalls.routeName, - arguments: false, - ); + Navigator.of( + context, + ).pushNamed(StackPrivacyCalls.routeName, arguments: false); }, child: Text( - "Get started", - style: STextStyles.button(context), + "Create new ${AppConfig.prefix}", + style: STextStyles.button(context).copyWith(fontSize: 20), ), - ) - : SizedBox( - width: double.infinity, - height: 70, - child: TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - onPressed: () { - Navigator.of(context).pushNamed( - StackPrivacyCalls.routeName, - arguments: false, - ); - }, - child: Text( - "Create new ${AppConfig.prefix}", - style: STextStyles.button(context).copyWith(fontSize: 20), - ), - ), - ); + ), + ); } } diff --git a/lib/pages/loading_view.dart b/lib/pages/loading_view.dart index e347860ec..c3ec1ffa1 100644 --- a/lib/pages/loading_view.dart +++ b/lib/pages/loading_view.dart @@ -14,6 +14,7 @@ import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:lottie/lottie.dart'; + import '../themes/stack_colors.dart'; import '../themes/theme_providers.dart'; import '../utilities/assets.dart'; @@ -36,40 +37,41 @@ class LoadingView extends ConsumerWidget { return Background( child: Scaffold( backgroundColor: Theme.of(context).extension()!.background, - body: Container( - color: Theme.of(context).extension()!.background, - child: Center( - child: ConditionalParent( - condition: Theme.of(context).extension()!.themeId == - "oled_black", - builder: (child) => RoundedContainer( - color: const Color(0xFFDEDEDE), - radiusMultiplier: 100, - width: width * 1.35, - height: width * 1.35, - child: child, - ), - child: SizedBox( - width: width, - child: assetPath != null - ? Image.file( - File( - assetPath, - ), - ) - : Lottie.asset( - Assets.lottie.test2, - animate: true, - repeat: true, - ), + body: SafeArea( + child: Container( + color: Theme.of(context).extension()!.background, + child: Center( + child: ConditionalParent( + condition: + Theme.of(context).extension()!.themeId == + "oled_black", + builder: + (child) => RoundedContainer( + color: const Color(0xFFDEDEDE), + radiusMultiplier: 100, + width: width * 1.35, + height: width * 1.35, + child: child, + ), + child: SizedBox( + width: width, + child: + assetPath != null + ? Image.file(File(assetPath)) + : Lottie.asset( + Assets.lottie.test2, + animate: true, + repeat: true, + ), + ), ), + // child: Image( + // image: AssetImage( + // Assets.png.splash, + // ), + // width: MediaQuery.of(context).size.width * 0.5, + // ), ), - // child: Image( - // image: AssetImage( - // Assets.png.splash, - // ), - // width: MediaQuery.of(context).size.width * 0.5, - // ), ), ), ), diff --git a/lib/pages/monkey/monkey_view.dart b/lib/pages/monkey/monkey_view.dart index ab39021cb..79cadf9a0 100644 --- a/lib/pages/monkey/monkey_view.dart +++ b/lib/pages/monkey/monkey_view.dart @@ -288,7 +288,7 @@ class _MonkeyViewState extends ConsumerState { ), ], ), - body: child, + body: SafeArea(child: child), ), child: ConditionalParent( condition: isDesktop, diff --git a/lib/pages/namecoin_names/confirm_name_transaction_view.dart b/lib/pages/namecoin_names/confirm_name_transaction_view.dart index 11dbb5c16..ff2f0b74a 100644 --- a/lib/pages/namecoin_names/confirm_name_transaction_view.dart +++ b/lib/pages/namecoin_names/confirm_name_transaction_view.dart @@ -21,7 +21,6 @@ import '../../models/isar/models/transaction_note.dart'; import '../../notifications/show_flush_bar.dart'; import '../../pages_desktop_specific/coin_control/desktop_coin_control_use_dialog.dart'; import '../../pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_auth_send.dart'; -import '../../providers/db/main_db_provider.dart'; import '../../providers/global/secure_store_provider.dart'; import '../../providers/providers.dart'; import '../../route_generator.dart'; @@ -296,29 +295,31 @@ class _ConfirmNameTransactionViewState style: STextStyles.navBarTitle(context), ), ), - body: LayoutBuilder( - builder: (builderContext, constraints) { - return Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, - ), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: child, + body: SafeArea( + child: LayoutBuilder( + builder: (builderContext, constraints) { + return Padding( + padding: const EdgeInsets.only( + left: 12, + top: 12, + right: 12, + ), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: child, + ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/notification_views/notifications_view.dart b/lib/pages/notification_views/notifications_view.dart index 7a20efffd..417d10bae 100644 --- a/lib/pages/notification_views/notifications_view.dart +++ b/lib/pages/notification_views/notifications_view.dart @@ -10,6 +10,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; + import '../../notifications/notification_card.dart'; import '../../providers/providers.dart'; import '../../providers/ui/unread_notifications_provider.dart'; @@ -20,10 +21,7 @@ import '../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../widgets/rounded_white_container.dart'; class NotificationsView extends ConsumerStatefulWidget { - const NotificationsView({ - super.key, - this.walletId, - }); + const NotificationsView({super.key, this.walletId}); final String? walletId; @@ -46,75 +44,81 @@ class _NotificationsViewState extends ConsumerState { @override Widget build(BuildContext context) { - final notifications = widget.walletId == null - ? ref - .watch(notificationsProvider.select((value) => value.notifications)) - : ref - .watch(notificationsProvider.select((value) => value.notifications)) - .where((element) => element.walletId == widget.walletId) - .toList(growable: false); + final notifications = + widget.walletId == null + ? ref.watch( + notificationsProvider.select((value) => value.notifications), + ) + : ref + .watch( + notificationsProvider.select((value) => value.notifications), + ) + .where((element) => element.walletId == widget.walletId) + .toList(growable: false); return Background( child: Scaffold( backgroundColor: Theme.of(context).extension()!.background, appBar: AppBar( - title: Text( - "Notifications", - style: STextStyles.navBarTitle(context), - ), + title: Text("Notifications", style: STextStyles.navBarTitle(context)), leading: AppBarBackButton( onPressed: () async { Navigator.of(context).pop(); }, ), ), - body: Padding( - padding: const EdgeInsets.all(12), - child: notifications.isNotEmpty - ? Column( - children: [ - Expanded( - child: ListView.builder( - shrinkWrap: true, - itemCount: notifications.length, - itemBuilder: (builderContext, index) { - final notification = notifications[index]; - if (notification.read == false) { - ref - .read(unreadNotificationsStateProvider.state) - .state - .add(notification.id); - } - return Padding( - padding: const EdgeInsets.all(4), - child: NotificationCard( - notification: notifications[index], - ), - ); - }, - ), - ), - ], - ) - : Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Padding( - padding: const EdgeInsets.all(4), - child: RoundedWhiteContainer( - child: Center( - child: FittedBox( - fit: BoxFit.scaleDown, - child: Text( - "Notifications will appear here", - style: STextStyles.itemSubtitle(context), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(12), + child: + notifications.isNotEmpty + ? Column( + children: [ + Expanded( + child: ListView.builder( + shrinkWrap: true, + itemCount: notifications.length, + itemBuilder: (builderContext, index) { + final notification = notifications[index]; + if (notification.read == false) { + ref + .read( + unreadNotificationsStateProvider.state, + ) + .state + .add(notification.id); + } + return Padding( + padding: const EdgeInsets.all(4), + child: NotificationCard( + notification: notifications[index], + ), + ); + }, + ), + ), + ], + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.all(4), + child: RoundedWhiteContainer( + child: Center( + child: FittedBox( + fit: BoxFit.scaleDown, + child: Text( + "Notifications will appear here", + style: STextStyles.itemSubtitle(context), + ), + ), ), ), ), - ), + ], ), - ], - ), + ), ), ), ); diff --git a/lib/pages/ordinals/ordinal_details_view.dart b/lib/pages/ordinals/ordinal_details_view.dart index 40ba0333e..05d7eb227 100644 --- a/lib/pages/ordinals/ordinal_details_view.dart +++ b/lib/pages/ordinals/ordinal_details_view.dart @@ -61,20 +61,19 @@ class _OrdinalDetailsViewState extends ConsumerState { final coin = ref.watch(pWalletCoin(widget.walletId)); return Background( - child: SafeArea( - child: Scaffold( + child: Scaffold( + backgroundColor: Theme.of(context).extension()!.background, + appBar: AppBar( backgroundColor: Theme.of(context).extension()!.background, - appBar: AppBar( - backgroundColor: - Theme.of(context).extension()!.background, - leading: const AppBarBackButton(), - title: Text( - "Ordinal details", - style: STextStyles.navBarTitle(context), - ), + leading: const AppBarBackButton(), + title: Text( + "Ordinal details", + style: STextStyles.navBarTitle(context), ), - body: SingleChildScrollView( + ), + body: SafeArea( + child: SingleChildScrollView( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Column( diff --git a/lib/pages/ordinals/ordinals_filter_view.dart b/lib/pages/ordinals/ordinals_filter_view.dart index 4c7d0b398..93c7e0dd7 100644 --- a/lib/pages/ordinals/ordinals_filter_view.dart +++ b/lib/pages/ordinals/ordinals_filter_view.dart @@ -69,9 +69,7 @@ class OrdinalFilter { final ordinalFilterProvider = StateProvider((_) => null); class OrdinalsFilterView extends ConsumerStatefulWidget { - const OrdinalsFilterView({ - super.key, - }); + const OrdinalsFilterView({super.key}); static const String routeName = "/ordinalsFilterView"; @@ -127,9 +125,10 @@ class _OrdinalsFilterViewState extends ConsumerState { return Text( isDateSelected ? "From..." : _fromDateString, style: STextStyles.fieldLabel(context).copyWith( - color: isDateSelected - ? Theme.of(context).extension()!.textSubtitle2 - : Theme.of(context).extension()!.accentColorDark, + color: + isDateSelected + ? Theme.of(context).extension()!.textSubtitle2 + : Theme.of(context).extension()!.accentColorDark, ), ); } @@ -139,9 +138,10 @@ class _OrdinalsFilterViewState extends ConsumerState { return Text( isDateSelected ? "To..." : _toDateString, style: STextStyles.fieldLabel(context).copyWith( - color: isDateSelected - ? Theme.of(context).extension()!.textSubtitle2 - : Theme.of(context).extension()!.accentColorDark, + color: + isDateSelected + ? Theme.of(context).extension()!.textSubtitle2 + : Theme.of(context).extension()!.accentColorDark, ), ); } @@ -154,13 +154,14 @@ class _OrdinalsFilterViewState extends ConsumerState { const middleSeparatorWidth = 12.0; final isDesktop = Util.isDesktop; - final width = isDesktop - ? null - : (MediaQuery.of(context).size.width - - (middleSeparatorWidth + - (2 * middleSeparatorPadding) + - (2 * Constants.size.standardPadding))) / - 2; + final width = + isDesktop + ? null + : (MediaQuery.of(context).size.width - + (middleSeparatorWidth + + (2 * middleSeparatorPadding) + + (2 * Constants.size.standardPadding))) / + 2; return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -181,7 +182,8 @@ class _OrdinalsFilterViewState extends ConsumerState { _selectedFromDate = date; // flag to adjust date so from date is always before to date - final flag = _selectedToDate != null && + final flag = + _selectedToDate != null && !_selectedFromDate!.isBefore(_selectedToDate!); if (flag) { _selectedToDate = DateTime.fromMillisecondsSinceEpoch( @@ -191,13 +193,15 @@ class _OrdinalsFilterViewState extends ConsumerState { setState(() { if (flag) { - _toDateString = _selectedToDate == null - ? "" - : Format.formatDate(_selectedToDate!); + _toDateString = + _selectedToDate == null + ? "" + : Format.formatDate(_selectedToDate!); } - _fromDateString = _selectedFromDate == null - ? "" - : Format.formatDate(_selectedFromDate!); + _fromDateString = + _selectedFromDate == null + ? "" + : Format.formatDate(_selectedFromDate!); }); } } @@ -205,15 +209,18 @@ class _OrdinalsFilterViewState extends ConsumerState { child: Container( width: width, decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - borderRadius: - BorderRadius.circular(Constants.size.circularBorderRadius), + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), border: Border.all( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, width: 1, ), ), @@ -228,18 +235,15 @@ class _OrdinalsFilterViewState extends ConsumerState { Assets.svg.calendar, height: 20, width: 20, - color: Theme.of(context) - .extension()! - .textSubtitle2, - ), - const SizedBox( - width: 10, + color: + Theme.of( + context, + ).extension()!.textSubtitle2, ), + const SizedBox(width: 10), Align( alignment: Alignment.centerLeft, - child: FittedBox( - child: _dateFromText, - ), + child: FittedBox(child: _dateFromText), ), ], ), @@ -248,8 +252,9 @@ class _OrdinalsFilterViewState extends ConsumerState { ), ), Padding( - padding: - const EdgeInsets.symmetric(horizontal: middleSeparatorPadding), + padding: const EdgeInsets.symmetric( + horizontal: middleSeparatorPadding, + ), child: Container( width: middleSeparatorWidth, // height: 1, @@ -272,7 +277,8 @@ class _OrdinalsFilterViewState extends ConsumerState { _selectedToDate = date; // flag to adjust date so from date is always before to date - final flag = _selectedFromDate != null && + final flag = + _selectedFromDate != null && !_selectedToDate!.isAfter(_selectedFromDate!); if (flag) { _selectedFromDate = DateTime.fromMillisecondsSinceEpoch( @@ -282,13 +288,15 @@ class _OrdinalsFilterViewState extends ConsumerState { setState(() { if (flag) { - _fromDateString = _selectedFromDate == null - ? "" - : Format.formatDate(_selectedFromDate!); + _fromDateString = + _selectedFromDate == null + ? "" + : Format.formatDate(_selectedFromDate!); } - _toDateString = _selectedToDate == null - ? "" - : Format.formatDate(_selectedToDate!); + _toDateString = + _selectedToDate == null + ? "" + : Format.formatDate(_selectedToDate!); }); } } @@ -296,15 +304,18 @@ class _OrdinalsFilterViewState extends ConsumerState { child: Container( width: width, decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - borderRadius: - BorderRadius.circular(Constants.size.circularBorderRadius), + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), border: Border.all( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, width: 1, ), ), @@ -319,18 +330,15 @@ class _OrdinalsFilterViewState extends ConsumerState { Assets.svg.calendar, height: 20, width: 20, - color: Theme.of(context) - .extension()! - .textSubtitle2, - ), - const SizedBox( - width: 10, + color: + Theme.of( + context, + ).extension()!.textSubtitle2, ), + const SizedBox(width: 10), Align( alignment: Alignment.centerLeft, - child: FittedBox( - child: _dateToText, - ), + child: FittedBox(child: _dateToText), ), ], ), @@ -338,10 +346,7 @@ class _OrdinalsFilterViewState extends ConsumerState { ), ), ), - if (isDesktop) - const SizedBox( - width: 24, - ), + if (isDesktop) const SizedBox(width: 24), ], ); } @@ -353,10 +358,7 @@ class _OrdinalsFilterViewState extends ConsumerState { maxWidth: 576, maxHeight: double.infinity, child: Padding( - padding: const EdgeInsets.only( - left: 32, - bottom: 32, - ), + padding: const EdgeInsets.only(left: 32, bottom: 32), child: _buildContent(context), ), ); @@ -384,22 +386,23 @@ class _OrdinalsFilterViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: EdgeInsets.symmetric( - horizontal: Constants.size.standardPadding, - ), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: - BoxConstraints(minHeight: constraints.maxHeight), - child: IntrinsicHeight( - child: _buildContent(context), + body: SafeArea( + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: Constants.size.standardPadding, + ), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight(child: _buildContent(context)), ), - ), - ); - }, + ); + }, + ), ), ), ), @@ -424,9 +427,7 @@ class _OrdinalsFilterViewState extends ConsumerState { const DesktopDialogCloseButton(), ], ), - SizedBox( - height: isDesktop ? 14 : 10, - ), + SizedBox(height: isDesktop ? 14 : 10), // if (!isDesktop) // Align( // alignment: Alignment.centerLeft, @@ -572,33 +573,29 @@ class _OrdinalsFilterViewState extends ConsumerState { child: FittedBox( child: Text( "Date", - style: isDesktop - ? STextStyles.labelExtraExtraSmall(context) - : STextStyles.smallMed12(context), + style: + isDesktop + ? STextStyles.labelExtraExtraSmall(context) + : STextStyles.smallMed12(context), ), ), ), - SizedBox( - height: isDesktop ? 10 : 8, - ), + SizedBox(height: isDesktop ? 10 : 8), _buildDateRangePicker(), - SizedBox( - height: isDesktop ? 32 : 24, - ), + SizedBox(height: isDesktop ? 32 : 24), Align( alignment: Alignment.centerLeft, child: FittedBox( child: Text( "Inscription", - style: isDesktop - ? STextStyles.labelExtraExtraSmall(context) - : STextStyles.smallMed12(context), + style: + isDesktop + ? STextStyles.labelExtraExtraSmall(context) + : STextStyles.smallMed12(context), ), ), ), - SizedBox( - height: isDesktop ? 10 : 8, - ), + SizedBox(height: isDesktop ? 10 : 8), Padding( padding: EdgeInsets.only(right: isDesktop ? 32 : 0), child: ClipRRect( @@ -612,65 +609,68 @@ class _OrdinalsFilterViewState extends ConsumerState { controller: _inscriptionTextEditingController, focusNode: inscriptionTextFieldFocusNode, onChanged: (_) => setState(() {}), - style: isDesktop - ? STextStyles.desktopTextExtraSmall(context).copyWith( - color: - Theme.of(context).extension()!.textDark, - height: 1.8, - ) - : STextStyles.field(context), + style: + isDesktop + ? STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, + height: 1.8, + ) + : STextStyles.field(context), decoration: standardInputDecoration( "Enter inscription number...", keywordTextFieldFocusNode, context, desktopMed: isDesktop, ).copyWith( - contentPadding: isDesktop - ? const EdgeInsets.symmetric( - vertical: 10, - horizontal: 16, - ) - : null, - suffixIcon: _inscriptionTextEditingController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _inscriptionTextEditingController.text = ""; - }); - }, - ), - ], + contentPadding: + isDesktop + ? const EdgeInsets.symmetric( + vertical: 10, + horizontal: 16, + ) + : null, + suffixIcon: + _inscriptionTextEditingController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _inscriptionTextEditingController.text = + ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), ), - SizedBox( - height: isDesktop ? 32 : 24, - ), + SizedBox(height: isDesktop ? 32 : 24), Align( alignment: Alignment.centerLeft, child: FittedBox( child: Text( "Keyword", - style: isDesktop - ? STextStyles.labelExtraExtraSmall(context) - : STextStyles.smallMed12(context), + style: + isDesktop + ? STextStyles.labelExtraExtraSmall(context) + : STextStyles.smallMed12(context), ), ), ), - SizedBox( - height: isDesktop ? 10 : 8, - ), + SizedBox(height: isDesktop ? 10 : 8), Padding( padding: EdgeInsets.only(right: isDesktop ? 32 : 0), child: ClipRRect( @@ -683,13 +683,16 @@ class _OrdinalsFilterViewState extends ConsumerState { key: const Key("OrdinalsViewKeywordFieldKey"), controller: _keywordTextEditingController, focusNode: keywordTextFieldFocusNode, - style: isDesktop - ? STextStyles.desktopTextExtraSmall(context).copyWith( - color: - Theme.of(context).extension()!.textDark, - height: 1.8, - ) - : STextStyles.field(context), + style: + isDesktop + ? STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, + height: 1.8, + ) + : STextStyles.field(context), onChanged: (_) => setState(() {}), decoration: standardInputDecoration( "Type keyword...", @@ -697,39 +700,39 @@ class _OrdinalsFilterViewState extends ConsumerState { context, desktopMed: isDesktop, ).copyWith( - contentPadding: isDesktop - ? const EdgeInsets.symmetric( - vertical: 10, - horizontal: 16, - ) - : null, - suffixIcon: _keywordTextEditingController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _keywordTextEditingController.text = ""; - }); - }, - ), - ], + contentPadding: + isDesktop + ? const EdgeInsets.symmetric( + vertical: 10, + horizontal: 16, + ) + : null, + suffixIcon: + _keywordTextEditingController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _keywordTextEditingController.text = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), ), if (!isDesktop) const Spacer(), - SizedBox( - height: isDesktop ? 32 : 20, - ), + SizedBox(height: isDesktop ? 32 : 20), Row( children: [ Expanded( @@ -741,9 +744,7 @@ class _OrdinalsFilterViewState extends ConsumerState { if (FocusScope.of(context).hasFocus) { FocusScope.of(context).unfocus(); await Future.delayed( - const Duration( - milliseconds: 75, - ), + const Duration(milliseconds: 75), ); } } @@ -753,9 +754,7 @@ class _OrdinalsFilterViewState extends ConsumerState { }, ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: PrimaryButton( buttonHeight: isDesktop ? ButtonHeight.l : null, @@ -765,16 +764,10 @@ class _OrdinalsFilterViewState extends ConsumerState { label: "Save", ), ), - if (isDesktop) - const SizedBox( - width: 32, - ), + if (isDesktop) const SizedBox(width: 32), ], ), - if (!isDesktop) - const SizedBox( - height: 20, - ), + if (!isDesktop) const SizedBox(height: 20), ], ); } diff --git a/lib/pages/ordinals/ordinals_view.dart b/lib/pages/ordinals/ordinals_view.dart index 17aaffb86..ed47fcd5c 100644 --- a/lib/pages/ordinals/ordinals_view.dart +++ b/lib/pages/ordinals/ordinals_view.dart @@ -11,7 +11,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; -import 'widgets/ordinals_list.dart'; + import '../../providers/global/wallets_provider.dart'; import '../../themes/stack_colors.dart'; import '../../utilities/assets.dart'; @@ -20,12 +20,10 @@ import '../../utilities/text_styles.dart'; import '../../wallets/wallet/wallet_mixin_interfaces/ordinals_interface.dart'; import '../../widgets/background.dart'; import '../../widgets/custom_buttons/app_bar_icon_button.dart'; +import 'widgets/ordinals_list.dart'; class OrdinalsView extends ConsumerStatefulWidget { - const OrdinalsView({ - super.key, - required this.walletId, - }); + const OrdinalsView({super.key, required this.walletId}); static const routeName = "/ordinalsView"; @@ -59,73 +57,66 @@ class _OrdinalsViewState extends ConsumerState { @override Widget build(BuildContext context) { return Background( - child: SafeArea( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - automaticallyImplyLeading: false, - leading: const AppBarBackButton(), - title: Text( - "Ordinals", - style: STextStyles.navBarTitle(context), - ), - titleSpacing: 0, - actions: [ - AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - size: 36, - icon: SvgPicture.asset( - Assets.svg.arrowRotate, - width: 20, - height: 20, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, - ), - onPressed: () async { - // show loading for a minimum of 2 seconds on refreshing - await showLoading( - whileFuture: Future.wait([ - Future.delayed(const Duration(seconds: 2)), - (ref.read(pWallets).getWallet(widget.walletId) - as OrdinalsInterface) - .refreshInscriptions(), - ]), - context: context, - message: "Refreshing...", - ); - }, + child: Scaffold( + backgroundColor: Theme.of(context).extension()!.background, + appBar: AppBar( + automaticallyImplyLeading: false, + leading: const AppBarBackButton(), + title: Text("Ordinals", style: STextStyles.navBarTitle(context)), + titleSpacing: 0, + actions: [ + AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + size: 36, + icon: SvgPicture.asset( + Assets.svg.arrowRotate, + width: 20, + height: 20, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, ), + onPressed: () async { + // show loading for a minimum of 2 seconds on refreshing + await showLoading( + whileFuture: Future.wait([ + Future.delayed(const Duration(seconds: 2)), + (ref.read(pWallets).getWallet(widget.walletId) + as OrdinalsInterface) + .refreshInscriptions(), + ]), + context: context, + message: "Refreshing...", + ); + }, ), - // AspectRatio( - // aspectRatio: 1, - // child: AppBarIconButton( - // size: 36, - // icon: SvgPicture.asset( - // Assets.svg.filter, - // width: 20, - // height: 20, - // color: Theme.of(context) - // .extension()! - // .topNavIconPrimary, - // ), - // onPressed: () { - // Navigator.of(context).pushNamed( - // OrdinalsFilterView.routeName, - // ); - // }, - // ), - // ), - ], - ), - body: Padding( - padding: const EdgeInsets.only( - left: 16, - right: 16, - top: 8, ), + // AspectRatio( + // aspectRatio: 1, + // child: AppBarIconButton( + // size: 36, + // icon: SvgPicture.asset( + // Assets.svg.filter, + // width: 20, + // height: 20, + // color: Theme.of(context) + // .extension()! + // .topNavIconPrimary, + // ), + // onPressed: () { + // Navigator.of(context).pushNamed( + // OrdinalsFilterView.routeName, + // ); + // }, + // ), + // ), + ], + ), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only(left: 16, right: 16, top: 8), child: Column( children: [ // ClipRRect( @@ -185,11 +176,7 @@ class _OrdinalsViewState extends ConsumerState { // const SizedBox( // height: 16, // ), - Expanded( - child: OrdinalsList( - walletId: widget.walletId, - ), - ), + Expanded(child: OrdinalsList(walletId: widget.walletId)), ], ), ), diff --git a/lib/pages/receive_view/addresses/edit_address_label_view.dart b/lib/pages/receive_view/addresses/edit_address_label_view.dart index 2e6052690..f0508f4a5 100644 --- a/lib/pages/receive_view/addresses/edit_address_label_view.dart +++ b/lib/pages/receive_view/addresses/edit_address_label_view.dart @@ -28,10 +28,7 @@ import '../../../widgets/stack_text_field.dart'; import '../../../widgets/textfield_icon_button.dart'; class EditAddressLabelView extends ConsumerStatefulWidget { - const EditAddressLabelView({ - super.key, - required this.addressLabelId, - }); + const EditAddressLabelView({super.key, required this.addressLabelId}); static const String routeName = "/editAddressLabel"; @@ -54,10 +51,11 @@ class _EditAddressLabelViewState extends ConsumerState { void initState() { isDesktop = Util.isDesktop; _labelFieldController = TextEditingController(); - addressLabel = MainDB.instance.isar.addressLabels - .where() - .idEqualTo(widget.addressLabelId) - .findFirstSync()!; + addressLabel = + MainDB.instance.isar.addressLabels + .where() + .idEqualTo(widget.addressLabelId) + .findFirstSync()!; _labelFieldController.text = addressLabel.value; super.initState(); } @@ -73,145 +71,163 @@ class _EditAddressLabelViewState extends ConsumerState { Widget build(BuildContext context) { return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: child, - ), + builder: (child) => Background(child: child), child: Scaffold( - backgroundColor: isDesktop - ? Colors.transparent - : Theme.of(context).extension()!.background, - appBar: isDesktop - ? null - : AppBar( - backgroundColor: - Theme.of(context).extension()!.background, - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 75), - ); - } - if (mounted) { - Navigator.of(context).pop(); - } - }, + backgroundColor: + isDesktop + ? Colors.transparent + : Theme.of(context).extension()!.background, + appBar: + isDesktop + ? null + : AppBar( + backgroundColor: + Theme.of(context).extension()!.background, + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 75), + ); + } + if (mounted) { + Navigator.of(context).pop(); + } + }, + ), + title: Text( + "Edit label", + style: STextStyles.navBarTitle(context), + ), ), - title: Text( - "Edit label", - style: STextStyles.navBarTitle(context), + body: SafeArea( + child: ConditionalParent( + condition: !isDesktop, + builder: + (child) => Padding( + padding: const EdgeInsets.all(12), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: child, + ), + ), + ), + ); + }, + ), ), - ), - body: ConditionalParent( - condition: !isDesktop, - builder: (child) => Padding( - padding: const EdgeInsets.all(12), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: child, - ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + if (isDesktop) + Padding( + padding: const EdgeInsets.only(left: 32, bottom: 12), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Edit label", + style: STextStyles.desktopH3(context), + ), + const DesktopDialogCloseButton(), + ], ), ), - ); - }, - ), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - if (isDesktop) Padding( - padding: const EdgeInsets.only( - left: 32, - bottom: 12, - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Edit label", - style: STextStyles.desktopH3(context), + padding: + isDesktop + ? const EdgeInsets.symmetric(horizontal: 32) + : const EdgeInsets.all(0), + child: ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, + controller: _labelFieldController, + style: + isDesktop + ? STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveText, + height: 1.8, + ) + : STextStyles.field(context), + focusNode: labelFieldFocusNode, + decoration: standardInputDecoration( + "Address label", + labelFieldFocusNode, + context, + desktopMed: isDesktop, + ).copyWith( + contentPadding: + isDesktop + ? const EdgeInsets.only( + left: 16, + top: 11, + bottom: 12, + right: 5, + ) + : null, + suffixIcon: + _labelFieldController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _labelFieldController.text = ""; + }); + }, + ), + ], + ), + ), + ) + : null, ), - const DesktopDialogCloseButton(), - ], + ), ), ), - Padding( - padding: isDesktop - ? const EdgeInsets.symmetric( - horizontal: 32, - ) - : const EdgeInsets.all(0), - child: ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - controller: _labelFieldController, - style: isDesktop - ? STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, - height: 1.8, - ) - : STextStyles.field(context), - focusNode: labelFieldFocusNode, - decoration: standardInputDecoration( - "Address label", - labelFieldFocusNode, - context, - desktopMed: isDesktop, - ).copyWith( - contentPadding: isDesktop - ? const EdgeInsets.only( - left: 16, - top: 11, - bottom: 12, - right: 5, - ) - : null, - suffixIcon: _labelFieldController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _labelFieldController.text = ""; - }); - }, - ), - ], - ), - ), - ) - : null, + // if (!isDesktop) + const Spacer(), + if (isDesktop) + Padding( + padding: const EdgeInsets.all(32), + child: PrimaryButton( + label: "Save", + onPressed: () async { + await MainDB.instance.updateAddressLabel( + addressLabel.copyWith( + label: _labelFieldController.text, + ), + ); + if (mounted) { + Navigator.of(context).pop(); + } + }, ), ), - ), - ), - // if (!isDesktop) - const Spacer(), - if (isDesktop) - Padding( - padding: const EdgeInsets.all(32), - child: PrimaryButton( - label: "Save", + if (!isDesktop) + TextButton( onPressed: () async { await MainDB.instance.updateAddressLabel( addressLabel.copyWith( @@ -222,29 +238,13 @@ class _EditAddressLabelViewState extends ConsumerState { Navigator.of(context).pop(); } }, + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + child: Text("Save", style: STextStyles.button(context)), ), - ), - if (!isDesktop) - TextButton( - onPressed: () async { - await MainDB.instance.updateAddressLabel( - addressLabel.copyWith( - label: _labelFieldController.text, - ), - ); - if (mounted) { - Navigator.of(context).pop(); - } - }, - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - child: Text( - "Save", - style: STextStyles.button(context), - ), - ), - ], + ], + ), ), ), ), diff --git a/lib/pages/receive_view/addresses/wallet_addresses_view.dart b/lib/pages/receive_view/addresses/wallet_addresses_view.dart index 6c1441b43..8b87fd074 100644 --- a/lib/pages/receive_view/addresses/wallet_addresses_view.dart +++ b/lib/pages/receive_view/addresses/wallet_addresses_view.dart @@ -27,10 +27,7 @@ import 'address_card.dart'; import 'address_details_view.dart'; class WalletAddressesView extends ConsumerStatefulWidget { - const WalletAddressesView({ - super.key, - required this.walletId, - }); + const WalletAddressesView({super.key, required this.walletId}); static const String routeName = "/walletAddressesView"; @@ -85,23 +82,24 @@ class _WalletAddressesViewState extends ConsumerState { .findAll(); } - final labels = await MainDB.instance - .getAddressLabels(widget.walletId) - .filter() - .group( - (q) => q - .valueContains(term, caseSensitive: false) - .or() - .addressStringContains(term, caseSensitive: false) - .or() - .group( - (q) => q - .tagsIsNotNull() - .and() - .tagsElementContains(term, caseSensitive: false), - ), - ) - .findAll(); + final labels = + await MainDB.instance + .getAddressLabels(widget.walletId) + .filter() + .group( + (q) => q + .valueContains(term, caseSensitive: false) + .or() + .addressStringContains(term, caseSensitive: false) + .or() + .group( + (q) => q.tagsIsNotNull().and().tagsElementContains( + term, + caseSensitive: false, + ), + ), + ) + .findAll(); if (labels.isEmpty) { return []; @@ -165,139 +163,137 @@ class _WalletAddressesViewState extends ConsumerState { return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - backgroundColor: - Theme.of(context).extension()!.backgroundAppBar, - leading: AppBarBackButton( - onPressed: () { - Navigator.of(context).pop(); - }, - ), - titleSpacing: 0, - title: Text( - "Wallet addresses", - style: STextStyles.navBarTitle(context), + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + backgroundColor: + Theme.of( + context, + ).extension()!.backgroundAppBar, + leading: AppBarBackButton( + onPressed: () { + Navigator.of(context).pop(); + }, + ), + titleSpacing: 0, + title: Text( + "Wallet addresses", + style: STextStyles.navBarTitle(context), + ), + ), + body: Padding(padding: const EdgeInsets.all(16), child: child), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: child, - ), - ), - ), - child: Column( - children: [ - // SizedBox( - // width: isDesktop ? 490 : null, - // child: ClipRRect( - // borderRadius: BorderRadius.circular( - // Constants.size.circularBorderRadius, - // ), - // child: TextField( - // autocorrect: !isDesktop, - // enableSuggestions: !isDesktop, - // controller: _searchController, - // focusNode: searchFieldFocusNode, - // onChanged: (value) { - // setState(() { - // _searchString = value; - // }); - // }, - // style: isDesktop - // ? STextStyles.desktopTextExtraSmall(context).copyWith( - // color: Theme.of(context) - // .extension()! - // .textFieldActiveText, - // height: 1.8, - // ) - // : STextStyles.field(context), - // decoration: standardInputDecoration( - // "Search...", - // searchFieldFocusNode, - // context, - // desktopMed: isDesktop, - // ).copyWith( - // prefixIcon: Padding( - // padding: EdgeInsets.symmetric( - // horizontal: isDesktop ? 12 : 10, - // vertical: isDesktop ? 18 : 16, - // ), - // child: SvgPicture.asset( - // Assets.svg.search, - // width: isDesktop ? 20 : 16, - // height: isDesktop ? 20 : 16, - // ), - // ), - // suffixIcon: _searchController.text.isNotEmpty - // ? Padding( - // padding: const EdgeInsets.only(right: 0), - // child: UnconstrainedBox( - // child: Row( - // children: [ - // TextFieldIconButton( - // child: const XIcon(), - // onTap: () async { - // setState(() { - // _searchController.text = ""; - // _searchString = ""; - // }); - // }, - // ), - // ], - // ), - // ), - // ) - // : null, - // ), - // ), - // ), - // ), - // SizedBox( - // height: isDesktop ? 20 : 16, - // ), - Expanded( - child: FutureBuilder( - future: _search(_searchString), - builder: (context, AsyncSnapshot> snapshot) { - if (snapshot.connectionState == ConnectionState.done && - snapshot.data != null) { - // listview - return ListView.separated( - itemCount: snapshot.data!.length, - separatorBuilder: (_, __) => Container( - height: 10, - ), - itemBuilder: (_, index) => AddressCard( - walletId: widget.walletId, - addressId: snapshot.data![index], - coin: coin, - onPressed: () { - Navigator.of(context).pushNamed( - AddressDetailsView.routeName, - arguments: Tuple2( - snapshot.data![index], - widget.walletId, + child: SafeArea( + child: Column( + children: [ + // SizedBox( + // width: isDesktop ? 490 : null, + // child: ClipRRect( + // borderRadius: BorderRadius.circular( + // Constants.size.circularBorderRadius, + // ), + // child: TextField( + // autocorrect: !isDesktop, + // enableSuggestions: !isDesktop, + // controller: _searchController, + // focusNode: searchFieldFocusNode, + // onChanged: (value) { + // setState(() { + // _searchString = value; + // }); + // }, + // style: isDesktop + // ? STextStyles.desktopTextExtraSmall(context).copyWith( + // color: Theme.of(context) + // .extension()! + // .textFieldActiveText, + // height: 1.8, + // ) + // : STextStyles.field(context), + // decoration: standardInputDecoration( + // "Search...", + // searchFieldFocusNode, + // context, + // desktopMed: isDesktop, + // ).copyWith( + // prefixIcon: Padding( + // padding: EdgeInsets.symmetric( + // horizontal: isDesktop ? 12 : 10, + // vertical: isDesktop ? 18 : 16, + // ), + // child: SvgPicture.asset( + // Assets.svg.search, + // width: isDesktop ? 20 : 16, + // height: isDesktop ? 20 : 16, + // ), + // ), + // suffixIcon: _searchController.text.isNotEmpty + // ? Padding( + // padding: const EdgeInsets.only(right: 0), + // child: UnconstrainedBox( + // child: Row( + // children: [ + // TextFieldIconButton( + // child: const XIcon(), + // onTap: () async { + // setState(() { + // _searchController.text = ""; + // _searchString = ""; + // }); + // }, + // ), + // ], + // ), + // ), + // ) + // : null, + // ), + // ), + // ), + // ), + // SizedBox( + // height: isDesktop ? 20 : 16, + // ), + Expanded( + child: FutureBuilder( + future: _search(_searchString), + builder: (context, AsyncSnapshot> snapshot) { + if (snapshot.connectionState == ConnectionState.done && + snapshot.data != null) { + // listview + return ListView.separated( + itemCount: snapshot.data!.length, + separatorBuilder: (_, __) => Container(height: 10), + itemBuilder: + (_, index) => AddressCard( + walletId: widget.walletId, + addressId: snapshot.data![index], + coin: coin, + onPressed: () { + Navigator.of(context).pushNamed( + AddressDetailsView.routeName, + arguments: Tuple2( + snapshot.data![index], + widget.walletId, + ), + ); + }, ), - ); - }, - ), - ); - } else { - return const Center( - child: LoadingIndicator( - height: 200, - width: 200, - ), - ); - } - }, + ); + } else { + return const Center( + child: LoadingIndicator(height: 200, width: 200), + ); + } + }, + ), ), - ), - ], + ], + ), ), ); } diff --git a/lib/pages/receive_view/generate_receiving_uri_qr_code_view.dart b/lib/pages/receive_view/generate_receiving_uri_qr_code_view.dart index 7b02e525f..d485cfa14 100644 --- a/lib/pages/receive_view/generate_receiving_uri_qr_code_view.dart +++ b/lib/pages/receive_view/generate_receiving_uri_qr_code_view.dart @@ -80,8 +80,9 @@ class _GenerateUriQrCodeViewState extends State { final RenderRepaintBoundary boundary = _qrKey.currentContext?.findRenderObject() as RenderRepaintBoundary; final ui.Image image = await boundary.toImage(); - final ByteData? byteData = - await image.toByteData(format: ui.ImageByteFormat.png); + final ByteData? byteData = await image.toByteData( + format: ui.ImageByteFormat.png, + ); final Uint8List pngBytes = byteData!.buffer.asUint8List(); if (shouldSaveInsteadOfShare) { @@ -131,10 +132,9 @@ class _GenerateUriQrCodeViewState extends State { final file = await File("${tempDir.path}/qrcode.png").create(); await file.writeAsBytes(pngBytes); - await Share.shareFiles( - ["${tempDir.path}/qrcode.png"], - text: "Receive URI QR Code", - ); + await Share.shareFiles([ + "${tempDir.path}/qrcode.png", + ], text: "Receive URI QR Code"); } } catch (e) { //todo: comeback to this @@ -216,25 +216,18 @@ class _GenerateUriQrCodeViewState extends State { style: STextStyles.pageTitleH2(context), ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Center( child: RepaintBoundary( key: _qrKey, child: SizedBox( width: width + 20, height: width + 20, - child: QR( - data: uriString, - size: width, - ), + child: QR(data: uriString, size: width), ), ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Center( child: SizedBox( width: width, @@ -244,9 +237,10 @@ class _GenerateUriQrCodeViewState extends State { Assets.svg.share, width: 14, height: 14, - color: Theme.of(context) - .extension()! - .buttonTextSecondary, + color: + Theme.of( + context, + ).extension()!.buttonTextSecondary, ), onPressed: () async { await _capturePng(false); @@ -299,62 +293,68 @@ class _GenerateUriQrCodeViewState extends State { return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed(const Duration(milliseconds: 70)); - } - if (context.mounted) { - Navigator.of(context).pop(); - } - }, - ), - title: Text( - "Generate QR code", - style: STextStyles.navBarTitle(context), - ), - ), - body: LayoutBuilder( - builder: (buildContext, constraints) { - return Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 70), + ); + } + if (context.mounted) { + Navigator.of(context).pop(); + } + }, ), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: child, + title: Text( + "Generate QR code", + style: STextStyles.navBarTitle(context), + ), + ), + body: SafeArea( + child: LayoutBuilder( + builder: (buildContext, constraints) { + return Padding( + padding: const EdgeInsets.only( + left: 12, + top: 12, + right: 12, ), - ), - ), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: child, + ), + ), + ), + ), + ); + }, ), - ); - }, + ), + ), ), - ), - ), child: Padding( - padding: isDesktop - ? const EdgeInsets.only( - top: 12, - left: 32, - right: 32, - bottom: 32, - ) - : const EdgeInsets.all(0), + padding: + isDesktop + ? const EdgeInsets.only( + top: 12, + left: 32, + right: 32, + bottom: 32, + ) + : const EdgeInsets.all(0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, mainAxisSize: isDesktop ? MainAxisSize.min : MainAxisSize.max, @@ -366,24 +366,23 @@ class _GenerateUriQrCodeViewState extends State { style: STextStyles.itemSubtitle(context), ), ), - if (!isDesktop) - const SizedBox( - height: 12, - ), + if (!isDesktop) const SizedBox(height: 12), Text( "Amount (Optional)", - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, - ) - : STextStyles.smallMed12(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconRight, + ) + : STextStyles.smallMed12(context), textAlign: TextAlign.left, ), - SizedBox( - height: isDesktop ? 10 : 8, - ), + SizedBox(height: isDesktop ? 10 : 8), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -393,70 +392,77 @@ class _GenerateUriQrCodeViewState extends State { enableSuggestions: Util.isDesktop ? false : true, controller: amountController, focusNode: _amountFocusNode, - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldDefaultText, - height: 1.8, - ) - : STextStyles.field(context), - keyboardType: Util.isDesktop - ? null - : const TextInputType.numberWithOptions(decimal: true), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textFieldDefaultText, + height: 1.8, + ) + : STextStyles.field(context), + keyboardType: + Util.isDesktop + ? null + : const TextInputType.numberWithOptions(decimal: true), onChanged: (_) => setState(() {}), decoration: standardInputDecoration( "Amount", _amountFocusNode, context, ).copyWith( - contentPadding: isDesktop - ? const EdgeInsets.only( - left: 16, - top: 11, - bottom: 12, - right: 5, - ) - : null, - suffixIcon: amountController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - amountController.text = ""; - }); - }, - ), - ], + contentPadding: + isDesktop + ? const EdgeInsets.only( + left: 16, + top: 11, + bottom: 12, + right: 5, + ) + : null, + suffixIcon: + amountController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + amountController.text = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), - SizedBox( - height: isDesktop ? 20 : 12, - ), + SizedBox(height: isDesktop ? 20 : 12), Text( "Note (Optional)", - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, - ) - : STextStyles.smallMed12(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconRight, + ) + : STextStyles.smallMed12(context), textAlign: TextAlign.left, ), - SizedBox( - height: isDesktop ? 10 : 8, - ), + SizedBox(height: isDesktop ? 10 : 8), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -466,68 +472,73 @@ class _GenerateUriQrCodeViewState extends State { enableSuggestions: Util.isDesktop ? false : true, controller: noteController, focusNode: _noteFocusNode, - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldDefaultText, - height: 1.8, - ) - : STextStyles.field(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textFieldDefaultText, + height: 1.8, + ) + : STextStyles.field(context), onChanged: (_) => setState(() {}), decoration: standardInputDecoration( "Note", _noteFocusNode, context, ).copyWith( - contentPadding: isDesktop - ? const EdgeInsets.only( - left: 16, - top: 11, - bottom: 12, - right: 5, - ) - : null, - suffixIcon: noteController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - noteController.text = ""; - }); - }, - ), - ], + contentPadding: + isDesktop + ? const EdgeInsets.only( + left: 16, + top: 11, + bottom: 12, + right: 5, + ) + : null, + suffixIcon: + noteController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + noteController.text = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), - SizedBox( - height: isDesktop ? 20 : 8, - ), + SizedBox(height: isDesktop ? 20 : 8), PrimaryButton( label: "Generate QR code", - onPressed: isDesktop - ? () { - final uriString = _generateURI(); - if (uriString == null) { - return; + onPressed: + isDesktop + ? () { + final uriString = _generateURI(); + if (uriString == null) { + return; + } + + setState(() { + didGenerate = true; + _uriString = uriString; + }); } - - setState(() { - didGenerate = true; - _uriString = uriString; - }); - } - : onGeneratePressed, + : onGeneratePressed, buttonHeight: isDesktop ? ButtonHeight.l : null, ), if (isDesktop && didGenerate) @@ -538,13 +549,12 @@ class _GenerateUriQrCodeViewState extends State { Column( mainAxisSize: MainAxisSize.min, children: [ - const SizedBox( - height: 20, - ), + const SizedBox(height: 20), RoundedWhiteContainer( - borderColor: Theme.of(context) - .extension()! - .background, + borderColor: + Theme.of( + context, + ).extension()!.background, width: isDesktop ? 370 : null, child: Column( children: [ @@ -552,29 +562,23 @@ class _GenerateUriQrCodeViewState extends State { "New QR Code", style: STextStyles.desktopTextMedium(context), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), Center( child: RepaintBoundary( key: _qrKey, child: SizedBox( width: 234, height: 234, - child: QR( - data: _uriString, - size: 220, - ), + child: QR(data: _uriString, size: 220), ), ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Row( - mainAxisAlignment: isDesktop - ? MainAxisAlignment.center - : MainAxisAlignment.start, + mainAxisAlignment: + isDesktop + ? MainAxisAlignment.center + : MainAxisAlignment.start, children: [ if (!isDesktop) SecondaryButton( @@ -589,15 +593,13 @@ class _GenerateUriQrCodeViewState extends State { Assets.svg.share, width: 20, height: 20, - color: Theme.of(context) - .extension()! - .buttonTextSecondary, + color: + Theme.of(context) + .extension()! + .buttonTextSecondary, ), ), - if (!isDesktop) - const SizedBox( - width: 16, - ), + if (!isDesktop) const SizedBox(width: 16), PrimaryButton( width: 170, buttonHeight: @@ -612,9 +614,10 @@ class _GenerateUriQrCodeViewState extends State { Assets.svg.arrowDown, width: 20, height: 20, - color: Theme.of(context) - .extension()! - .buttonTextPrimary, + color: + Theme.of(context) + .extension()! + .buttonTextPrimary, ), ), ], diff --git a/lib/pages/receive_view/receive_view.dart b/lib/pages/receive_view/receive_view.dart index 43a5c6c8d..9c8abcb6c 100644 --- a/lib/pages/receive_view/receive_view.dart +++ b/lib/pages/receive_view/receive_view.dart @@ -20,7 +20,6 @@ import 'package:isar/isar.dart'; import '../../models/isar/models/isar_models.dart'; import '../../models/keys/view_only_wallet_data.dart'; import '../../notifications/show_flush_bar.dart'; -import '../../providers/db/main_db_provider.dart'; import '../../providers/providers.dart'; import '../../route_generator.dart'; import '../../themes/stack_colors.dart'; @@ -94,10 +93,9 @@ class _ReceiveViewState extends ConsumerState { return WillPopScope( onWillPop: () async => shouldPop, child: Container( - color: Theme.of(context) - .extension()! - .overlay - .withOpacity(0.5), + color: Theme.of( + context, + ).extension()!.overlay.withOpacity(0.5), child: const CustomLoadingOverlay( message: "Generating address", eventBus: null, @@ -112,8 +110,9 @@ class _ReceiveViewState extends ConsumerState { if (wallet is Bip39HDWallet && wallet is! BCashInterface) { DerivePathType? type; if (wallet.isViewOnly && wallet is ExtendedKeysInterface) { - final voData = await wallet.getViewOnlyWalletData() - as ExtendedKeysViewOnlyWalletData; + final voData = + await wallet.getViewOnlyWalletData() + as ExtendedKeysViewOnlyWalletData; for (final t in wallet.cryptoCurrency.supportedDerivationPathTypes) { final testPath = wallet.cryptoCurrency.constructDerivePath( derivePathType: t, @@ -151,8 +150,9 @@ class _ReceiveViewState extends ConsumerState { shouldPop = true; if (mounted) { - Navigator.of(context) - .popUntil(ModalRoute.withName(ReceiveView.routeName)); + Navigator.of( + context, + ).popUntil(ModalRoute.withName(ReceiveView.routeName)); setState(() { _addressMap[_walletAddressTypes[_currentIndex]] = @@ -173,10 +173,9 @@ class _ReceiveViewState extends ConsumerState { return WillPopScope( onWillPop: () async => shouldPop, child: Container( - color: Theme.of(context) - .extension()! - .overlay - .withOpacity(0.5), + color: Theme.of( + context, + ).extension()!.overlay.withOpacity(0.5), child: const CustomLoadingOverlay( message: "Generating address", eventBus: null, @@ -214,7 +213,8 @@ class _ReceiveViewState extends ConsumerState { if (wallet is ViewOnlyOptionInterface && wallet.isViewOnly) { _showMultiType = false; } else { - _showMultiType = _supportsSpark || + _showMultiType = + _supportsSpark || (wallet is! BCashInterface && wallet is Bip39HDWallet && wallet.supportedAddressTypes.length > 1); @@ -227,9 +227,9 @@ class _ReceiveViewState extends ConsumerState { _walletAddressTypes.insert(0, AddressType.spark); } else { _walletAddressTypes.addAll( - (wallet as Bip39HDWallet) - .supportedAddressTypes - .where((e) => e != wallet.info.mainAddressType), + (wallet as Bip39HDWallet).supportedAddressTypes.where( + (e) => e != wallet.info.mainAddressType, + ), ); } } @@ -238,8 +238,9 @@ class _ReceiveViewState extends ConsumerState { _walletAddressTypes.removeWhere((e) => e == AddressType.p2pkh); } - _addressMap[_walletAddressTypes[_currentIndex]] = - ref.read(pWalletReceivingAddress(walletId)); + _addressMap[_walletAddressTypes[_currentIndex]] = ref.read( + pWalletReceivingAddress(walletId), + ); if (_showMultiType) { for (final type in _walletAddressTypes) { @@ -255,15 +256,15 @@ class _ReceiveViewState extends ConsumerState { .findFirst() .asStream() .listen((event) { - WidgetsBinding.instance.addPostFrameCallback((_) { - if (mounted) { - setState(() { - _addressMap[type] = - event?.value ?? _addressMap[type] ?? "[No address yet]"; + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted) { + setState(() { + _addressMap[type] = + event?.value ?? _addressMap[type] ?? "[No address yet]"; + }); + } }); - } - }); - }); + }); } } @@ -291,8 +292,9 @@ class _ReceiveViewState extends ConsumerState { address = ref.watch(pWalletReceivingAddress(walletId)); } - final wallet = - ref.watch(pWallets.select((value) => value.getWallet(walletId))); + final wallet = ref.watch( + pWallets.select((value) => value.getWallet(walletId)), + ); final bool canGen; if (wallet is ViewOnlyOptionInterface && @@ -318,11 +320,7 @@ class _ReceiveViewState extends ConsumerState { ), actions: [ Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 10, - ), + padding: const EdgeInsets.only(top: 10, bottom: 10, right: 10), child: AspectRatio( aspectRatio: 1, child: AppBarIconButton( @@ -334,9 +332,10 @@ class _ReceiveViewState extends ConsumerState { color: Theme.of(context).extension()!.background, icon: SvgPicture.asset( Assets.svg.verticalEllipsis, - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, width: 20, height: 20, ), @@ -353,9 +352,10 @@ class _ReceiveViewState extends ConsumerState { right: 10, child: Container( decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .popupBG, + color: + Theme.of( + context, + ).extension()!.popupBG, borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), @@ -407,114 +407,176 @@ class _ReceiveViewState extends ConsumerState { ), ], ), - body: Padding( - padding: const EdgeInsets.all(12), - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - ConditionalParent( - condition: _showMultiType, - builder: (child) => Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Text( - "Address type", - style: STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .infoItemLabel, - ), - ), - const SizedBox( - height: 10, - ), - DropdownButtonHideUnderline( - child: DropdownButton2( - value: _currentIndex, - items: [ - for (int i = 0; - i < _walletAddressTypes.length; - i++) - DropdownMenuItem( - value: i, - child: Text( - _supportsSpark && - _walletAddressTypes[i] == - AddressType.p2pkh - ? "Transparent address" - : "${_walletAddressTypes[i].readableName} address", - style: STextStyles.w500_14(context), - ), - ), - ], - onChanged: (value) { - if (value != null && value != _currentIndex) { - setState(() { - _currentIndex = value; - }); - } - }, - isExpanded: true, - iconStyleData: IconStyleData( - icon: Padding( - padding: const EdgeInsets.only(right: 10), - child: SvgPicture.asset( - Assets.svg.chevronDown, - width: 12, - height: 6, - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(12), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + ConditionalParent( + condition: _showMultiType, + builder: + (child) => Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text( + "Address type", + style: STextStyles.w500_14(context).copyWith( + color: + Theme.of( + context, + ).extension()!.infoItemLabel, ), ), - ), - buttonStyleData: ButtonStyleData( - decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + const SizedBox(height: 10), + DropdownButtonHideUnderline( + child: DropdownButton2( + value: _currentIndex, + items: [ + for ( + int i = 0; + i < _walletAddressTypes.length; + i++ + ) + DropdownMenuItem( + value: i, + child: Text( + _supportsSpark && + _walletAddressTypes[i] == + AddressType.p2pkh + ? "Transparent address" + : "${_walletAddressTypes[i].readableName} address", + style: STextStyles.w500_14(context), + ), + ), + ], + onChanged: (value) { + if (value != null && + value != _currentIndex) { + setState(() { + _currentIndex = value; + }); + } + }, + isExpanded: true, + iconStyleData: IconStyleData( + icon: Padding( + padding: const EdgeInsets.only(right: 10), + child: SvgPicture.asset( + Assets.svg.chevronDown, + width: 12, + height: 6, + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconRight, + ), + ), + ), + buttonStyleData: ButtonStyleData( + decoration: BoxDecoration( + color: + Theme.of(context) + .extension()! + .textFieldDefaultBG, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + ), + dropdownStyleData: DropdownStyleData( + offset: const Offset(0, -10), + elevation: 0, + decoration: BoxDecoration( + color: + Theme.of(context) + .extension()! + .textFieldDefaultBG, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + ), + menuItemStyleData: const MenuItemStyleData( + padding: EdgeInsets.symmetric( + horizontal: 16, + vertical: 8, + ), + ), ), ), - ), - dropdownStyleData: DropdownStyleData( - offset: const Offset(0, -10), - elevation: 0, - decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), + const SizedBox(height: 12), + child, + ], + ), + child: GestureDetector( + onTap: () { + HapticFeedback.lightImpact(); + clipboard.setData(ClipboardData(text: address)); + showFloatingFlushBar( + type: FlushBarType.info, + message: "Copied to clipboard", + iconAsset: Assets.svg.copy, + context: context, + ); + }, + child: RoundedWhiteContainer( + child: Column( + children: [ + Row( + children: [ + Text( + "Your $ticker address", + style: STextStyles.itemSubtitle(context), + ), + const Spacer(), + Row( + children: [ + SvgPicture.asset( + Assets.svg.copy, + width: 10, + height: 10, + color: + Theme.of(context) + .extension()! + .infoItemIcons, + ), + const SizedBox(width: 4), + Text( + "Copy", + style: STextStyles.link2(context), + ), + ], + ), + ], ), - ), - menuItemStyleData: const MenuItemStyleData( - padding: EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, + const SizedBox(height: 4), + Row( + children: [ + Expanded( + child: Text( + address, + style: STextStyles.itemSubtitle12( + context, + ), + ), + ), + ], ), - ), + ], ), ), - const SizedBox( - height: 12, - ), - child, - ], + ), ), - child: GestureDetector( - onTap: () { + const SizedBox(height: 12), + PrimaryButton( + label: "Copy address", + onPressed: () { HapticFeedback.lightImpact(); - clipboard.setData( - ClipboardData( - text: address, - ), - ); + clipboard.setData(ClipboardData(text: address)); showFloatingFlushBar( type: FlushBarType.info, message: "Copied to clipboard", @@ -522,134 +584,62 @@ class _ReceiveViewState extends ConsumerState { context: context, ); }, - child: RoundedWhiteContainer( - child: Column( - children: [ - Row( - children: [ - Text( - "Your $ticker address", - style: STextStyles.itemSubtitle(context), - ), - const Spacer(), - Row( - children: [ - SvgPicture.asset( - Assets.svg.copy, - width: 10, - height: 10, - color: Theme.of(context) - .extension()! - .infoItemIcons, - ), - const SizedBox( - width: 4, - ), - Text( - "Copy", - style: STextStyles.link2(context), - ), - ], - ), - ], - ), - const SizedBox( - height: 4, - ), - Row( - children: [ - Expanded( - child: Text( - address, - style: STextStyles.itemSubtitle12(context), - ), - ), - ], - ), - ], - ), - ), - ), - ), - const SizedBox( - height: 12, - ), - PrimaryButton( - label: "Copy address", - onPressed: () { - HapticFeedback.lightImpact(); - clipboard.setData( - ClipboardData( - text: address, - ), - ); - showFloatingFlushBar( - type: FlushBarType.info, - message: "Copied to clipboard", - iconAsset: Assets.svg.copy, - context: context, - ); - }, - ), - if (canGen) - const SizedBox( - height: 12, - ), - if (canGen) - SecondaryButton( - label: "Generate new address", - onPressed: _supportsSpark && - _walletAddressTypes[_currentIndex] == - AddressType.spark - ? generateNewSparkAddress - : generateNewAddress, ), - const SizedBox( - height: 30, - ), - RoundedWhiteContainer( - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Center( - child: Column( - children: [ - QR( - data: AddressUtils.buildUriString( - coin.uriScheme, - address, - {}, + if (canGen) const SizedBox(height: 12), + if (canGen) + SecondaryButton( + label: "Generate new address", + onPressed: + _supportsSpark && + _walletAddressTypes[_currentIndex] == + AddressType.spark + ? generateNewSparkAddress + : generateNewAddress, + ), + const SizedBox(height: 30), + RoundedWhiteContainer( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Center( + child: Column( + children: [ + QR( + data: AddressUtils.buildUriString( + coin.uriScheme, + address, + {}, + ), + size: MediaQuery.of(context).size.width / 2, ), - size: MediaQuery.of(context).size.width / 2, - ), - const SizedBox( - height: 20, - ), - CustomTextButton( - text: "Advanced options", - onTap: () async { - unawaited( - Navigator.of(context).push( - RouteGenerator.getRoute( - shouldUseMaterialRoute: - RouteGenerator.useMaterialPageRoute, - builder: (_) => GenerateUriQrCodeView( - coin: coin, - receivingAddress: address, - ), - settings: const RouteSettings( - name: GenerateUriQrCodeView.routeName, + const SizedBox(height: 20), + CustomTextButton( + text: "Advanced options", + onTap: () async { + unawaited( + Navigator.of(context).push( + RouteGenerator.getRoute( + shouldUseMaterialRoute: + RouteGenerator.useMaterialPageRoute, + builder: + (_) => GenerateUriQrCodeView( + coin: coin, + receivingAddress: address, + ), + settings: const RouteSettings( + name: GenerateUriQrCodeView.routeName, + ), ), ), - ), - ); - }, - ), - ], + ); + }, + ), + ], + ), ), ), ), - ), - ], + ], + ), ), ), ), diff --git a/lib/pages/send_view/confirm_transaction_view.dart b/lib/pages/send_view/confirm_transaction_view.dart index 57a6549ca..ac6d9863c 100644 --- a/lib/pages/send_view/confirm_transaction_view.dart +++ b/lib/pages/send_view/confirm_transaction_view.dart @@ -411,29 +411,31 @@ class _ConfirmTransactionViewState style: STextStyles.navBarTitle(context), ), ), - body: LayoutBuilder( - builder: (builderContext, constraints) { - return Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, - ), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: child, + body: SafeArea( + child: LayoutBuilder( + builder: (builderContext, constraints) { + return Padding( + padding: const EdgeInsets.only( + left: 12, + top: 12, + right: 12, + ), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: child, + ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/send_view/frost_ms/frost_send_view.dart b/lib/pages/send_view/frost_ms/frost_send_view.dart index 3d90a896f..22c290036 100644 --- a/lib/pages/send_view/frost_ms/frost_send_view.dart +++ b/lib/pages/send_view/frost_ms/frost_send_view.dart @@ -51,11 +51,7 @@ import '../../coin_control/coin_control_view.dart'; import 'recipient.dart'; class FrostSendView extends ConsumerStatefulWidget { - const FrostSendView({ - super.key, - required this.walletId, - required this.coin, - }); + const FrostSendView({super.key, required this.walletId, required this.coin}); static const String routeName = "/frostSendView"; @@ -107,9 +103,7 @@ class _FrostSendViewState extends ConsumerState { try { // wait for keyboard to disappear FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 100), - ); + await Future.delayed(const Duration(milliseconds: 100)); TxData? txData; if (mounted) { @@ -143,9 +137,7 @@ class _FrostSendViewState extends ConsumerState { callerRouteName: FrostSendView.routeName, ); - await Navigator.of(context).pushNamed( - FrostStepScaffold.routeName, - ); + await Navigator.of(context).pushNamed(FrostStepScaffold.routeName); } } catch (e) { if (mounted) { @@ -165,9 +157,10 @@ class _FrostSendViewState extends ConsumerState { child: Text( "Ok", style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), ), onPressed: () { @@ -229,7 +222,8 @@ class _FrostSendViewState extends ConsumerState { debugPrint("BUILD: $runtimeType"); final wallet = ref.watch(pWallets).getWallet(walletId); - final showCoinControl = wallet is CoinControlInterface && + final showCoinControl = + wallet is CoinControlInterface && ref.watch( prefsChangeNotifierProvider.select( (value) => value.enableCoinControl, @@ -241,56 +235,59 @@ class _FrostSendViewState extends ConsumerState { return ConditionalParent( condition: !Util.isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed(const Duration(milliseconds: 50)); - } - if (context.mounted) { - Navigator.of(context).pop(); - } - }, - ), - title: Text( - "Send ${coin.ticker}", - style: STextStyles.navBarTitle(context), - ), - ), - body: LayoutBuilder( - builder: (builderContext, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - // subtract top and bottom padding set in parent - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: child, - ), - ), + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 50), + ); + } + if (context.mounted) { + Navigator.of(context).pop(); + } + }, ), - ); - }, + title: Text( + "Send ${coin.ticker}", + style: STextStyles.navBarTitle(context), + ), + ), + body: SafeArea( + child: LayoutBuilder( + builder: (builderContext, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + // subtract top and bottom padding set in parent + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: child, + ), + ), + ), + ); + }, + ), + ), + ), ), - ), - ), child: ConditionalParent( condition: Util.isDesktop, - builder: (child) => Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 14, - ), - child: child, - ), + builder: + (child) => Padding( + padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 14), + child: child, + ), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ @@ -307,24 +304,19 @@ class _FrostSendViewState extends ConsumerState { child: Row( children: [ SvgPicture.file( - File( - ref.watch( - coinIconProvider(coin), - ), - ), + File(ref.watch(coinIconProvider(coin))), width: 22, height: 22, ), - const SizedBox( - width: 6, - ), + const SizedBox(width: 6), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( ref.watch(pWalletName(walletId)), - style: STextStyles.titleBold12(context) - .copyWith(fontSize: 14), + style: STextStyles.titleBold12( + context, + ).copyWith(fontSize: 14), overflow: TextOverflow.ellipsis, maxLines: 1, ), @@ -333,15 +325,14 @@ class _FrostSendViewState extends ConsumerState { // ), Text( "Available balance", - style: STextStyles.label(context) - .copyWith(fontSize: 10), + style: STextStyles.label( + context, + ).copyWith(fontSize: 10), ), ], ), Util.isDesktop - ? const SizedBox( - height: 24, - ) + ? const SizedBox(height: 24) : const Spacer(), GestureDetector( onTap: () {}, @@ -351,15 +342,16 @@ class _FrostSendViewState extends ConsumerState { crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( - ref.watch(pAmountFormatter(coin)).format( + ref + .watch(pAmountFormatter(coin)) + .format( ref .watch(pWalletBalance(walletId)) .spendable, ), - style: - STextStyles.titleBold12(context).copyWith( - fontSize: 10, - ), + style: STextStyles.titleBold12( + context, + ).copyWith(fontSize: 10), textAlign: TextAlign.right, ), ], @@ -370,41 +362,40 @@ class _FrostSendViewState extends ConsumerState { ), ), ), - SizedBox( - height: recipientWidgetIndexes.length > 1 ? 8 : 16, - ), + SizedBox(height: recipientWidgetIndexes.length > 1 ? 8 : 16), Column( children: [ for (int i = 0; i < recipientWidgetIndexes.length; i++) ConditionalParent( condition: recipientWidgetIndexes.length > 1, - builder: (child) => Padding( - padding: const EdgeInsets.only(top: 8), - child: child, - ), + builder: + (child) => Padding( + padding: const EdgeInsets.only(top: 8), + child: child, + ), child: Recipient( - key: Key( - "recipientKey_${recipientWidgetIndexes[i]}", - ), + key: Key("recipientKey_${recipientWidgetIndexes[i]}"), index: recipientWidgetIndexes[i], displayNumber: i + 1, coin: coin, onChanged: () { _validateRecipientFormStates(); }, - remove: i == 0 && recipientWidgetIndexes.length == 1 - ? null - : () { - ref - .read( - pRecipient(recipientWidgetIndexes[i]) - .notifier, - ) - .state = null; - recipientWidgetIndexes.removeAt(i); - setState(() {}); - _validateRecipientFormStates(); - }, + remove: + i == 0 && recipientWidgetIndexes.length == 1 + ? null + : () { + ref + .read( + pRecipient( + recipientWidgetIndexes[i], + ).notifier, + ) + .state = null; + recipientWidgetIndexes.removeAt(i); + setState(() {}); + _validateRecipientFormStates(); + }, addAnotherRecipientTapped: () { // used for tracking recipient forms _greatestWidgetIndex++; @@ -413,7 +404,9 @@ class _FrostSendViewState extends ConsumerState { _validateRecipientFormStates(); }, sendAllTapped: () { - return ref.read(pAmountFormatter(coin)).format( + return ref + .read(pAmountFormatter(coin)) + .format( ref.read(pWalletBalance(walletId)).spendable, withUnitName: false, ); @@ -422,10 +415,7 @@ class _FrostSendViewState extends ConsumerState { ), ], ), - if (recipientWidgetIndexes.length > 1) - const SizedBox( - height: 12, - ), + if (recipientWidgetIndexes.length > 1) const SizedBox(height: 12), if (recipientWidgetIndexes.length > 1) SecondaryButton( width: double.infinity, @@ -437,10 +427,7 @@ class _FrostSendViewState extends ConsumerState { setState(() {}); }, ), - if (showCoinControl) - const SizedBox( - height: 8, - ), + if (showCoinControl) const SizedBox(height: 8), if (showCoinControl) RoundedWhiteContainer( child: Row( @@ -449,15 +436,17 @@ class _FrostSendViewState extends ConsumerState { Text( "Coin control", style: STextStyles.w500_14(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, + color: + Theme.of( + context, + ).extension()!.textSubtitle1, ), ), CustomTextButton( - text: selectedUTXOs.isEmpty - ? "Select coins" - : "Selected coins (${selectedUTXOs.length})", + text: + selectedUTXOs.isEmpty + ? "Select coins" + : "Selected coins (${selectedUTXOs.length})", onTap: () async { if (FocusScope.of(context).hasFocus) { FocusScope.of(context).unfocus(); @@ -492,17 +481,13 @@ class _FrostSendViewState extends ConsumerState { ], ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Text( "Note (optional)", style: STextStyles.smallMed12(context), textAlign: TextAlign.left, ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -519,36 +504,32 @@ class _FrostSendViewState extends ConsumerState { _noteFocusNode, context, ).copyWith( - suffixIcon: noteController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - noteController.text = ""; - }); - }, - ), - ], + suffixIcon: + noteController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + noteController.text = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Padding( - padding: const EdgeInsets.only( - bottom: 12, - top: 16, - ), + padding: const EdgeInsets.only(bottom: 12, top: 16), child: FeeSlider( coin: coin, showWU: true, @@ -557,22 +538,14 @@ class _FrostSendViewState extends ConsumerState { }, ), ), - Util.isDesktop - ? const SizedBox( - height: 12, - ) - : const Spacer(), - const SizedBox( - height: 12, - ), + Util.isDesktop ? const SizedBox(height: 12) : const Spacer(), + const SizedBox(height: 12), PrimaryButton( label: "Create multisig transaction", enabled: _buttonEnabled, onPressed: _createSignConfig, ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), ], ), ), diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index 4047a2064..4ea893ea7 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -1223,7 +1223,9 @@ class _SendViewState extends ConsumerState { _address = _address!.substring(0, _address!.indexOf("\n")); } - sendToController.text = AddressUtils().formatEpicCashAddress(_address!); + sendToController.text = AddressUtils().formatEpicCashAddress( + _address!, + ); } }); } @@ -1257,733 +1259,680 @@ class _SendViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: LayoutBuilder( - builder: (builderContext, constraints) { - return Padding( - padding: const EdgeInsets.only(left: 12, top: 12, right: 12), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - // subtract top and bottom padding set in parent - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Container( - decoration: BoxDecoration( - color: - Theme.of( - context, - ).extension()!.popupBG, - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + body: SafeArea( + child: LayoutBuilder( + builder: (builderContext, constraints) { + return Padding( + padding: const EdgeInsets.only(left: 12, top: 12, right: 12), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + // subtract top and bottom padding set in parent + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Container( + decoration: BoxDecoration( + color: + Theme.of( + context, + ).extension()!.popupBG, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - ), - child: Padding( - padding: const EdgeInsets.all(12.0), - child: Row( - children: [ - SvgPicture.file( - File(ref.watch(coinIconProvider(coin))), - width: 22, - height: 22, - ), - const SizedBox(width: 6), - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - ref.watch(pWalletName(walletId)), - style: STextStyles.titleBold12( - context, - ).copyWith(fontSize: 14), - overflow: TextOverflow.ellipsis, - maxLines: 1, - ), - // const SizedBox( - // height: 2, - // ), - if (isFiro) - Text( - "${ref.watch(publicPrivateBalanceStateProvider.state).state.name.capitalize()} balance", - style: STextStyles.label( - context, - ).copyWith(fontSize: 10), - ), - if (coin is! Firo) + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Row( + children: [ + SvgPicture.file( + File(ref.watch(coinIconProvider(coin))), + width: 22, + height: 22, + ), + const SizedBox(width: 6), + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ Text( - "Available balance", - style: STextStyles.label( + ref.watch(pWalletName(walletId)), + style: STextStyles.titleBold12( context, - ).copyWith(fontSize: 10), + ).copyWith(fontSize: 14), + overflow: TextOverflow.ellipsis, + maxLines: 1, ), - ], - ), - const Spacer(), - Builder( - builder: (context) { - final Amount amount; - if (isFiro) { - switch (ref - .watch( - publicPrivateBalanceStateProvider - .state, - ) - .state) { - case FiroType.public: - amount = - ref - .read( - pWalletBalance(walletId), - ) - .spendable; - break; - case FiroType.lelantus: - amount = - ref - .read( - pWalletBalanceSecondary( - walletId, - ), - ) - .spendable; - break; - case FiroType.spark: - amount = - ref - .read( - pWalletBalanceTertiary( - walletId, - ), - ) - .spendable; - break; + // const SizedBox( + // height: 2, + // ), + if (isFiro) + Text( + "${ref.watch(publicPrivateBalanceStateProvider.state).state.name.capitalize()} balance", + style: STextStyles.label( + context, + ).copyWith(fontSize: 10), + ), + if (coin is! Firo) + Text( + "Available balance", + style: STextStyles.label( + context, + ).copyWith(fontSize: 10), + ), + ], + ), + const Spacer(), + Builder( + builder: (context) { + final Amount amount; + if (isFiro) { + switch (ref + .watch( + publicPrivateBalanceStateProvider + .state, + ) + .state) { + case FiroType.public: + amount = + ref + .read( + pWalletBalance( + walletId, + ), + ) + .spendable; + break; + case FiroType.lelantus: + amount = + ref + .read( + pWalletBalanceSecondary( + walletId, + ), + ) + .spendable; + break; + case FiroType.spark: + amount = + ref + .read( + pWalletBalanceTertiary( + walletId, + ), + ) + .spendable; + break; + } + } else { + amount = + ref + .read( + pWalletBalance(walletId), + ) + .spendable; } - } else { - amount = - ref - .read(pWalletBalance(walletId)) - .spendable; - } - return GestureDetector( - onTap: () { - cryptoAmountController.text = ref - .read(pAmountFormatter(coin)) - .format( - amount, - withUnitName: false, - ); - }, - child: Container( - color: Colors.transparent, - child: Column( - crossAxisAlignment: - CrossAxisAlignment.end, - children: [ - Text( - ref - .watch( - pAmountFormatter(coin), - ) - .format(amount), - style: STextStyles.titleBold12( - context, - ).copyWith(fontSize: 10), - textAlign: TextAlign.right, - ), - if (price != null) + return GestureDetector( + onTap: () { + cryptoAmountController.text = ref + .read(pAmountFormatter(coin)) + .format( + amount, + withUnitName: false, + ); + }, + child: Container( + color: Colors.transparent, + child: Column( + crossAxisAlignment: + CrossAxisAlignment.end, + children: [ Text( - "${(amount.decimal * price).toAmount(fractionDigits: 2).fiatString(locale: locale)} ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", - style: STextStyles.subtitle( - context, - ).copyWith(fontSize: 8), + ref + .watch( + pAmountFormatter(coin), + ) + .format(amount), + style: + STextStyles.titleBold12( + context, + ).copyWith(fontSize: 10), textAlign: TextAlign.right, ), - ], + if (price != null) + Text( + "${(amount.decimal * price).toAmount(fractionDigits: 2).fiatString(locale: locale)} ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", + style: STextStyles.subtitle( + context, + ).copyWith(fontSize: 8), + textAlign: TextAlign.right, + ), + ], + ), ), - ), - ); - }, - ), - ], + ); + }, + ), + ], + ), ), ), - ), - const SizedBox(height: 16), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - isPaynymSend - ? "Send to PayNym address" - : "Send to", - style: STextStyles.smallMed12(context), - textAlign: TextAlign.left, - ), - // if (coin is Monero) - // CustomTextButton( - // text: "Use OpenAlias", - // onTap: () async { - // await showModalBottomSheet( - // context: context, - // builder: (context) => - // OpenAliasBottomSheet( - // onSelected: (address) { - // sendToController.text = address; - // }, - // ), - // ); - // }, - // ), - ], - ), - const SizedBox(height: 8), - if (isPaynymSend) - TextField( - key: const Key("sendViewPaynymAddressFieldKey"), - controller: sendToController, - enabled: false, - readOnly: true, - style: STextStyles.fieldLabel(context), + const SizedBox(height: 16), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + isPaynymSend + ? "Send to PayNym address" + : "Send to", + style: STextStyles.smallMed12(context), + textAlign: TextAlign.left, + ), + // if (coin is Monero) + // CustomTextButton( + // text: "Use OpenAlias", + // onTap: () async { + // await showModalBottomSheet( + // context: context, + // builder: (context) => + // OpenAliasBottomSheet( + // onSelected: (address) { + // sendToController.text = address; + // }, + // ), + // ); + // }, + // ), + ], ), - if (!isPaynymSend) - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - key: const Key("sendViewAddressFieldKey"), + const SizedBox(height: 8), + if (isPaynymSend) + TextField( + key: const Key("sendViewPaynymAddressFieldKey"), controller: sendToController, - readOnly: false, - autocorrect: false, - enableSuggestions: false, - // inputFormatters: [ - // FilteringTextInputFormatter.allow( - // RegExp("[a-zA-Z0-9]{34}")), - // ], - toolbarOptions: const ToolbarOptions( - copy: false, - cut: false, - paste: true, - selectAll: false, + enabled: false, + readOnly: true, + style: STextStyles.fieldLabel(context), + ), + if (!isPaynymSend) + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - onChanged: (newValue) async { - final trimmed = newValue.trim(); - - if ((trimmed.length - (_address?.length ?? 0)) - .abs() > - 1) { - final parsed = AddressUtils.parsePaymentUri( - trimmed, - logging: Logging.instance, - ); - if (parsed != null) { - _applyUri(parsed); + child: TextField( + key: const Key("sendViewAddressFieldKey"), + controller: sendToController, + readOnly: false, + autocorrect: false, + enableSuggestions: false, + // inputFormatters: [ + // FilteringTextInputFormatter.allow( + // RegExp("[a-zA-Z0-9]{34}")), + // ], + toolbarOptions: const ToolbarOptions( + copy: false, + cut: false, + paste: true, + selectAll: false, + ), + onChanged: (newValue) async { + final trimmed = newValue.trim(); + + if ((trimmed.length - + (_address?.length ?? 0)) + .abs() > + 1) { + final parsed = + AddressUtils.parsePaymentUri( + trimmed, + logging: Logging.instance, + ); + if (parsed != null) { + _applyUri(parsed); + } else { + await _checkSparkNameAndOrSetAddress( + newValue, + ); + } } else { await _checkSparkNameAndOrSetAddress( newValue, + setController: false, ); } - } else { - await _checkSparkNameAndOrSetAddress( - newValue, - setController: false, - ); - } - - _setValidAddressProviders(_address); - setState(() { - _addressToggleFlag = newValue.isNotEmpty; - }); - }, - focusNode: _addressFocusNode, - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Enter ${coin.ticker} address", - _addressFocusNode, - context, - ).copyWith( - contentPadding: const EdgeInsets.only( - left: 16, - top: 6, - bottom: 8, - right: 5, - ), - suffixIcon: Padding( - padding: - sendToController.text.isEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceAround, - children: [ - _addressToggleFlag - ? TextFieldIconButton( + _setValidAddressProviders(_address); + + setState(() { + _addressToggleFlag = newValue.isNotEmpty; + }); + }, + focusNode: _addressFocusNode, + style: STextStyles.field(context), + decoration: standardInputDecoration( + "Enter ${coin.ticker} address", + _addressFocusNode, + context, + ).copyWith( + contentPadding: const EdgeInsets.only( + left: 16, + top: 6, + bottom: 8, + right: 5, + ), + suffixIcon: Padding( + padding: + sendToController.text.isEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceAround, + children: [ + _addressToggleFlag + ? TextFieldIconButton( + semanticsLabel: + "Clear Button. Clears The Address Field Input.", + key: const Key( + "sendViewClearAddressFieldButtonKey", + ), + onTap: () { + sendToController.text = ""; + _address = ""; + _setValidAddressProviders( + _address, + ); + setState(() { + _addressToggleFlag = + false; + }); + }, + child: const XIcon(), + ) + : TextFieldIconButton( + semanticsLabel: + "Paste Button. Pastes From Clipboard To Address Field Input.", + key: const Key( + "sendViewPasteAddressFieldButtonKey", + ), + onTap: _pasteAddress, + child: + sendToController + .text + .isEmpty + ? const ClipboardIcon() + : const XIcon(), + ), + if (sendToController.text.isEmpty) + TextFieldIconButton( semanticsLabel: - "Clear Button. Clears The Address Field Input.", + "Address Book Button. Opens Address Book For Address Field.", key: const Key( - "sendViewClearAddressFieldButtonKey", + "sendViewAddressBookButtonKey", ), onTap: () { - sendToController.text = ""; - _address = ""; - _setValidAddressProviders( - _address, + Navigator.of( + context, + ).pushNamed( + AddressBookView.routeName, + arguments: widget.coin, ); - setState(() { - _addressToggleFlag = false; - }); }, - child: const XIcon(), - ) - : TextFieldIconButton( + child: const AddressBookIcon(), + ), + if (sendToController.text.isEmpty) + TextFieldIconButton( semanticsLabel: - "Paste Button. Pastes From Clipboard To Address Field Input.", + "Scan QR Button. Opens Camera For Scanning QR Code.", key: const Key( - "sendViewPasteAddressFieldButtonKey", + "sendViewScanQrButtonKey", ), - onTap: _pasteAddress, - child: - sendToController - .text - .isEmpty - ? const ClipboardIcon() - : const XIcon(), - ), - if (sendToController.text.isEmpty) - TextFieldIconButton( - semanticsLabel: - "Address Book Button. Opens Address Book For Address Field.", - key: const Key( - "sendViewAddressBookButtonKey", - ), - onTap: () { - Navigator.of(context).pushNamed( - AddressBookView.routeName, - arguments: widget.coin, - ); - }, - child: const AddressBookIcon(), - ), - if (sendToController.text.isEmpty) - TextFieldIconButton( - semanticsLabel: - "Scan QR Button. Opens Camera For Scanning QR Code.", - key: const Key( - "sendViewScanQrButtonKey", + onTap: _scanQr, + child: const QrCodeIcon(), ), - onTap: _scanQr, - child: const QrCodeIcon(), - ), - ], + ], + ), ), ), ), ), ), - ), - const SizedBox(height: 10), - if (isStellar || - (ref.watch(pValidSparkSendToAddress) && - ref.watch( - publicPrivateBalanceStateProvider, - ) != - FiroType.lelantus)) - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - key: const Key("sendViewMemoFieldKey"), - maxLength: (coin is Firo) ? 31 : null, - controller: memoController, - readOnly: false, - autocorrect: false, - enableSuggestions: false, - focusNode: _memoFocus, - style: STextStyles.field(context), - onChanged: (_) { - setState(() {}); - }, - decoration: standardInputDecoration( - "Enter memo (optional)", - _memoFocus, - context, - ).copyWith( - counterText: '', - contentPadding: const EdgeInsets.only( - left: 16, - top: 6, - bottom: 8, - right: 5, - ), - suffixIcon: Padding( - padding: - memoController.text.isEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceAround, - children: [ - memoController.text.isNotEmpty - ? TextFieldIconButton( - semanticsLabel: - "Clear Button. Clears The Memo Field Input.", - key: const Key( - "sendViewClearMemoFieldButtonKey", - ), - onTap: () { - memoController.text = ""; - setState(() {}); - }, - child: const XIcon(), - ) - : TextFieldIconButton( - semanticsLabel: - "Paste Button. Pastes From Clipboard To Memo Field Input.", - key: const Key( - "sendViewPasteMemoFieldButtonKey", - ), - onTap: () async { - final ClipboardData? data = - await clipboard.getData( - Clipboard.kTextPlain, - ); - if (data?.text != null && - data!.text!.isNotEmpty) { - final String content = - data.text!.trim(); - - memoController.text = - content.trim(); - + const SizedBox(height: 10), + if (isStellar || + (ref.watch(pValidSparkSendToAddress) && + ref.watch( + publicPrivateBalanceStateProvider, + ) != + FiroType.lelantus)) + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + key: const Key("sendViewMemoFieldKey"), + maxLength: (coin is Firo) ? 31 : null, + controller: memoController, + readOnly: false, + autocorrect: false, + enableSuggestions: false, + focusNode: _memoFocus, + style: STextStyles.field(context), + onChanged: (_) { + setState(() {}); + }, + decoration: standardInputDecoration( + "Enter memo (optional)", + _memoFocus, + context, + ).copyWith( + counterText: '', + contentPadding: const EdgeInsets.only( + left: 16, + top: 6, + bottom: 8, + right: 5, + ), + suffixIcon: Padding( + padding: + memoController.text.isEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceAround, + children: [ + memoController.text.isNotEmpty + ? TextFieldIconButton( + semanticsLabel: + "Clear Button. Clears The Memo Field Input.", + key: const Key( + "sendViewClearMemoFieldButtonKey", + ), + onTap: () { + memoController.text = ""; setState(() {}); - } - }, - child: const ClipboardIcon(), - ), - ], + }, + child: const XIcon(), + ) + : TextFieldIconButton( + semanticsLabel: + "Paste Button. Pastes From Clipboard To Memo Field Input.", + key: const Key( + "sendViewPasteMemoFieldButtonKey", + ), + onTap: () async { + final ClipboardData? data = + await clipboard.getData( + Clipboard.kTextPlain, + ); + if (data?.text != null && + data! + .text! + .isNotEmpty) { + final String content = + data.text!.trim(); + + memoController.text = + content.trim(); + + setState(() {}); + } + }, + child: const ClipboardIcon(), + ), + ], + ), ), ), ), ), ), - ), - Builder( - builder: (_) { - final String? error; - - if (_address == null || _address!.isEmpty) { - error = null; - } else if (isFiro) { - if (ref.watch( - publicPrivateBalanceStateProvider, - ) == - FiroType.lelantus) { - if (_data != null && - _data.contactLabel == _address) { - error = - SparkInterface.validateSparkAddress( - address: _data.address, - isTestNet: - coin.network == - CryptoCurrencyNetwork.test, - ) - ? "Unsupported" - : null; - } else if (ref.watch( - pValidSparkSendToAddress, - )) { - error = "Unsupported"; + Builder( + builder: (_) { + final String? error; + + if (_address == null || _address!.isEmpty) { + error = null; + } else if (isFiro) { + if (ref.watch( + publicPrivateBalanceStateProvider, + ) == + FiroType.lelantus) { + if (_data != null && + _data.contactLabel == _address) { + error = + SparkInterface.validateSparkAddress( + address: _data.address, + isTestNet: + coin.network == + CryptoCurrencyNetwork.test, + ) + ? "Unsupported" + : null; + } else if (ref.watch( + pValidSparkSendToAddress, + )) { + error = "Unsupported"; + } else { + error = + ref.watch(pValidSendToAddress) + ? null + : "Invalid address"; + } } else { - error = - ref.watch(pValidSendToAddress) - ? null - : "Invalid address"; + if (_data != null && + _data.contactLabel == _address) { + error = null; + } else if (!ref.watch( + pValidSendToAddress, + ) && + !ref.watch(pValidSparkSendToAddress)) { + error = "Invalid address"; + } else { + error = null; + } } } else { if (_data != null && _data.contactLabel == _address) { error = null; - } else if (!ref.watch(pValidSendToAddress) && - !ref.watch(pValidSparkSendToAddress)) { + } else if (!ref.watch(pValidSendToAddress)) { error = "Invalid address"; } else { error = null; } } - } else { - if (_data != null && - _data.contactLabel == _address) { - error = null; - } else if (!ref.watch(pValidSendToAddress)) { - error = "Invalid address"; - } else { - error = null; - } - } - if (error == null || error.isEmpty) { - return Container(); - } else { - return Align( - alignment: Alignment.topLeft, - child: Padding( - padding: const EdgeInsets.only( - left: 12.0, - top: 4.0, - ), - child: Text( - error, - textAlign: TextAlign.left, - style: STextStyles.label( - context, - ).copyWith( - color: - Theme.of(context) - .extension()! - .textError, + if (error == null || error.isEmpty) { + return Container(); + } else { + return Align( + alignment: Alignment.topLeft, + child: Padding( + padding: const EdgeInsets.only( + left: 12.0, + top: 4.0, ), - ), - ), - ); - } - }, - ), - if (isFiro) const SizedBox(height: 12), - if (isFiro) - Text( - "Send from", - style: STextStyles.smallMed12(context), - textAlign: TextAlign.left, - ), - if (isFiro) const SizedBox(height: 8), - if (isFiro) - Stack( - children: [ - TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: - Util.isDesktop ? false : true, - readOnly: true, - textInputAction: TextInputAction.none, - ), - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, - ), - child: RawMaterialButton( - splashColor: - Theme.of( + child: Text( + error, + textAlign: TextAlign.left, + style: STextStyles.label( context, - ).extension()!.highlight, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: () { - showModalBottomSheet( - backgroundColor: Colors.transparent, - context: context, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical( - top: Radius.circular(20), - ), - ), - builder: - (_) => FiroBalanceSelectionSheet( - walletId: walletId, - ), - ); - }, - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Text( - "${ref.watch(publicPrivateBalanceStateProvider.state).state.name.capitalize()} balance", - style: STextStyles.itemSubtitle12( - context, - ), - ), - const SizedBox(width: 10), - Builder( - builder: (_) { - final Amount amount; - switch (ref - .read( - publicPrivateBalanceStateProvider - .state, - ) - .state) { - case FiroType.public: - amount = - ref - .watch( - pWalletBalance( - walletId, - ), - ) - .spendable; - break; - case FiroType.lelantus: - amount = - ref - .watch( - pWalletBalanceSecondary( - walletId, - ), - ) - .spendable; - break; - case FiroType.spark: - amount = - ref - .watch( - pWalletBalanceTertiary( - walletId, - ), - ) - .spendable; - break; - } - - return Text( - ref - .watch( - pAmountFormatter(coin), - ) - .format(amount), - style: - STextStyles.itemSubtitle( - context, - ), - ); - }, - ), - ], - ), - SvgPicture.asset( - Assets.svg.chevronDown, - width: 8, - height: 4, + ).copyWith( color: Theme.of(context) .extension()! - .textSubtitle2, + .textError, ), - ], + ), ), - ), - ), - ], + ); + } + }, ), - const SizedBox(height: 12), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ + if (isFiro) const SizedBox(height: 12), + if (isFiro) Text( - "Amount", + "Send from", style: STextStyles.smallMed12(context), textAlign: TextAlign.left, ), - if (coin is! Ethereum && coin is! Tezos) - CustomTextButton( - text: _getSendAllTitle( - showCoinControl, - selectedUTXOs, + if (isFiro) const SizedBox(height: 8), + if (isFiro) + Stack( + children: [ + TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: + Util.isDesktop ? false : true, + readOnly: true, + textInputAction: TextInputAction.none, ), - onTap: () => _sendAllTapped(showCoinControl), - ), - ], - ), - const SizedBox(height: 8), - TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - style: STextStyles.smallMed14(context).copyWith( - color: - Theme.of( - context, - ).extension()!.textDark, - ), - key: const Key( - "amountInputFieldCryptoTextFieldKey", - ), - controller: cryptoAmountController, - focusNode: _cryptoFocus, - keyboardType: - Util.isDesktop - ? null - : const TextInputType.numberWithOptions( - signed: false, - decimal: true, + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, ), - textAlign: TextAlign.right, - inputFormatters: [ - AmountInputFormatter( - decimals: coin.fractionDigits, - unit: ref.watch(pAmountUnit(coin)), - locale: locale, - ), + child: RawMaterialButton( + splashColor: + Theme.of( + context, + ).extension()!.highlight, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: () { + showModalBottomSheet( + backgroundColor: Colors.transparent, + context: context, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(20), + ), + ), + builder: + (_) => FiroBalanceSelectionSheet( + walletId: walletId, + ), + ); + }, + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Text( + "${ref.watch(publicPrivateBalanceStateProvider.state).state.name.capitalize()} balance", + style: + STextStyles.itemSubtitle12( + context, + ), + ), + const SizedBox(width: 10), + Builder( + builder: (_) { + final Amount amount; + switch (ref + .read( + publicPrivateBalanceStateProvider + .state, + ) + .state) { + case FiroType.public: + amount = + ref + .watch( + pWalletBalance( + walletId, + ), + ) + .spendable; + break; + case FiroType.lelantus: + amount = + ref + .watch( + pWalletBalanceSecondary( + walletId, + ), + ) + .spendable; + break; + case FiroType.spark: + amount = + ref + .watch( + pWalletBalanceTertiary( + walletId, + ), + ) + .spendable; + break; + } - // regex to validate a crypto amount with 8 decimal places - // TextInputFormatter.withFunction((oldValue, - // newValue) => - // // RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$') - // // RegExp(r'^\d{1,3}([,\.]\d+)?|[,\.\d]+$') - // getAmountRegex(locale, coin.fractionDigits) - // .hasMatch(newValue.text) - // ? newValue - // : oldValue), - ], - decoration: InputDecoration( - contentPadding: const EdgeInsets.only( - top: 12, - right: 12, - ), - hintText: "0", - hintStyle: STextStyles.fieldLabel( - context, - ).copyWith(fontSize: 14), - prefixIcon: FittedBox( - fit: BoxFit.scaleDown, - child: Padding( - padding: const EdgeInsets.all(12), - child: Text( - ref - .watch(pAmountUnit(coin)) - .unitForCoin(coin), - style: STextStyles.smallMed14( - context, - ).copyWith( - color: - Theme.of(context) - .extension()! - .accentColorDark, + return Text( + ref + .watch( + pAmountFormatter( + coin, + ), + ) + .format(amount), + style: + STextStyles.itemSubtitle( + context, + ), + ); + }, + ), + ], + ), + SvgPicture.asset( + Assets.svg.chevronDown, + width: 8, + height: 4, + color: + Theme.of(context) + .extension()! + .textSubtitle2, + ), + ], + ), ), ), - ), + ], ), + const SizedBox(height: 12), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Amount", + style: STextStyles.smallMed12(context), + textAlign: TextAlign.left, + ), + if (coin is! Ethereum && coin is! Tezos) + CustomTextButton( + text: _getSendAllTitle( + showCoinControl, + selectedUTXOs, + ), + onTap: + () => _sendAllTapped(showCoinControl), + ), + ], ), - ), - if (Prefs.instance.externalCalls) const SizedBox(height: 8), - if (Prefs.instance.externalCalls) TextField( autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, @@ -1994,10 +1943,10 @@ class _SendViewState extends ConsumerState { ).extension()!.textDark, ), key: const Key( - "amountInputFieldFiatTextFieldKey", + "amountInputFieldCryptoTextFieldKey", ), - controller: baseAmountController, - focusNode: _baseFocus, + controller: cryptoAmountController, + focusNode: _cryptoFocus, keyboardType: Util.isDesktop ? null @@ -2008,19 +1957,21 @@ class _SendViewState extends ConsumerState { textAlign: TextAlign.right, inputFormatters: [ AmountInputFormatter( - decimals: 2, + decimals: coin.fractionDigits, + unit: ref.watch(pAmountUnit(coin)), locale: locale, ), - // regex to validate a fiat amount with 2 decimal places + + // regex to validate a crypto amount with 8 decimal places // TextInputFormatter.withFunction((oldValue, // newValue) => - // // RegExp(r'^([0-9]*[,.]?[0-9]{0,2}|[,.][0-9]{0,2})$') - // getAmountRegex(locale, 2) + // // RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$') + // // RegExp(r'^\d{1,3}([,\.]\d+)?|[,\.\d]+$') + // getAmountRegex(locale, coin.fractionDigits) // .hasMatch(newValue.text) // ? newValue // : oldValue), ], - onChanged: _fiatFieldChanged, decoration: InputDecoration( contentPadding: const EdgeInsets.only( top: 12, @@ -2035,11 +1986,9 @@ class _SendViewState extends ConsumerState { child: Padding( padding: const EdgeInsets.all(12), child: Text( - ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.currency, - ), - ), + ref + .watch(pAmountUnit(coin)) + .unitForCoin(coin), style: STextStyles.smallMed14( context, ).copyWith( @@ -2053,86 +2002,214 @@ class _SendViewState extends ConsumerState { ), ), ), - if (showCoinControl) const SizedBox(height: 8), - if (showCoinControl) - RoundedWhiteContainer( - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - "Coin control", - style: STextStyles.w500_14( - context, - ).copyWith( - color: - Theme.of(context) - .extension()! - .textSubtitle1, + if (Prefs.instance.externalCalls) + const SizedBox(height: 8), + if (Prefs.instance.externalCalls) + TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: + Util.isDesktop ? false : true, + style: STextStyles.smallMed14(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, + ), + key: const Key( + "amountInputFieldFiatTextFieldKey", + ), + controller: baseAmountController, + focusNode: _baseFocus, + keyboardType: + Util.isDesktop + ? null + : const TextInputType.numberWithOptions( + signed: false, + decimal: true, + ), + textAlign: TextAlign.right, + inputFormatters: [ + AmountInputFormatter( + decimals: 2, + locale: locale, + ), + // regex to validate a fiat amount with 2 decimal places + // TextInputFormatter.withFunction((oldValue, + // newValue) => + // // RegExp(r'^([0-9]*[,.]?[0-9]{0,2}|[,.][0-9]{0,2})$') + // getAmountRegex(locale, 2) + // .hasMatch(newValue.text) + // ? newValue + // : oldValue), + ], + onChanged: _fiatFieldChanged, + decoration: InputDecoration( + contentPadding: const EdgeInsets.only( + top: 12, + right: 12, + ), + hintText: "0", + hintStyle: STextStyles.fieldLabel( + context, + ).copyWith(fontSize: 14), + prefixIcon: FittedBox( + fit: BoxFit.scaleDown, + child: Padding( + padding: const EdgeInsets.all(12), + child: Text( + ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.currency, + ), + ), + style: STextStyles.smallMed14( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorDark, + ), + ), ), ), - CustomTextButton( - text: - selectedUTXOs.isEmpty - ? "Select coins" - : "Selected coins (${selectedUTXOs.length})", - onTap: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 100), - ); - } - - if (context.mounted) { - final spendable = - ref - .read(pWalletBalance(walletId)) - .spendable; - - Amount? amount; - if (ref.read(pSendAmount) != null) { - amount = ref.read(pSendAmount)!; + ), + ), + if (showCoinControl) const SizedBox(height: 8), + if (showCoinControl) + RoundedWhiteContainer( + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Coin control", + style: STextStyles.w500_14( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textSubtitle1, + ), + ), + CustomTextButton( + text: + selectedUTXOs.isEmpty + ? "Select coins" + : "Selected coins (${selectedUTXOs.length})", + onTap: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 100), + ); + } - if (spendable == amount) { - // this is now a send all - } else { - amount += _currentFee; + if (context.mounted) { + final spendable = + ref + .read( + pWalletBalance(walletId), + ) + .spendable; + + Amount? amount; + if (ref.read(pSendAmount) != null) { + amount = ref.read(pSendAmount)!; + + if (spendable == amount) { + // this is now a send all + } else { + amount += _currentFee; + } } - } - final result = await Navigator.of( - context, - ).pushNamed( - CoinControlView.routeName, - arguments: Tuple4( - walletId, - CoinControlViewType.use, - amount, - selectedUTXOs, - ), - ); + final result = await Navigator.of( + context, + ).pushNamed( + CoinControlView.routeName, + arguments: Tuple4( + walletId, + CoinControlViewType.use, + amount, + selectedUTXOs, + ), + ); - if (result is Set) { - setState(() { - selectedUTXOs = result; - }); + if (result is Set) { + setState(() { + selectedUTXOs = result; + }); + } } - } - }, + }, + ), + ], + ), + ), + const SizedBox(height: 12), + if (coin is Epiccash) + Text( + "On chain Note (optional)", + style: STextStyles.smallMed12(context), + textAlign: TextAlign.left, + ), + if (coin is Epiccash) const SizedBox(height: 8), + if (coin is Epiccash) + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: + Util.isDesktop ? false : true, + maxLength: 256, + controller: onChainNoteController, + focusNode: _onChainNoteFocusNode, + style: STextStyles.field(context), + onChanged: (_) => setState(() {}), + decoration: standardInputDecoration( + "Type something...", + _onChainNoteFocusNode, + context, + ).copyWith( + suffixIcon: + onChainNoteController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only( + right: 0, + ), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + onChainNoteController + .text = ""; + }); + }, + ), + ], + ), + ), + ) + : null, ), - ], + ), ), - ), - const SizedBox(height: 12), - if (coin is Epiccash) + if (coin is Epiccash) const SizedBox(height: 12), Text( - "On chain Note (optional)", + (coin is Epiccash) + ? "Local Note (optional)" + : "Note (optional)", style: STextStyles.smallMed12(context), textAlign: TextAlign.left, ), - if (coin is Epiccash) const SizedBox(height: 8), - if (coin is Epiccash) + const SizedBox(height: 8), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -2141,18 +2218,17 @@ class _SendViewState extends ConsumerState { autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, - maxLength: 256, - controller: onChainNoteController, - focusNode: _onChainNoteFocusNode, + controller: noteController, + focusNode: _noteFocusNode, style: STextStyles.field(context), onChanged: (_) => setState(() {}), decoration: standardInputDecoration( "Type something...", - _onChainNoteFocusNode, + _noteFocusNode, context, ).copyWith( suffixIcon: - onChainNoteController.text.isNotEmpty + noteController.text.isNotEmpty ? Padding( padding: const EdgeInsets.only( right: 0, @@ -2164,8 +2240,8 @@ class _SendViewState extends ConsumerState { child: const XIcon(), onTap: () async { setState(() { - onChainNoteController - .text = ""; + noteController.text = + ""; }); }, ), @@ -2177,272 +2253,230 @@ class _SendViewState extends ConsumerState { ), ), ), - if (coin is Epiccash) const SizedBox(height: 12), - Text( - (coin is Epiccash) - ? "Local Note (optional)" - : "Note (optional)", - style: STextStyles.smallMed12(context), - textAlign: TextAlign.left, - ), - const SizedBox(height: 8), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - controller: noteController, - focusNode: _noteFocusNode, - style: STextStyles.field(context), - onChanged: (_) => setState(() {}), - decoration: standardInputDecoration( - "Type something...", - _noteFocusNode, - context, - ).copyWith( - suffixIcon: - noteController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only( - right: 0, - ), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - noteController.text = ""; - }); - }, - ), - ], - ), - ), - ) - : null, + const SizedBox(height: 12), + if (hasFees) + Text( + "Transaction fee ${isEth + ? isCustomFee.value + ? "" + : "(max)" + : "(estimated)"}", + style: STextStyles.smallMed12(context), + textAlign: TextAlign.left, ), - ), - ), - const SizedBox(height: 12), - if (hasFees) - Text( - "Transaction fee ${isEth - ? isCustomFee.value - ? "" - : "(max)" - : "(estimated)"}", - style: STextStyles.smallMed12(context), - textAlign: TextAlign.left, - ), - if (hasFees) const SizedBox(height: 8), - if (hasFees) - Stack( - children: [ - TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: - Util.isDesktop ? false : true, - controller: feeController, - readOnly: true, - textInputAction: TextInputAction.none, - ), - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, + if (hasFees) const SizedBox(height: 8), + if (hasFees) + Stack( + children: [ + TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: + Util.isDesktop ? false : true, + controller: feeController, + readOnly: true, + textInputAction: TextInputAction.none, ), - child: RawMaterialButton( - splashColor: - Theme.of( - context, - ).extension()!.highlight, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, ), - onPressed: - isFiro && - ref - .watch( - publicPrivateBalanceStateProvider - .state, - ) - .state != - FiroType.public - ? null - : _onFeeSelectPressed, - child: - (isFiro && - ref - .watch( - publicPrivateBalanceStateProvider - .state, - ) - .state != - FiroType.public) - ? Row( - children: [ - FutureBuilder( - future: _calculateFeesFuture, - builder: (context, snapshot) { - if (snapshot.connectionState == - ConnectionState - .done && - snapshot.hasData) { - _setCurrentFee( - snapshot.data!, - false, - ); - return Text( - "~${snapshot.data!}", - style: - STextStyles.itemSubtitle( - context, - ), - ); - } else { - return AnimatedText( - stringsToLoopThrough: - stringsToLoopThrough, - style: - STextStyles.itemSubtitle( - context, - ), - ); - } - }, - ), - ], - ) - : Row( - mainAxisAlignment: - MainAxisAlignment - .spaceBetween, - children: [ - Row( - children: [ - Text( - ref + child: RawMaterialButton( + splashColor: + Theme.of( + context, + ).extension()!.highlight, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: + isFiro && + ref .watch( - feeRateTypeMobileStateProvider + publicPrivateBalanceStateProvider .state, ) - .state - .prettyName, - style: - STextStyles.itemSubtitle12( - context, - ), - ), - const SizedBox(width: 10), - FutureBuilder( - future: - _calculateFeesFuture, - builder: ( - context, - snapshot, - ) { - if (snapshot.connectionState == - ConnectionState - .done && - snapshot.hasData) { - _setCurrentFee( - snapshot.data!, - false, - ); - return Text( - isCustomFee.value - ? "" - : "~${snapshot.data!}", - style: - STextStyles.itemSubtitle( - context, - ), - ); - } else { - return AnimatedText( - stringsToLoopThrough: - stringsToLoopThrough, - style: - STextStyles.itemSubtitle( - context, - ), - ); - } - }, - ), - ], - ), - SvgPicture.asset( - Assets.svg.chevronDown, - width: 8, - height: 4, - color: - Theme.of(context) - .extension< - StackColors - >()! - .textSubtitle2, - ), - ], - ), + .state != + FiroType.public + ? null + : _onFeeSelectPressed, + child: + (isFiro && + ref + .watch( + publicPrivateBalanceStateProvider + .state, + ) + .state != + FiroType.public) + ? Row( + children: [ + FutureBuilder( + future: + _calculateFeesFuture, + builder: ( + context, + snapshot, + ) { + if (snapshot.connectionState == + ConnectionState + .done && + snapshot.hasData) { + _setCurrentFee( + snapshot.data!, + false, + ); + return Text( + "~${snapshot.data!}", + style: + STextStyles.itemSubtitle( + context, + ), + ); + } else { + return AnimatedText( + stringsToLoopThrough: + stringsToLoopThrough, + style: + STextStyles.itemSubtitle( + context, + ), + ); + } + }, + ), + ], + ) + : Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Row( + children: [ + Text( + ref + .watch( + feeRateTypeMobileStateProvider + .state, + ) + .state + .prettyName, + style: + STextStyles.itemSubtitle12( + context, + ), + ), + const SizedBox(width: 10), + FutureBuilder( + future: + _calculateFeesFuture, + builder: ( + context, + snapshot, + ) { + if (snapshot.connectionState == + ConnectionState + .done && + snapshot + .hasData) { + _setCurrentFee( + snapshot.data!, + false, + ); + return Text( + isCustomFee.value + ? "" + : "~${snapshot.data!}", + style: + STextStyles.itemSubtitle( + context, + ), + ); + } else { + return AnimatedText( + stringsToLoopThrough: + stringsToLoopThrough, + style: + STextStyles.itemSubtitle( + context, + ), + ); + } + }, + ), + ], + ), + SvgPicture.asset( + Assets.svg.chevronDown, + width: 8, + height: 4, + color: + Theme.of(context) + .extension< + StackColors + >()! + .textSubtitle2, + ), + ], + ), + ), ), + ], + ), + if (isCustomFee.value && !isEth) + Padding( + padding: const EdgeInsets.only( + bottom: 12, + top: 16, + ), + child: FeeSlider( + coin: coin, + onSatVByteChanged: (rate) { + customFeeRate = rate; + }, ), - ], - ), - if (isCustomFee.value && !isEth) - Padding( - padding: const EdgeInsets.only( - bottom: 12, - top: 16, ), - child: FeeSlider( - coin: coin, - onSatVByteChanged: (rate) { - customFeeRate = rate; - }, + if (isCustomFee.value && isEth) + const SizedBox(height: 12), + if (isCustomFee.value && isEth) + EthFeeForm( + minGasLimit: kEthereumMinGasLimit, + stateChanged: (fee) => ethFee = fee, ), - ), - if (isCustomFee.value && isEth) + const Spacer(), const SizedBox(height: 12), - if (isCustomFee.value && isEth) - EthFeeForm( - minGasLimit: kEthereumMinGasLimit, - stateChanged: (fee) => ethFee = fee, - ), - const Spacer(), - const SizedBox(height: 12), - TextButton( - onPressed: - ref.watch(pPreviewTxButtonEnabled(coin)) - ? _previewTransaction - : null, - style: - ref.watch(pPreviewTxButtonEnabled(coin)) - ? Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context) - : Theme.of(context) - .extension()! - .getPrimaryDisabledButtonStyle(context), - child: Text( - "Preview", - style: STextStyles.button(context), + TextButton( + onPressed: + ref.watch(pPreviewTxButtonEnabled(coin)) + ? _previewTransaction + : null, + style: + ref.watch(pPreviewTxButtonEnabled(coin)) + ? Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context) + : Theme.of(context) + .extension()! + .getPrimaryDisabledButtonStyle( + context, + ), + child: Text( + "Preview", + style: STextStyles.button(context), + ), ), - ), - const SizedBox(height: 16), - ], + const SizedBox(height: 16), + ], + ), ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ); diff --git a/lib/pages/send_view/token_send_view.dart b/lib/pages/send_view/token_send_view.dart index 7eaaa43f4..8d9f41327 100644 --- a/lib/pages/send_view/token_send_view.dart +++ b/lib/pages/send_view/token_send_view.dart @@ -663,365 +663,299 @@ class _TokenSendViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: LayoutBuilder( - builder: (builderContext, constraints) { - return Padding( - padding: const EdgeInsets.only(left: 12, top: 12, right: 12), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - // subtract top and bottom padding set in parent - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Container( - decoration: BoxDecoration( - color: - Theme.of( - context, - ).extension()!.popupBG, - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + body: SafeArea( + child: LayoutBuilder( + builder: (builderContext, constraints) { + return Padding( + padding: const EdgeInsets.only(left: 12, top: 12, right: 12), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + // subtract top and bottom padding set in parent + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Container( + decoration: BoxDecoration( + color: + Theme.of( + context, + ).extension()!.popupBG, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - ), - child: Padding( - padding: const EdgeInsets.all(12.0), - child: Row( - children: [ - EthTokenIcon( - contractAddress: tokenContract.address, - ), - const SizedBox(width: 6), - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - ref.watch(pWalletName(walletId)), - style: STextStyles.titleBold12( - context, - ).copyWith(fontSize: 14), - overflow: TextOverflow.ellipsis, - maxLines: 1, - ), - Text( - "Available balance", - style: STextStyles.label( - context, - ).copyWith(fontSize: 10), - ), - ], - ), - const Spacer(), - GestureDetector( - onTap: () { - cryptoAmountController.text = ref - .watch(pAmountFormatter(coin)) - .format( - ref - .read( - pTokenBalance(( - walletId: widget.walletId, - contractAddress: - tokenContract.address, - )), - ) - .spendable, - ethContract: tokenContract, - withUnitName: false, - indicatePrecisionLoss: true, - ); - }, - child: Container( - color: Colors.transparent, - child: Column( - crossAxisAlignment: - CrossAxisAlignment.end, - children: [ - Text( - ref - .watch(pAmountFormatter(coin)) - .format( - ref - .watch( - pTokenBalance(( - walletId: - widget.walletId, - contractAddress: - tokenContract - .address, - )), - ) - .spendable, - ethContract: tokenContract, - ), - style: STextStyles.titleBold12( - context, - ).copyWith(fontSize: 10), - textAlign: TextAlign.right, - ), - if (price != null) + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Row( + children: [ + EthTokenIcon( + contractAddress: tokenContract.address, + ), + const SizedBox(width: 6), + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + ref.watch(pWalletName(walletId)), + style: STextStyles.titleBold12( + context, + ).copyWith(fontSize: 14), + overflow: TextOverflow.ellipsis, + maxLines: 1, + ), + Text( + "Available balance", + style: STextStyles.label( + context, + ).copyWith(fontSize: 10), + ), + ], + ), + const Spacer(), + GestureDetector( + onTap: () { + cryptoAmountController.text = ref + .watch(pAmountFormatter(coin)) + .format( + ref + .read( + pTokenBalance(( + walletId: widget.walletId, + contractAddress: + tokenContract.address, + )), + ) + .spendable, + ethContract: tokenContract, + withUnitName: false, + indicatePrecisionLoss: true, + ); + }, + child: Container( + color: Colors.transparent, + child: Column( + crossAxisAlignment: + CrossAxisAlignment.end, + children: [ Text( - "${(ref.watch(pTokenBalance((walletId: widget.walletId, contractAddress: tokenContract.address))).spendable.decimal * price).toAmount(fractionDigits: 2).fiatString(locale: locale)} ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", - style: STextStyles.subtitle( + ref + .watch(pAmountFormatter(coin)) + .format( + ref + .watch( + pTokenBalance(( + walletId: + widget.walletId, + contractAddress: + tokenContract + .address, + )), + ) + .spendable, + ethContract: tokenContract, + ), + style: STextStyles.titleBold12( context, - ).copyWith(fontSize: 8), + ).copyWith(fontSize: 10), textAlign: TextAlign.right, ), - ], + if (price != null) + Text( + "${(ref.watch(pTokenBalance((walletId: widget.walletId, contractAddress: tokenContract.address))).spendable.decimal * price).toAmount(fractionDigits: 2).fiatString(locale: locale)} ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", + style: STextStyles.subtitle( + context, + ).copyWith(fontSize: 8), + textAlign: TextAlign.right, + ), + ], + ), ), ), - ), - ], + ], + ), ), ), - ), - const SizedBox(height: 16), - Text( - "Send to", - style: STextStyles.smallMed12(context), - textAlign: TextAlign.left, - ), - const SizedBox(height: 8), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + const SizedBox(height: 16), + Text( + "Send to", + style: STextStyles.smallMed12(context), + textAlign: TextAlign.left, ), - child: TextField( - key: const Key("tokenSendViewAddressFieldKey"), - controller: sendToController, - readOnly: false, - autocorrect: false, - enableSuggestions: false, - toolbarOptions: const ToolbarOptions( - copy: false, - cut: false, - paste: true, - selectAll: false, + const SizedBox(height: 8), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - onChanged: (newValue) { - _address = newValue.trim(); - _updatePreviewButtonState( - _address, - _amountToSend, - ); - - setState(() { - _addressToggleFlag = newValue.isNotEmpty; - }); - }, - focusNode: _addressFocusNode, - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Enter ${tokenContract.symbol} address", - _addressFocusNode, - context, - ).copyWith( - contentPadding: const EdgeInsets.only( - left: 16, - top: 6, - bottom: 8, - right: 5, + child: TextField( + key: const Key("tokenSendViewAddressFieldKey"), + controller: sendToController, + readOnly: false, + autocorrect: false, + enableSuggestions: false, + toolbarOptions: const ToolbarOptions( + copy: false, + cut: false, + paste: true, + selectAll: false, ), - suffixIcon: Padding( - padding: - sendToController.text.isEmpty - ? const EdgeInsets.only(right: 8) - : const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceAround, - children: [ - _addressToggleFlag - ? TextFieldIconButton( + onChanged: (newValue) { + _address = newValue.trim(); + _updatePreviewButtonState( + _address, + _amountToSend, + ); + + setState(() { + _addressToggleFlag = newValue.isNotEmpty; + }); + }, + focusNode: _addressFocusNode, + style: STextStyles.field(context), + decoration: standardInputDecoration( + "Enter ${tokenContract.symbol} address", + _addressFocusNode, + context, + ).copyWith( + contentPadding: const EdgeInsets.only( + left: 16, + top: 6, + bottom: 8, + right: 5, + ), + suffixIcon: Padding( + padding: + sendToController.text.isEmpty + ? const EdgeInsets.only(right: 8) + : const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceAround, + children: [ + _addressToggleFlag + ? TextFieldIconButton( + key: const Key( + "tokenSendViewClearAddressFieldButtonKey", + ), + onTap: () { + sendToController.text = ""; + _address = ""; + _updatePreviewButtonState( + _address, + _amountToSend, + ); + setState(() { + _addressToggleFlag = false; + }); + }, + child: const XIcon(), + ) + : TextFieldIconButton( + key: const Key( + "tokenSendViewPasteAddressFieldButtonKey", + ), + onTap: + _onTokenSendViewPasteAddressFieldButtonPressed, + child: + sendToController + .text + .isEmpty + ? const ClipboardIcon() + : const XIcon(), + ), + if (sendToController.text.isEmpty) + TextFieldIconButton( key: const Key( - "tokenSendViewClearAddressFieldButtonKey", + "sendViewAddressBookButtonKey", ), onTap: () { - sendToController.text = ""; - _address = ""; - _updatePreviewButtonState( - _address, - _amountToSend, + Navigator.of(context).pushNamed( + AddressBookView.routeName, + arguments: widget.coin, ); - setState(() { - _addressToggleFlag = false; - }); }, - child: const XIcon(), - ) - : TextFieldIconButton( + child: const AddressBookIcon(), + ), + if (sendToController.text.isEmpty) + TextFieldIconButton( key: const Key( - "tokenSendViewPasteAddressFieldButtonKey", + "sendViewScanQrButtonKey", ), onTap: - _onTokenSendViewPasteAddressFieldButtonPressed, - child: - sendToController.text.isEmpty - ? const ClipboardIcon() - : const XIcon(), - ), - if (sendToController.text.isEmpty) - TextFieldIconButton( - key: const Key( - "sendViewAddressBookButtonKey", + _onTokenSendViewScanQrButtonPressed, + child: const QrCodeIcon(), ), - onTap: () { - Navigator.of(context).pushNamed( - AddressBookView.routeName, - arguments: widget.coin, - ); - }, - child: const AddressBookIcon(), - ), - if (sendToController.text.isEmpty) - TextFieldIconButton( - key: const Key( - "sendViewScanQrButtonKey", - ), - onTap: - _onTokenSendViewScanQrButtonPressed, - child: const QrCodeIcon(), - ), - ], + ], + ), ), ), ), ), ), - ), - Builder( - builder: (_) { - final error = _updateInvalidAddressText( - _address ?? "", - ); - - if (error == null || error.isEmpty) { - return Container(); - } else { - return Align( - alignment: Alignment.topLeft, - child: Padding( - padding: const EdgeInsets.only( - left: 12.0, - top: 4.0, - ), - child: Text( - error, - textAlign: TextAlign.left, - style: STextStyles.label( - context, - ).copyWith( - color: - Theme.of(context) - .extension()! - .textError, + Builder( + builder: (_) { + final error = _updateInvalidAddressText( + _address ?? "", + ); + + if (error == null || error.isEmpty) { + return Container(); + } else { + return Align( + alignment: Alignment.topLeft, + child: Padding( + padding: const EdgeInsets.only( + left: 12.0, + top: 4.0, + ), + child: Text( + error, + textAlign: TextAlign.left, + style: STextStyles.label( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textError, + ), ), ), - ), - ); - } - }, - ), - const SizedBox(height: 12), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Amount", - style: STextStyles.smallMed12(context), - textAlign: TextAlign.left, - ), - // CustomTextButton( - // text: "Send all ${tokenContract.symbol}", - // onTap: () async { - // cryptoAmountController.text = ref - // .read(tokenServiceProvider)! - // .balance - // .getSpendable() - // .toStringAsFixed(tokenContract.decimals); - // - // _cryptoAmountChanged(); - // }, - // ), - ], - ), - const SizedBox(height: 8), - TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - style: STextStyles.smallMed14(context).copyWith( - color: - Theme.of( - context, - ).extension()!.textDark, - ), - key: const Key( - "amountInputFieldCryptoTextFieldKey", + ); + } + }, ), - controller: cryptoAmountController, - focusNode: _cryptoFocus, - keyboardType: - Util.isDesktop - ? null - : const TextInputType.numberWithOptions( - signed: false, - decimal: true, - ), - textAlign: TextAlign.right, - inputFormatters: [ - AmountInputFormatter( - decimals: tokenContract.decimals, - unit: ref.watch(pAmountUnit(coin)), - locale: locale, - ), - // // regex to validate a crypto amount with 8 decimal places - // TextInputFormatter.withFunction((oldValue, - // newValue) => - // RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$') - // .hasMatch(newValue.text) - // ? newValue - // : oldValue), - ], - decoration: InputDecoration( - contentPadding: const EdgeInsets.only( - top: 12, - right: 12, - ), - hintText: "0", - hintStyle: STextStyles.fieldLabel( - context, - ).copyWith(fontSize: 14), - prefixIcon: FittedBox( - fit: BoxFit.scaleDown, - child: Padding( - padding: const EdgeInsets.all(12), - child: Text( - ref - .watch(pAmountUnit(coin)) - .unitForContract(tokenContract), - style: STextStyles.smallMed14( - context, - ).copyWith( - color: - Theme.of(context) - .extension()! - .accentColorDark, - ), - ), + const SizedBox(height: 12), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Amount", + style: STextStyles.smallMed12(context), + textAlign: TextAlign.left, ), - ), + // CustomTextButton( + // text: "Send all ${tokenContract.symbol}", + // onTap: () async { + // cryptoAmountController.text = ref + // .read(tokenServiceProvider)! + // .balance + // .getSpendable() + // .toStringAsFixed(tokenContract.decimals); + // + // _cryptoAmountChanged(); + // }, + // ), + ], ), - ), - if (Prefs.instance.externalCalls) const SizedBox(height: 8), - if (Prefs.instance.externalCalls) TextField( autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, @@ -1032,10 +966,10 @@ class _TokenSendViewState extends ConsumerState { ).extension()!.textDark, ), key: const Key( - "amountInputFieldFiatTextFieldKey", + "amountInputFieldCryptoTextFieldKey", ), - controller: baseAmountController, - focusNode: _baseFocus, + controller: cryptoAmountController, + focusNode: _cryptoFocus, keyboardType: Util.isDesktop ? null @@ -1046,18 +980,18 @@ class _TokenSendViewState extends ConsumerState { textAlign: TextAlign.right, inputFormatters: [ AmountInputFormatter( - decimals: 2, + decimals: tokenContract.decimals, + unit: ref.watch(pAmountUnit(coin)), locale: locale, ), - // // regex to validate a fiat amount with 2 decimal places + // // regex to validate a crypto amount with 8 decimal places // TextInputFormatter.withFunction((oldValue, // newValue) => - // RegExp(r'^([0-9]*[,.]?[0-9]{0,2}|[,.][0-9]{0,2})$') + // RegExp(r'^([0-9]*[,.]?[0-9]{0,8}|[,.][0-9]{0,8})$') // .hasMatch(newValue.text) // ? newValue // : oldValue), ], - onChanged: _onFiatAmountFieldChanged, decoration: InputDecoration( contentPadding: const EdgeInsets.only( top: 12, @@ -1072,11 +1006,9 @@ class _TokenSendViewState extends ConsumerState { child: Padding( padding: const EdgeInsets.all(12), child: Text( - ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.currency, - ), - ), + ref + .watch(pAmountUnit(coin)) + .unitForContract(tokenContract), style: STextStyles.smallMed14( context, ).copyWith( @@ -1090,243 +1022,321 @@ class _TokenSendViewState extends ConsumerState { ), ), ), - const SizedBox(height: 12), - Text( - "Note (optional)", - style: STextStyles.smallMed12(context), - textAlign: TextAlign.left, - ), - const SizedBox(height: 8), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - controller: noteController, - focusNode: _noteFocusNode, - style: STextStyles.field(context), - onChanged: (_) => setState(() {}), - decoration: standardInputDecoration( - "Type something...", - _noteFocusNode, - context, - ).copyWith( - suffixIcon: - noteController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only( - right: 0, - ), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - noteController.text = ""; - }); - }, - ), - ], - ), + if (Prefs.instance.externalCalls) + const SizedBox(height: 8), + if (Prefs.instance.externalCalls) + TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: + Util.isDesktop ? false : true, + style: STextStyles.smallMed14(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, + ), + key: const Key( + "amountInputFieldFiatTextFieldKey", + ), + controller: baseAmountController, + focusNode: _baseFocus, + keyboardType: + Util.isDesktop + ? null + : const TextInputType.numberWithOptions( + signed: false, + decimal: true, + ), + textAlign: TextAlign.right, + inputFormatters: [ + AmountInputFormatter( + decimals: 2, + locale: locale, + ), + // // regex to validate a fiat amount with 2 decimal places + // TextInputFormatter.withFunction((oldValue, + // newValue) => + // RegExp(r'^([0-9]*[,.]?[0-9]{0,2}|[,.][0-9]{0,2})$') + // .hasMatch(newValue.text) + // ? newValue + // : oldValue), + ], + onChanged: _onFiatAmountFieldChanged, + decoration: InputDecoration( + contentPadding: const EdgeInsets.only( + top: 12, + right: 12, + ), + hintText: "0", + hintStyle: STextStyles.fieldLabel( + context, + ).copyWith(fontSize: 14), + prefixIcon: FittedBox( + fit: BoxFit.scaleDown, + child: Padding( + padding: const EdgeInsets.all(12), + child: Text( + ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.currency, ), - ) - : null, + ), + style: STextStyles.smallMed14( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorDark, + ), + ), + ), + ), + ), ), + const SizedBox(height: 12), + Text( + "Note (optional)", + style: STextStyles.smallMed12(context), + textAlign: TextAlign.left, ), - ), - const SizedBox(height: 12), - Text( - "Transaction fee ${isCustomFee.value ? "" : "(max)"}", - style: STextStyles.smallMed12(context), - textAlign: TextAlign.left, - ), - const SizedBox(height: 8), - Stack( - children: [ - TextField( + const SizedBox(height: 8), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, - controller: feeController, - readOnly: true, - textInputAction: TextInputAction.none, + controller: noteController, + focusNode: _noteFocusNode, + style: STextStyles.field(context), + onChanged: (_) => setState(() {}), + decoration: standardInputDecoration( + "Type something...", + _noteFocusNode, + context, + ).copyWith( + suffixIcon: + noteController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only( + right: 0, + ), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + noteController.text = + ""; + }); + }, + ), + ], + ), + ), + ) + : null, + ), ), - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, + ), + const SizedBox(height: 12), + Text( + "Transaction fee ${isCustomFee.value ? "" : "(max)"}", + style: STextStyles.smallMed12(context), + textAlign: TextAlign.left, + ), + const SizedBox(height: 8), + Stack( + children: [ + TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: + Util.isDesktop ? false : true, + controller: feeController, + readOnly: true, + textInputAction: TextInputAction.none, ), - child: RawMaterialButton( - splashColor: - Theme.of( - context, - ).extension()!.highlight, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, ), - onPressed: () { - showModalBottomSheet( - backgroundColor: Colors.transparent, - context: context, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical( - top: Radius.circular(20), - ), + child: RawMaterialButton( + splashColor: + Theme.of( + context, + ).extension()!.highlight, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - builder: - (_) => TransactionFeeSelectionSheet( - walletId: walletId, - isToken: true, - amount: (Decimal.tryParse( - cryptoAmountController - .text, - ) ?? - Decimal.zero) - .toAmount( - fractionDigits: - tokenContract.decimals, - ), - updateChosen: (String fee) { - if (fee == "custom") { - if (!isCustomFee.value) { - setState(() { - isCustomFee.value = true; - }); + ), + onPressed: () { + showModalBottomSheet( + backgroundColor: Colors.transparent, + context: context, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(20), + ), + ), + builder: + (_) => TransactionFeeSelectionSheet( + walletId: walletId, + isToken: true, + amount: (Decimal.tryParse( + cryptoAmountController + .text, + ) ?? + Decimal.zero) + .toAmount( + fractionDigits: + tokenContract.decimals, + ), + updateChosen: (String fee) { + if (fee == "custom") { + if (!isCustomFee.value) { + setState(() { + isCustomFee.value = true; + }); + } + return; } - return; - } - setState(() { - _calculateFeesFuture = Future( - () => fee, - ); - if (isCustomFee.value) { - isCustomFee.value = false; + setState(() { + _calculateFeesFuture = Future( + () => fee, + ); + if (isCustomFee.value) { + isCustomFee.value = false; + } + }); + }, + ), + ); + }, + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Text( + ref + .watch( + feeRateTypeMobileStateProvider + .state, + ) + .state + .prettyName, + style: STextStyles.itemSubtitle12( + context, + ), + ), + const SizedBox(width: 10), + FutureBuilder( + future: _calculateFeesFuture, + builder: (context, snapshot) { + if (snapshot.connectionState == + ConnectionState.done && + snapshot.hasData) { + return Text( + isCustomFee.value + ? "" + : "~${snapshot.data!}", + style: + STextStyles.itemSubtitle( + context, + ), + ); + } else { + return AnimatedText( + stringsToLoopThrough: + const [ + "Calculating", + "Calculating.", + "Calculating..", + "Calculating...", + ], + style: + STextStyles.itemSubtitle( + context, + ), + ); } - }); - }, - ), - ); - }, - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Text( - ref - .watch( - feeRateTypeMobileStateProvider - .state, - ) - .state - .prettyName, - style: STextStyles.itemSubtitle12( - context, + }, ), + ], + ), + SvgPicture.asset( + Assets.svg.chevronDown, + width: 8, + height: 4, + colorFilter: ColorFilter.mode( + Theme.of(context) + .extension()! + .textSubtitle2, + BlendMode.srcIn, ), - const SizedBox(width: 10), - FutureBuilder( - future: _calculateFeesFuture, - builder: (context, snapshot) { - if (snapshot.connectionState == - ConnectionState.done && - snapshot.hasData) { - return Text( - isCustomFee.value - ? "" - : "~${snapshot.data!}", - style: - STextStyles.itemSubtitle( - context, - ), - ); - } else { - return AnimatedText( - stringsToLoopThrough: const [ - "Calculating", - "Calculating.", - "Calculating..", - "Calculating...", - ], - style: - STextStyles.itemSubtitle( - context, - ), - ); - } - }, - ), - ], - ), - SvgPicture.asset( - Assets.svg.chevronDown, - width: 8, - height: 4, - colorFilter: ColorFilter.mode( - Theme.of(context) - .extension()! - .textSubtitle2, - BlendMode.srcIn, ), - ), - ], + ], + ), ), ), - ), - ], - ), - if (isCustomFee.value) const SizedBox(height: 12), - if (isCustomFee.value) - EthFeeForm( - minGasLimit: kEthereumTokenMinGasLimit, - stateChanged: (value) => ethFee = value, + ], ), - const Spacer(), - const SizedBox(height: 12), - TextButton( - onPressed: - ref - .watch( - previewTokenTxButtonStateProvider - .state, - ) - .state - ? _previewTransaction - : null, - style: - ref - .watch( - previewTokenTxButtonStateProvider - .state, - ) - .state - ? Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context) - : Theme.of(context) - .extension()! - .getPrimaryDisabledButtonStyle(context), - child: Text( - "Preview", - style: STextStyles.button(context), + if (isCustomFee.value) const SizedBox(height: 12), + if (isCustomFee.value) + EthFeeForm( + minGasLimit: kEthereumTokenMinGasLimit, + stateChanged: (value) => ethFee = value, + ), + const Spacer(), + const SizedBox(height: 12), + TextButton( + onPressed: + ref + .watch( + previewTokenTxButtonStateProvider + .state, + ) + .state + ? _previewTransaction + : null, + style: + ref + .watch( + previewTokenTxButtonStateProvider + .state, + ) + .state + ? Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context) + : Theme.of(context) + .extension()! + .getPrimaryDisabledButtonStyle( + context, + ), + child: Text( + "Preview", + style: STextStyles.button(context), + ), ), - ), - const SizedBox(height: 16), - ], + const SizedBox(height: 16), + ], + ), ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ); diff --git a/lib/pages/settings_views/global_settings_view/about_view.dart b/lib/pages/settings_views/global_settings_view/about_view.dart index b72c3222c..404490163 100644 --- a/lib/pages/settings_views/global_settings_view/about_view.dart +++ b/lib/pages/settings_views/global_settings_view/about_view.dart @@ -40,324 +40,280 @@ class AboutView extends ConsumerWidget { Navigator.of(context).pop(); }, ), - title: Text( - "About", - style: STextStyles.navBarTitle(context), - ), + title: Text("About", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - FutureBuilder( - future: PackageInfo.fromPlatform(), - builder: - (context, AsyncSnapshot snapshot) { - String version = ""; - String signature = ""; - String appName = ""; - String build = ""; + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + FutureBuilder( + future: PackageInfo.fromPlatform(), + builder: ( + context, + AsyncSnapshot snapshot, + ) { + String version = ""; + String signature = ""; + String appName = ""; + String build = ""; - if (snapshot.connectionState == - ConnectionState.done && - snapshot.hasData) { - version = snapshot.data!.version; - build = snapshot.data!.buildNumber; - signature = snapshot.data!.buildSignature; - appName = snapshot.data!.appName; - } + if (snapshot.connectionState == + ConnectionState.done && + snapshot.hasData) { + version = snapshot.data!.version; + build = snapshot.data!.buildNumber; + signature = snapshot.data!.buildSignature; + appName = snapshot.data!.appName; + } - return Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Center( - child: Text( - appName, - style: STextStyles.pageTitleH2(context), + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Center( + child: Text( + appName, + style: STextStyles.pageTitleH2(context), + ), ), - ), - const SizedBox( - height: 24, - ), - RoundedWhiteContainer( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.stretch, - children: [ - Text( - "Version", - style: STextStyles.titleBold12(context), - ), - const SizedBox( - height: 4, - ), - SelectableText( - version, - style: - STextStyles.itemSubtitle(context), - ), - ], + const SizedBox(height: 24), + RoundedWhiteContainer( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.stretch, + children: [ + Text( + "Version", + style: STextStyles.titleBold12( + context, + ), + ), + const SizedBox(height: 4), + SelectableText( + version, + style: STextStyles.itemSubtitle( + context, + ), + ), + ], + ), ), - ), - const SizedBox( - height: 12, - ), - RoundedWhiteContainer( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.stretch, - children: [ - Text( - "Build number", - style: STextStyles.titleBold12(context), - ), - const SizedBox( - height: 4, - ), - SelectableText( - build, - style: - STextStyles.itemSubtitle(context), - ), - ], + const SizedBox(height: 12), + RoundedWhiteContainer( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.stretch, + children: [ + Text( + "Build number", + style: STextStyles.titleBold12( + context, + ), + ), + const SizedBox(height: 4), + SelectableText( + build, + style: STextStyles.itemSubtitle( + context, + ), + ), + ], + ), ), - ), - const SizedBox( - height: 12, - ), - RoundedWhiteContainer( + const SizedBox(height: 12), + RoundedWhiteContainer( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.stretch, + children: [ + Text( + "Build commit", + style: STextStyles.titleBold12( + context, + ), + ), + const SizedBox(height: 4), + SelectableText( + GitStatus.appCommitHash, + style: STextStyles.itemSubtitle( + context, + ), + ), + ], + ), + ), + const SizedBox(height: 12), + RoundedWhiteContainer( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.stretch, + children: [ + Text( + "Build signature", + style: STextStyles.titleBold12( + context, + ), + ), + const SizedBox(height: 4), + SelectableText( + signature, + style: STextStyles.itemSubtitle( + context, + ), + ), + ], + ), + ), + ], + ); + }, + ), + if (AppConfig.coins.whereType().isNotEmpty) + const SizedBox(height: 12), + if (AppConfig.coins.whereType().isNotEmpty) + FutureBuilder( + future: GitStatus.getFiroCommitStatus(), + builder: ( + context, + AsyncSnapshot snapshot, + ) { + CommitStatus stateOfCommit = + CommitStatus.notLoaded; + + if (snapshot.connectionState == + ConnectionState.done && + snapshot.hasData) { + stateOfCommit = snapshot.data!; + } + return RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Text( - "Build commit", + "Firo Build Commit", style: STextStyles.titleBold12(context), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), SelectableText( - GitStatus.appCommitHash, - style: - STextStyles.itemSubtitle(context), + GitStatus.firoCommit, + style: GitStatus.styleForStatus( + stateOfCommit, + context, + ), ), ], ), - ), - const SizedBox( - height: 12, - ), - RoundedWhiteContainer( + ); + }, + ), + if (AppConfig.coins.whereType().isNotEmpty) + const SizedBox(height: 12), + if (AppConfig.coins.whereType().isNotEmpty) + FutureBuilder( + future: GitStatus.getEpicCommitStatus(), + builder: ( + context, + AsyncSnapshot snapshot, + ) { + CommitStatus stateOfCommit = + CommitStatus.notLoaded; + + if (snapshot.connectionState == + ConnectionState.done && + snapshot.hasData) { + stateOfCommit = snapshot.data!; + } + + return RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Text( - "Build signature", + "Epic Cash Build Commit", style: STextStyles.titleBold12(context), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), SelectableText( - signature, - style: - STextStyles.itemSubtitle(context), + GitStatus.epicCashCommit, + style: GitStatus.styleForStatus( + stateOfCommit, + context, + ), ), ], ), - ), - ], - ); - }, - ), - if (AppConfig.coins.whereType().isNotEmpty) - const SizedBox( - height: 12, - ), - if (AppConfig.coins.whereType().isNotEmpty) - FutureBuilder( - future: GitStatus.getFiroCommitStatus(), - builder: ( - context, - AsyncSnapshot snapshot, - ) { - CommitStatus stateOfCommit = - CommitStatus.notLoaded; - - if (snapshot.connectionState == - ConnectionState.done && - snapshot.hasData) { - stateOfCommit = snapshot.data!; - } - return RoundedWhiteContainer( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.stretch, - children: [ - Text( - "Firo Build Commit", - style: STextStyles.titleBold12(context), - ), - const SizedBox( - height: 4, - ), - SelectableText( - GitStatus.firoCommit, - style: GitStatus.styleForStatus( - stateOfCommit, - context, - ), - ), - ], - ), - ); - }, - ), - if (AppConfig.coins.whereType().isNotEmpty) - const SizedBox( - height: 12, - ), - if (AppConfig.coins.whereType().isNotEmpty) - FutureBuilder( - future: GitStatus.getEpicCommitStatus(), - builder: ( - context, - AsyncSnapshot snapshot, - ) { - CommitStatus stateOfCommit = - CommitStatus.notLoaded; - - if (snapshot.connectionState == - ConnectionState.done && - snapshot.hasData) { - stateOfCommit = snapshot.data!; - } - - return RoundedWhiteContainer( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.stretch, - children: [ - Text( - "Epic Cash Build Commit", - style: STextStyles.titleBold12(context), - ), - const SizedBox( - height: 4, - ), - SelectableText( - GitStatus.epicCashCommit, - style: GitStatus.styleForStatus( - stateOfCommit, - context, - ), - ), - ], - ), - ); - }, - ), - if (AppConfig.coins.whereType().isNotEmpty) - const SizedBox( - height: 12, - ), - // if (AppConfig.coins.whereType().isNotEmpty) - // FutureBuilder( - // future: GitStatus.getMoneroCommitStatus(), - // builder: ( - // context, - // AsyncSnapshot snapshot, - // ) { - // CommitStatus stateOfCommit = - // CommitStatus.notLoaded; - // - // if (snapshot.connectionState == - // ConnectionState.done && - // snapshot.hasData) { - // stateOfCommit = snapshot.data!; - // } - // return RoundedWhiteContainer( - // child: Column( - // crossAxisAlignment: - // CrossAxisAlignment.stretch, - // children: [ - // Text( - // "Monero Build Commit", - // style: STextStyles.titleBold12(context), - // ), - // const SizedBox( - // height: 4, - // ), - // SelectableText( - // GitStatus.moneroCommit, - // style: GitStatus.styleForStatus( - // stateOfCommit, - // context, - // ), - // ), - // ], - // ), - // ); - // }, - // ), - // const SizedBox( - // height: 12, - // ), - RoundedWhiteContainer( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Website", - style: STextStyles.titleBold12(context), - ), - const SizedBox( - height: 4, - ), - CustomTextButton( - text: "https://stackwallet.com", - onTap: () { - launchUrl( - Uri.parse("https://stackwallet.com"), - mode: LaunchMode.externalApplication, - ); - }, - ), - ], - ), - ), - if (AppConfig.coins.whereType().isNotEmpty) - const SizedBox( - height: 12, - ), - if (AppConfig.coins.whereType().isNotEmpty) + ); + }, + ), + if (AppConfig.coins.whereType().isNotEmpty) + const SizedBox(height: 12), + // if (AppConfig.coins.whereType().isNotEmpty) + // FutureBuilder( + // future: GitStatus.getMoneroCommitStatus(), + // builder: ( + // context, + // AsyncSnapshot snapshot, + // ) { + // CommitStatus stateOfCommit = + // CommitStatus.notLoaded; + // + // if (snapshot.connectionState == + // ConnectionState.done && + // snapshot.hasData) { + // stateOfCommit = snapshot.data!; + // } + // return RoundedWhiteContainer( + // child: Column( + // crossAxisAlignment: + // CrossAxisAlignment.stretch, + // children: [ + // Text( + // "Monero Build Commit", + // style: STextStyles.titleBold12(context), + // ), + // const SizedBox( + // height: 4, + // ), + // SelectableText( + // GitStatus.moneroCommit, + // style: GitStatus.styleForStatus( + // stateOfCommit, + // context, + // ), + // ), + // ], + // ), + // ); + // }, + // ), + // const SizedBox( + // height: 12, + // ), RoundedWhiteContainer( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Tezos functionality", + "Website", style: STextStyles.titleBold12(context), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), CustomTextButton( - text: "Powered by TzKT API", + text: "https://stackwallet.com", onTap: () { launchUrl( - Uri.parse("https://tzkt.io"), + Uri.parse("https://stackwallet.com"), mode: LaunchMode.externalApplication, ); }, @@ -365,55 +321,82 @@ class AboutView extends ConsumerWidget { ], ), ), - const SizedBox( - height: 12, - ), - const Spacer(), - RichText( - textAlign: TextAlign.center, - text: TextSpan( - style: STextStyles.label(context), - children: [ - const TextSpan( - text: - "By using ${AppConfig.appName}, you agree to the ", - ), - TextSpan( - text: "Terms of service", - style: STextStyles.richLink(context), - recognizer: TapGestureRecognizer() - ..onTap = () { - launchUrl( - Uri.parse( - "https://stackwallet.com/terms-of-service.html", - ), - mode: LaunchMode.externalApplication, - ); - }, - ), - const TextSpan(text: " and "), - TextSpan( - text: "Privacy policy", - style: STextStyles.richLink(context), - recognizer: TapGestureRecognizer() - ..onTap = () { - launchUrl( - Uri.parse( - "https://stackwallet.com/privacy-policy.html", - ), - mode: LaunchMode.externalApplication, - ); - }, + if (AppConfig.coins.whereType().isNotEmpty) + const SizedBox(height: 12), + if (AppConfig.coins.whereType().isNotEmpty) + RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Tezos functionality", + style: STextStyles.titleBold12(context), + ), + const SizedBox(height: 4), + CustomTextButton( + text: "Powered by TzKT API", + onTap: () { + launchUrl( + Uri.parse("https://tzkt.io"), + mode: LaunchMode.externalApplication, + ); + }, + ), + ], ), - ], + ), + const SizedBox(height: 12), + const Spacer(), + RichText( + textAlign: TextAlign.center, + text: TextSpan( + style: STextStyles.label(context), + children: [ + const TextSpan( + text: + "By using ${AppConfig.appName}, you agree to the ", + ), + TextSpan( + text: "Terms of service", + style: STextStyles.richLink(context), + recognizer: + TapGestureRecognizer() + ..onTap = () { + launchUrl( + Uri.parse( + "https://stackwallet.com/terms-of-service.html", + ), + mode: + LaunchMode.externalApplication, + ); + }, + ), + const TextSpan(text: " and "), + TextSpan( + text: "Privacy policy", + style: STextStyles.richLink(context), + recognizer: + TapGestureRecognizer() + ..onTap = () { + launchUrl( + Uri.parse( + "https://stackwallet.com/privacy-policy.html", + ), + mode: + LaunchMode.externalApplication, + ); + }, + ), + ], + ), ), - ), - ], + ], + ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/advanced_views/advanced_settings_view.dart b/lib/pages/settings_views/global_settings_view/advanced_views/advanced_settings_view.dart index d86f17526..20f880dd7 100644 --- a/lib/pages/settings_views/global_settings_view/advanced_views/advanced_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/advanced_views/advanced_settings_view.dart @@ -28,9 +28,7 @@ import 'manage_coin_units/manage_coin_units_view.dart'; import 'manage_explorer_view.dart'; class AdvancedSettingsView extends StatelessWidget { - const AdvancedSettingsView({ - super.key, - }); + const AdvancedSettingsView({super.key}); static const String routeName = "/advancedSettings"; @@ -47,149 +45,93 @@ class AdvancedSettingsView extends StatelessWidget { Navigator.of(context).pop(); }, ), - title: Text( - "Advanced", - style: STextStyles.navBarTitle(context), - ), + title: Text("Advanced", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: () { - Navigator.of(context) - .pushNamed(LoggingSettingsView.routeName); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 20, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - child: Row( - children: [ - Text( - "Logging", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - ], + onPressed: () { + Navigator.of( + context, + ).pushNamed(LoggingSettingsView.routeName); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 20, + ), + child: Row( + children: [ + Text( + "Logging", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + ], + ), ), ), ), - ), - const SizedBox( - height: 8, - ), - RoundedWhiteContainer( - child: Consumer( - builder: (_, ref, __) { - return RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + const SizedBox(height: 8), + RoundedWhiteContainer( + child: Consumer( + builder: (_, ref, __) { + return RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - ), - onPressed: null, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Toggle testnet coins", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.showTestNetCoins, - ), - ), - onValueChanged: (newValue) { - ref - .read(prefsChangeNotifierProvider) - .showTestNetCoins = newValue; - }, + onPressed: null, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Toggle testnet coins", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, ), - ), - ], - ), - ), - ); - }, - ), - ), - const SizedBox( - height: 8, - ), - RoundedWhiteContainer( - child: Consumer( - builder: (_, ref, __) { - return RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: null, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Enable coin control", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.enableCoinControl, + SizedBox( + height: 20, + width: 40, + child: DraggableSwitchButton( + isOn: ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.showTestNetCoins, + ), ), + onValueChanged: (newValue) { + ref + .read(prefsChangeNotifierProvider) + .showTestNetCoins = newValue; + }, ), - onValueChanged: (newValue) { - ref - .read(prefsChangeNotifierProvider) - .enableCoinControl = newValue; - }, ), - ), - ], + ], + ), ), - ), - ); - }, - ), - ), - // showExchange pref. - if (Constants.enableExchange) - const SizedBox( - height: 8, + ); + }, + ), ), - if (Constants.enableExchange) + const SizedBox(height: 8), RoundedWhiteContainer( child: Consumer( builder: (_, ref, __) { @@ -208,7 +150,7 @@ class AdvancedSettingsView extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - "Enable exchange features", + "Enable coin control", style: STextStyles.titleBold12(context), textAlign: TextAlign.left, ), @@ -218,13 +160,13 @@ class AdvancedSettingsView extends StatelessWidget { child: DraggableSwitchButton( isOn: ref.watch( prefsChangeNotifierProvider.select( - (value) => value.enableExchange, + (value) => value.enableCoinControl, ), ), onValueChanged: (newValue) { ref .read(prefsChangeNotifierProvider) - .enableExchange = newValue; + .enableCoinControl = newValue; }, ), ), @@ -235,138 +177,185 @@ class AdvancedSettingsView extends StatelessWidget { }, ), ), - const SizedBox( - height: 8, - ), - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: Consumer( - builder: (_, ref, __) { - final externalCalls = ref.watch( - prefsChangeNotifierProvider - .select((value) => value.externalCalls), - ); - return RawMaterialButton( - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: () { - Navigator.of(context).pushNamed( - StackPrivacyCalls.routeName, - arguments: true, + // showExchange pref. + if (Constants.enableExchange) const SizedBox(height: 8), + if (Constants.enableExchange) + RoundedWhiteContainer( + child: Consumer( + builder: (_, ref, __) { + return RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: null, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Enable exchange features", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + SizedBox( + height: 20, + width: 40, + child: DraggableSwitchButton( + isOn: ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.enableExchange, + ), + ), + onValueChanged: (newValue) { + ref + .read(prefsChangeNotifierProvider) + .enableExchange = newValue; + }, + ), + ), + ], + ), + ), ); }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 20, + ), + ), + const SizedBox(height: 8), + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: Consumer( + builder: (_, ref, __) { + final externalCalls = ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.externalCalls, ), - child: Row( - children: [ - RichText( - textAlign: TextAlign.left, - text: TextSpan( - children: [ - TextSpan( - text: "${AppConfig.prefix} Experience", - style: STextStyles.titleBold12(context), - ), - TextSpan( - text: externalCalls - ? "\nEasy crypto" - : "\nIncognito", - style: STextStyles.label(context) - .copyWith(fontSize: 15.0), - ), - ], + ); + return RawMaterialButton( + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: () { + Navigator.of(context).pushNamed( + StackPrivacyCalls.routeName, + arguments: true, + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 20, + ), + child: Row( + children: [ + RichText( + textAlign: TextAlign.left, + text: TextSpan( + children: [ + TextSpan( + text: "${AppConfig.prefix} Experience", + style: STextStyles.titleBold12(context), + ), + TextSpan( + text: + externalCalls + ? "\nEasy crypto" + : "\nIncognito", + style: STextStyles.label( + context, + ).copyWith(fontSize: 15.0), + ), + ], + ), ), - ), - ], + ], + ), ), - ), - ); - }, - ), - ), - const SizedBox( - height: 8, - ), - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), + ); + }, ), - onPressed: () { - Navigator.of(context).pushNamed( - ChooseCoinView.routeName, - arguments: const Tuple3( - "Manage block explorers", - "block explorer", - ManageExplorerView.routeName, + ), + const SizedBox(height: 8), + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 20, ), - child: Row( - children: [ - Text( - "Change block explorer", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, + onPressed: () { + Navigator.of(context).pushNamed( + ChooseCoinView.routeName, + arguments: const Tuple3( + "Manage block explorers", + "block explorer", + ManageExplorerView.routeName, ), - ], + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 20, + ), + child: Row( + children: [ + Text( + "Change block explorer", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + ], + ), ), ), ), - ), - const SizedBox( - height: 8, - ), - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: () { - Navigator.of(context).pushNamed( - ManageCoinUnitsView.routeName, - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 20, + const SizedBox(height: 8), + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - child: Row( - children: [ - Text( - "Units", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - ], + onPressed: () { + Navigator.of( + context, + ).pushNamed(ManageCoinUnitsView.routeName); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 20, + ), + child: Row( + children: [ + Text( + "Units", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + ], + ), ), ), ), - ), - ], + ], + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/advanced_views/manage_coin_units/edit_coin_units_view.dart b/lib/pages/settings_views/global_settings_view/advanced_views/manage_coin_units/edit_coin_units_view.dart index 08d801cc4..661939aef 100644 --- a/lib/pages/settings_views/global_settings_view/advanced_views/manage_coin_units/edit_coin_units_view.dart +++ b/lib/pages/settings_views/global_settings_view/advanced_views/manage_coin_units/edit_coin_units_view.dart @@ -154,9 +154,11 @@ class _EditCoinUnitsViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: child, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: child, + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/advanced_views/manage_coin_units/manage_coin_units_view.dart b/lib/pages/settings_views/global_settings_view/advanced_views/manage_coin_units/manage_coin_units_view.dart index 28ebe18a9..af5838eff 100644 --- a/lib/pages/settings_views/global_settings_view/advanced_views/manage_coin_units/manage_coin_units_view.dart +++ b/lib/pages/settings_views/global_settings_view/advanced_views/manage_coin_units/manage_coin_units_view.dart @@ -99,7 +99,7 @@ class ManageCoinUnitsView extends ConsumerWidget { style: STextStyles.navBarTitle(context), ), ), - body: child, + body: SafeArea(child: child), ), ), child: ListView.separated( diff --git a/lib/pages/settings_views/global_settings_view/advanced_views/manage_explorer_view.dart b/lib/pages/settings_views/global_settings_view/advanced_views/manage_explorer_view.dart index 1260aa70d..486da8184 100644 --- a/lib/pages/settings_views/global_settings_view/advanced_views/manage_explorer_view.dart +++ b/lib/pages/settings_views/global_settings_view/advanced_views/manage_explorer_view.dart @@ -21,10 +21,7 @@ import '../../../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../../../widgets/rounded_white_container.dart'; class ManageExplorerView extends ConsumerStatefulWidget { - const ManageExplorerView({ - super.key, - required this.coin, - }); + const ManageExplorerView({super.key, required this.coin}); static const String routeName = "/manageExplorer"; @@ -41,9 +38,10 @@ class _ManageExplorerViewState extends ConsumerState { void initState() { super.initState(); textEditingController = TextEditingController( - text: getBlockExplorerTransactionUrlFor(coin: widget.coin, txid: "[TXID]") - .toString() - .replaceAll("%5BTXID%5D", "[TXID]"), + text: getBlockExplorerTransactionUrlFor( + coin: widget.coin, + txid: "[TXID]", + ).toString().replaceAll("%5BTXID%5D", "[TXID]"), ); } @@ -69,71 +67,66 @@ class _ManageExplorerViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: Column( - children: [ - Expanded( - child: Column( - children: [ - TextField( - controller: textEditingController, - decoration: const InputDecoration( - border: OutlineInputBorder(), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + children: [ + Expanded( + child: Column( + children: [ + TextField( + controller: textEditingController, + decoration: const InputDecoration( + border: OutlineInputBorder(), + ), ), - ), - const SizedBox( - height: 8, - ), - RoundedWhiteContainer( - child: Center( - child: Text( - "Edit your block explorer above. Keep in mind that " - "every block explorer has a slightly different URL " - "scheme.\n\nPaste in your block explorer of choice," - " then edit in [TXID] where the transaction ID " - "should go, and ${AppConfig.appName} will auto fill the " - "transaction ID in that place of URL.", - style: STextStyles.itemSubtitle(context), + const SizedBox(height: 8), + RoundedWhiteContainer( + child: Center( + child: Text( + "Edit your block explorer above. Keep in mind that " + "every block explorer has a slightly different URL " + "scheme.\n\nPaste in your block explorer of choice," + " then edit in [TXID] where the transaction ID " + "should go, and ${AppConfig.appName} will auto fill the " + "transaction ID in that place of URL.", + style: STextStyles.itemSubtitle(context), + ), ), ), - ), - ], - ), - ), - Align( - alignment: Alignment.bottomCenter, - child: ConstrainedBox( - constraints: const BoxConstraints( - minWidth: 480, - minHeight: 70, + ], ), - child: TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - onPressed: () async { - textEditingController.text = - textEditingController.text.trim(); - await setBlockExplorerForCoin( - coin: widget.coin, - url: Uri.parse( - textEditingController.text, - ), - ); + ), + Align( + alignment: Alignment.bottomCenter, + child: ConstrainedBox( + constraints: const BoxConstraints( + minWidth: 480, + minHeight: 70, + ), + child: TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + onPressed: () async { + textEditingController.text = + textEditingController.text.trim(); + await setBlockExplorerForCoin( + coin: widget.coin, + url: Uri.parse(textEditingController.text), + ); - if (mounted) { - Navigator.of(context).pop(); - } - }, - child: Text( - "Save", - style: STextStyles.button(context), + if (mounted) { + Navigator.of(context).pop(); + } + }, + child: Text("Save", style: STextStyles.button(context)), ), ), ), - ), - ], + ], + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/appearance_settings/appearance_settings_view.dart b/lib/pages/settings_views/global_settings_view/appearance_settings/appearance_settings_view.dart index fe17f8ffc..aa10724a7 100644 --- a/lib/pages/settings_views/global_settings_view/appearance_settings/appearance_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/appearance_settings/appearance_settings_view.dart @@ -39,125 +39,124 @@ class AppearanceSettingsView extends ConsumerWidget { Navigator.of(context).pop(); }, ), - title: Text( - "Appearance", - style: STextStyles.navBarTitle(context), - ), + title: Text("Appearance", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( - child: Consumer( - builder: (_, ref, __) { - return RawMaterialButton( - splashColor: Theme.of(context) - .extension()! - .highlight, - materialTapTargetSize: - MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedWhiteContainer( + child: Consumer( + builder: (_, ref, __) { + return RawMaterialButton( + splashColor: + Theme.of( + context, + ).extension()!.highlight, + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - ), - onPressed: null, - child: Padding( - padding: - const EdgeInsets.symmetric(vertical: 8), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - "Display favorite wallets", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: ref.watch( - prefsChangeNotifierProvider.select( - (value) => - value.showFavoriteWallets, + onPressed: null, + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 8, + ), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Display favorite wallets", + style: STextStyles.titleBold12( + context, + ), + textAlign: TextAlign.left, + ), + SizedBox( + height: 20, + width: 40, + child: DraggableSwitchButton( + isOn: ref.watch( + prefsChangeNotifierProvider.select( + (value) => + value.showFavoriteWallets, + ), ), + onValueChanged: (newValue) { + ref + .read( + prefsChangeNotifierProvider, + ) + .showFavoriteWallets = newValue; + }, ), - onValueChanged: (newValue) { - ref - .read( - prefsChangeNotifierProvider, - ) - .showFavoriteWallets = newValue; - }, ), - ), - ], + ], + ), ), - ), - ); - }, + ); + }, + ), ), - ), - const SizedBox( - height: 10, - ), - RoundedWhiteContainer( - child: Column( - children: [ - Row( - children: [ - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Choose Theme", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - const SizedBox( - height: 12, - ), - const Padding( - padding: EdgeInsets.all(4), - child: ThemeOptionsWidget(), - ), - ], - ), - ], - ), - const SizedBox( - height: 12, - ), - SecondaryButton( - label: "Add more themes", - onPressed: () { - Navigator.of(context).pushNamed( - ManageThemesView.routeName, - ); - }, - ), - ], + const SizedBox(height: 10), + RoundedWhiteContainer( + child: Column( + children: [ + Row( + children: [ + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Choose Theme", + style: STextStyles.titleBold12( + context, + ), + textAlign: TextAlign.left, + ), + const SizedBox(height: 12), + const Padding( + padding: EdgeInsets.all(4), + child: ThemeOptionsWidget(), + ), + ], + ), + ], + ), + const SizedBox(height: 12), + SecondaryButton( + label: "Add more themes", + onPressed: () { + Navigator.of( + context, + ).pushNamed(ManageThemesView.routeName); + }, + ), + ], + ), ), - ), - ], + ], + ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/appearance_settings/manage_themes.dart b/lib/pages/settings_views/global_settings_view/appearance_settings/manage_themes.dart index 4744d857f..40f654603 100644 --- a/lib/pages/settings_views/global_settings_view/appearance_settings/manage_themes.dart +++ b/lib/pages/settings_views/global_settings_view/appearance_settings/manage_themes.dart @@ -13,9 +13,9 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:tuple/tuple.dart'; + import '../../../../models/isar/stack_theme.dart'; -import 'sub_widgets/install_theme_from_file_dialog.dart'; -import 'sub_widgets/stack_theme_card.dart'; import '../../../../providers/db/main_db_provider.dart'; import '../../../../providers/global/prefs_provider.dart'; import '../../../../themes/stack_colors.dart'; @@ -30,7 +30,8 @@ import '../../../../widgets/desktop/primary_button.dart'; import '../../../../widgets/desktop/secondary_button.dart'; import '../../../../widgets/loading_indicator.dart'; import '../../../../widgets/rounded_white_container.dart'; -import 'package:tuple/tuple.dart'; +import 'sub_widgets/install_theme_from_file_dialog.dart'; +import 'sub_widgets/stack_theme_card.dart'; class ManageThemesView extends ConsumerStatefulWidget { const ManageThemesView({super.key}); @@ -66,117 +67,117 @@ class _ManageThemesViewState extends ConsumerState { Widget build(BuildContext context) { return ConditionalParent( condition: !Util.isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () { - Navigator.of(context).pop(); - }, - ), - title: Text( - "Add more themes", - style: STextStyles.navBarTitle(context), - ), - actions: [ - Padding( - padding: const EdgeInsets.only(right: 2), - child: AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - icon: SvgPicture.asset( - Assets.svg.circlePlusFilled, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, - height: 20, - width: 20, - ), - onPressed: _onInstallPressed, - ), + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () { + Navigator.of(context).pop(); + }, ), - ), - ], - ), - body: _showThemes - ? Column( - children: [ - Expanded( - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16, - ), - child: IntrinsicHeight( - child: child, - ), + title: Text( + "Add more themes", + style: STextStyles.navBarTitle(context), + ), + actions: [ + Padding( + padding: const EdgeInsets.only(right: 2), + child: AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + icon: SvgPicture.asset( + Assets.svg.circlePlusFilled, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, + height: 20, + width: 20, ), - ), - ), - Padding( - padding: const EdgeInsets.all(16), - child: SecondaryButton( - label: "Install theme file", onPressed: _onInstallPressed, ), ), - ], - ) - : SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: IntrinsicHeight( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - RoundedWhiteContainer( - child: Text( - "You are using Incognito Mode. Please press the" - " button below to load available themes from our server" - " or install a theme file manually from your device.", - style: STextStyles.smallMed12(context), + ), + ], + ), + body: SafeArea( + child: + _showThemes + ? Column( + children: [ + Expanded( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16, + ), + child: IntrinsicHeight(child: child), + ), + ), ), - ), - const SizedBox( - height: 12, - ), - PrimaryButton( - label: "Load themes", - onPressed: () { - setState(() { - _showThemes = true; - future = ref.watch(pThemeService).fetchThemes; - }); - }, - ), - const SizedBox( - height: 12, - ), - SecondaryButton( - label: "Install theme file", - onPressed: _onInstallPressed, - ), - const SizedBox( - height: 16, - ), - Expanded( - child: IncognitoInstalledThemes( - cardWidth: - (MediaQuery.of(context).size.width - 48) / 2, + Padding( + padding: const EdgeInsets.all(16), + child: SecondaryButton( + label: "Install theme file", + onPressed: _onInstallPressed, + ), + ), + ], + ) + : SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: IntrinsicHeight( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + RoundedWhiteContainer( + child: Text( + "You are using Incognito Mode. Please press the" + " button below to load available themes from our server" + " or install a theme file manually from your device.", + style: STextStyles.smallMed12(context), + ), + ), + const SizedBox(height: 12), + PrimaryButton( + label: "Load themes", + onPressed: () { + setState(() { + _showThemes = true; + future = + ref + .watch(pThemeService) + .fetchThemes; + }); + }, + ), + const SizedBox(height: 12), + SecondaryButton( + label: "Install theme file", + onPressed: _onInstallPressed, + ), + const SizedBox(height: 16), + Expanded( + child: IncognitoInstalledThemes( + cardWidth: + (MediaQuery.of(context).size.width - + 48) / + 2, + ), + ), + const SizedBox(height: 16), + ], + ), ), ), - const SizedBox( - height: 16, - ), - ], - ), - ), - ), - ), - ), - ), + ), + ), + ), + ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -191,17 +192,17 @@ class _ManageThemesViewState extends ConsumerState { return Wrap( spacing: 16, runSpacing: 16, - children: snapshot.data! - .map( - (e) => SizedBox( - key: Key("ManageThemesView_card_${e.id}_key"), - width: (MediaQuery.of(context).size.width - 48) / 2, - child: StackThemeCard( - data: e, - ), - ), - ) - .toList(), + children: + snapshot.data! + .map( + (e) => SizedBox( + key: Key("ManageThemesView_card_${e.id}_key"), + width: + (MediaQuery.of(context).size.width - 48) / 2, + child: StackThemeCard(data: e), + ), + ) + .toList(), ); } else { return Center( @@ -219,10 +220,7 @@ class _ManageThemesViewState extends ConsumerState { } class IncognitoInstalledThemes extends ConsumerStatefulWidget { - const IncognitoInstalledThemes({ - super.key, - required this.cardWidth, - }); + const IncognitoInstalledThemes({super.key, required this.cardWidth}); final double cardWidth; @@ -238,28 +236,33 @@ class _IncognitoInstalledThemesState List> installedThemeIdNames = []; void _updateInstalledList() { - installedThemeIdNames = ref - .read(pThemeService) - .installedThemes - .where((e) => e.themeId != "light" && e.themeId != "dark") - .map((e) => Tuple3(e.themeId, e.name, e.version)) - .toList(); + installedThemeIdNames = + ref + .read(pThemeService) + .installedThemes + .where((e) => e.themeId != "light" && e.themeId != "dark") + .map((e) => Tuple3(e.themeId, e.name, e.version)) + .toList(); } @override void initState() { _updateInstalledList(); - _subscription = - ref.read(mainDBProvider).isar.stackThemes.watchLazy().listen((_) { - if (mounted) { - WidgetsBinding.instance.addPostFrameCallback((_) { - setState(() { - _updateInstalledList(); - }); + _subscription = ref + .read(mainDBProvider) + .isar + .stackThemes + .watchLazy() + .listen((_) { + if (mounted) { + WidgetsBinding.instance.addPostFrameCallback((_) { + setState(() { + _updateInstalledList(); + }); + }); + } }); - } - }); super.initState(); } @@ -275,24 +278,25 @@ class _IncognitoInstalledThemesState return Wrap( spacing: 16, runSpacing: 16, - children: installedThemeIdNames - .map( - (e) => SizedBox( - key: Key("IncognitoInstalledThemes_card_${e.item1}_key"), - width: widget.cardWidth, - child: StackThemeCard( - data: StackThemeMetaData( - name: e.item2, - id: e.item1, - version: e.item3 ?? 1, - sha256: "", - size: "", - previewImageUrl: "", + children: + installedThemeIdNames + .map( + (e) => SizedBox( + key: Key("IncognitoInstalledThemes_card_${e.item1}_key"), + width: widget.cardWidth, + child: StackThemeCard( + data: StackThemeMetaData( + name: e.item2, + id: e.item1, + version: e.item3 ?? 1, + sha256: "", + size: "", + previewImageUrl: "", + ), + ), ), - ), - ), - ) - .toList(), + ) + .toList(), ); } } diff --git a/lib/pages/settings_views/global_settings_view/appearance_settings/system_brightness_theme_selection_view.dart b/lib/pages/settings_views/global_settings_view/appearance_settings/system_brightness_theme_selection_view.dart index becef5fb6..d78c6cb3f 100644 --- a/lib/pages/settings_views/global_settings_view/appearance_settings/system_brightness_theme_selection_view.dart +++ b/lib/pages/settings_views/global_settings_view/appearance_settings/system_brightness_theme_selection_view.dart @@ -64,11 +64,12 @@ class _SystemBrightnessThemeSelectionViewState @override void initState() { - installedThemeIdNames = ref - .read(pThemeService) - .installedThemes - .map((e) => Tuple2(e.themeId, e.name)) - .toList(); + installedThemeIdNames = + ref + .read(pThemeService) + .installedThemes + .map((e) => Tuple2(e.themeId, e.name)) + .toList(); super.initState(); } @@ -89,52 +90,45 @@ class _SystemBrightnessThemeSelectionViewState style: STextStyles.navBarTitle(context), ), ), - body: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const SizedBox( - height: 16, - ), - RoundedWhiteContainer( - child: Text( - "Select a light and dark theme that will be" - " activated automatically when your phone system" - " switches light and dark mode.", - style: STextStyles.smallMed12(context), + body: SafeArea( + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints(minHeight: constraints.maxHeight), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const SizedBox(height: 16), + RoundedWhiteContainer( + child: Text( + "Select a light and dark theme that will be" + " activated automatically when your phone system" + " switches light and dark mode.", + style: STextStyles.smallMed12(context), + ), ), - ), - const SizedBox( - height: 10, - ), - RoundedWhiteContainer( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Choose light mode theme", - style: STextStyles.titleBold12(context), - ), - const SizedBox( - height: 18, - ), - for (int i = 0; + const SizedBox(height: 10), + RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Choose light mode theme", + style: STextStyles.titleBold12(context), + ), + const SizedBox(height: 18), + for ( + int i = 0; i < (2 * installedThemeIdNames.length) - 1; - i++) - (i % 2 == 1) - ? const SizedBox( - height: 10, - ) - : ThemeOption( + i++ + ) + (i % 2 == 1) + ? const SizedBox(height: 10) + : ThemeOption( label: installedThemeIdNames[i ~/ 2].item2, onPressed: () { @@ -170,36 +164,33 @@ class _SystemBrightnessThemeSelectionViewState installedThemeIdNames[i ~/ 2].item1, groupValue: ref.watch( prefsChangeNotifierProvider.select( - (value) => value - .systemBrightnessLightThemeId, + (value) => + value + .systemBrightnessLightThemeId, ), ), ), - ], + ], + ), ), - ), - const SizedBox( - height: 10, - ), - RoundedWhiteContainer( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Choose dark mode theme", - style: STextStyles.titleBold12(context), - ), - const SizedBox( - height: 18, - ), - for (int i = 0; + const SizedBox(height: 10), + RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Choose dark mode theme", + style: STextStyles.titleBold12(context), + ), + const SizedBox(height: 18), + for ( + int i = 0; i < (2 * installedThemeIdNames.length) - 1; - i++) - (i % 2 == 1) - ? const SizedBox( - height: 10, - ) - : ThemeOption( + i++ + ) + (i % 2 == 1) + ? const SizedBox(height: 10) + : ThemeOption( label: installedThemeIdNames[i ~/ 2].item2, onPressed: () { @@ -235,24 +226,24 @@ class _SystemBrightnessThemeSelectionViewState installedThemeIdNames[i ~/ 2].item1, groupValue: ref.watch( prefsChangeNotifierProvider.select( - (value) => value - .systemBrightnessDarkThemeId, + (value) => + value + .systemBrightnessDarkThemeId, ), ), ), - ], + ], + ), ), - ), - const SizedBox( - height: 16, - ), - ], + const SizedBox(height: 16), + ], + ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ); diff --git a/lib/pages/settings_views/global_settings_view/currency_view.dart b/lib/pages/settings_views/global_settings_view/currency_view.dart index 2f85dc445..f49671b22 100644 --- a/lib/pages/settings_views/global_settings_view/currency_view.dart +++ b/lib/pages/settings_views/global_settings_view/currency_view.dart @@ -69,20 +69,14 @@ class _CurrencyViewState extends ConsumerState { BorderRadius? _borderRadius(int index) { if (index == 0 && currenciesWithoutSelected.length == 1) { - return BorderRadius.circular( - Constants.size.circularBorderRadius, - ); + return BorderRadius.circular(Constants.size.circularBorderRadius); } else if (index == 0) { return BorderRadius.vertical( - top: Radius.circular( - Constants.size.circularBorderRadius, - ), + top: Radius.circular(Constants.size.circularBorderRadius), ); } else if (index == currenciesWithoutSelected.length - 1) { return BorderRadius.vertical( - bottom: Radius.circular( - Constants.size.circularBorderRadius, - ), + bottom: Radius.circular(Constants.size.circularBorderRadius), ); } return null; @@ -120,14 +114,16 @@ class _CurrencyViewState extends ConsumerState { final isDesktop = Util.isDesktop; if (!isDesktop) { - current = ref - .watch(prefsChangeNotifierProvider.select((value) => value.currency)); + current = ref.watch( + prefsChangeNotifierProvider.select((value) => value.currency), + ); } - currenciesWithoutSelected = ref - .watch(baseCurrenciesProvider.select((value) => value.map)) - .keys - .toList(); + currenciesWithoutSelected = + ref + .watch(baseCurrenciesProvider.select((value) => value.map)) + .keys + .toList(); if (current.isNotEmpty) { currenciesWithoutSelected.remove(current); @@ -157,18 +153,13 @@ class _CurrencyViewState extends ConsumerState { } }, ), - title: Text( - "Currency", - style: STextStyles.navBarTitle(context), - ), + title: Text("Currency", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.only( - top: 12, - left: 16, - right: 16, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only(top: 12, left: 16, right: 16), + child: child, ), - child: child, ), ), ); @@ -194,9 +185,7 @@ class _CurrencyViewState extends ConsumerState { child: child, ), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), Row( children: [ Expanded( @@ -206,9 +195,7 @@ class _CurrencyViewState extends ConsumerState { onPressed: Navigator.of(context).pop, ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: PrimaryButton( label: "Save changes", @@ -240,8 +227,9 @@ class _CurrencyViewState extends ConsumerState { headerSliverBuilder: (context, innerBoxIsScrolled) { return [ SliverOverlapAbsorber( - handle: - NestedScrollView.sliverOverlapAbsorberHandleFor(context), + handle: NestedScrollView.sliverOverlapAbsorberHandleFor( + context, + ), sliver: SliverToBoxAdapter( child: Padding( padding: const EdgeInsets.only(bottom: 16), @@ -274,26 +262,27 @@ class _CurrencyViewState extends ConsumerState { height: 16, ), ), - suffixIcon: _searchController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _searchController.text = ""; - filter = ""; - }); - }, - ), - ], + suffixIcon: + _searchController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _searchController.text = ""; + filter = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), @@ -312,116 +301,110 @@ class _CurrencyViewState extends ConsumerState { ), ), SliverList( - delegate: SliverChildBuilderDelegate( - (context, index) { - return Container( - decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .popupBG, - borderRadius: _borderRadius(index), + delegate: SliverChildBuilderDelegate((context, index) { + return Container( + decoration: BoxDecoration( + color: + Theme.of( + context, + ).extension()!.popupBG, + borderRadius: _borderRadius(index), + ), + child: Padding( + padding: const EdgeInsets.all(4), + key: Key( + "currencySelect_${currenciesWithoutSelected[index]}", ), - child: Padding( - padding: const EdgeInsets.all(4), - key: Key( - "currencySelect_${currenciesWithoutSelected[index]}", - ), - child: RoundedContainer( - padding: const EdgeInsets.all(0), - color: currenciesWithoutSelected[index] == current - ? Theme.of(context) - .extension()! - .currencyListItemBG - : Theme.of(context) - .extension()! - .popupBG, - child: RawMaterialButton( - onPressed: () async { - onTap(index); - }, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), + child: RoundedContainer( + padding: const EdgeInsets.all(0), + color: + currenciesWithoutSelected[index] == current + ? Theme.of(context) + .extension()! + .currencyListItemBG + : Theme.of( + context, + ).extension()!.popupBG, + child: RawMaterialButton( + onPressed: () async { + onTap(index); + }, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - child: Padding( - padding: const EdgeInsets.all(12.0), - child: Row( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - SizedBox( - width: 20, - height: 20, - child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, - materialTapTargetSize: - MaterialTapTargetSize.shrinkWrap, - value: true, - groupValue: currenciesWithoutSelected[ - index] == - current, - onChanged: (_) { - onTap(index); - }, - ), - ), - const SizedBox( - width: 12, + ), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: 20, + height: 20, + child: Radio( + activeColor: + Theme.of(context) + .extension()! + .radioButtonIconEnabled, + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + value: true, + groupValue: + currenciesWithoutSelected[index] == + current, + onChanged: (_) { + onTap(index); + }, ), - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - currenciesWithoutSelected[index], - key: (currenciesWithoutSelected[ - index] == - current) - ? const Key( + ), + const SizedBox(width: 12), + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + currenciesWithoutSelected[index], + key: + (currenciesWithoutSelected[index] == + current) + ? const Key( "selectedCurrencySettingsCurrencyText", ) - : null, - style: STextStyles.largeMedium14( - context, - ), - ), - const SizedBox( - height: 2, + : null, + style: STextStyles.largeMedium14( + context, ), - Text( - ref.watch( - baseCurrenciesProvider.select( - (value) => value.map, - ), - )[currenciesWithoutSelected[ - index]] ?? - "", - key: (currenciesWithoutSelected[ - index] == - current) - ? const Key( + ), + const SizedBox(height: 2), + Text( + ref.watch( + baseCurrenciesProvider.select( + (value) => value.map, + ), + )[currenciesWithoutSelected[index]] ?? + "", + key: + (currenciesWithoutSelected[index] == + current) + ? const Key( "selectedCurrencySettingsCurrencyTextDescription", ) - : null, - style: STextStyles.itemSubtitle( - context, - ), + : null, + style: STextStyles.itemSubtitle( + context, ), - ], - ), - ], - ), + ), + ], + ), + ], ), ), ), ), - ); - }, - childCount: currenciesWithoutSelected.length, - ), + ), + ); + }, childCount: currenciesWithoutSelected.length), ), ], ); diff --git a/lib/pages/settings_views/global_settings_view/global_settings_view.dart b/lib/pages/settings_views/global_settings_view/global_settings_view.dart index 082d03429..5dc6d4101 100644 --- a/lib/pages/settings_views/global_settings_view/global_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/global_settings_view.dart @@ -38,9 +38,7 @@ import 'syncing_preferences_views/syncing_preferences_view.dart'; import 'tor_settings/tor_settings_view.dart'; class GlobalSettingsView extends StatelessWidget { - const GlobalSettingsView({ - super.key, - }); + const GlobalSettingsView({super.key}); static const String routeName = "/globalSettings"; @@ -56,271 +54,248 @@ class GlobalSettingsView extends StatelessWidget { Navigator.of(context).pop(); }, ), - title: Text( - "Settings", - style: STextStyles.navBarTitle(context), - ), + title: Text("Settings", style: STextStyles.navBarTitle(context)), ), - body: LayoutBuilder( - builder: (builderContext, constraints) { - return Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, - ), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( - padding: const EdgeInsets.all(4), - child: Column( - children: [ - SettingsListButton( - iconAssetName: Assets.svg.addressBook, - iconSize: 16, - title: "Address book", - onPressed: () { - Navigator.of(context) - .pushNamed(AddressBookView.routeName); - }, - ), - const SizedBox( - height: 8, - ), - SettingsListButton( - iconAssetName: Assets.svg.downloadFolder, - iconSize: 14, - title: "${AppConfig.prefix} backup & restore", - onPressed: () { - Navigator.push( - context, - RouteGenerator.getRoute( - shouldUseMaterialRoute: - RouteGenerator.useMaterialPageRoute, - builder: (_) => const LockscreenView( - showBackButton: true, - routeOnSuccess: - StackBackupView.routeName, - biometricsCancelButtonString: - "CANCEL", - biometricsLocalizedReason: - "Authenticate to access ${AppConfig.prefix} backup & restore settings", - biometricsAuthenticationTitle: - "${AppConfig.prefix} backup", - ), - settings: const RouteSettings( - name: "/swblockscreen", + body: SafeArea( + child: LayoutBuilder( + builder: (builderContext, constraints) { + return Padding( + padding: const EdgeInsets.only(left: 12, top: 12, right: 12), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedWhiteContainer( + padding: const EdgeInsets.all(4), + child: Column( + children: [ + SettingsListButton( + iconAssetName: Assets.svg.addressBook, + iconSize: 16, + title: "Address book", + onPressed: () { + Navigator.of( + context, + ).pushNamed(AddressBookView.routeName); + }, + ), + const SizedBox(height: 8), + SettingsListButton( + iconAssetName: Assets.svg.downloadFolder, + iconSize: 14, + title: + "${AppConfig.prefix} backup & restore", + onPressed: () { + Navigator.push( + context, + RouteGenerator.getRoute( + shouldUseMaterialRoute: + RouteGenerator + .useMaterialPageRoute, + builder: + (_) => const LockscreenView( + showBackButton: true, + routeOnSuccess: + StackBackupView.routeName, + biometricsCancelButtonString: + "CANCEL", + biometricsLocalizedReason: + "Authenticate to access ${AppConfig.prefix} backup & restore settings", + biometricsAuthenticationTitle: + "${AppConfig.prefix} backup", + ), + settings: const RouteSettings( + name: "/swblockscreen", + ), ), - ), - ); - }, - ), - const SizedBox( - height: 8, - ), - SettingsListButton( - iconAssetName: Assets.svg.lock, - iconSize: 16, - title: "Security", - onPressed: () { - Navigator.of(context) - .pushNamed(SecurityView.routeName); - }, - ), - const SizedBox( - height: 8, - ), - SettingsListButton( - iconAssetName: Assets.svg.dollarSign, - iconSize: 18, - title: "Currency", - onPressed: () { - Navigator.of(context).pushNamed( - BaseCurrencySettingsView.routeName, - ); - }, - ), - const SizedBox( - height: 8, - ), - SettingsListButton( - iconAssetName: Assets.svg.language, - iconSize: 18, - title: "Language", - onPressed: () { - Navigator.of(context).pushNamed( - LanguageSettingsView.routeName, - ); - }, - ), - const SizedBox( - height: 8, - ), - SettingsListButton( - iconAssetName: Assets.svg.tor, - iconSize: 18, - title: "Tor Settings", - onPressed: () { - Navigator.of(context) - .pushNamed(TorSettingsView.routeName); - }, - ), - const SizedBox( - height: 8, - ), - SettingsListButton( - iconAssetName: Assets.svg.node, - iconSize: 16, - title: "Manage nodes", - onPressed: () { - Navigator.of(context) - .pushNamed(ManageNodesView.routeName); - }, - ), - const SizedBox( - height: 8, - ), - SettingsListButton( - iconAssetName: Assets.svg.arrowRotate, - iconSize: 18, - title: "Syncing preferences", - onPressed: () { - Navigator.of(context).pushNamed( - SyncingPreferencesView.routeName, - ); - }, - ), - const SizedBox( - height: 8, - ), - SettingsListButton( - iconAssetName: Assets.svg.arrowUpRight, - iconSize: 16, - title: "Startup", - onPressed: () { - Navigator.of(context).pushNamed( - StartupPreferencesView.routeName, - ); - }, - ), - if (AppConfig.hasFeature( - AppFeature.themeSelection)) - const SizedBox( - height: 8, + ); + }, + ), + const SizedBox(height: 8), + SettingsListButton( + iconAssetName: Assets.svg.lock, + iconSize: 16, + title: "Security", + onPressed: () { + Navigator.of( + context, + ).pushNamed(SecurityView.routeName); + }, + ), + const SizedBox(height: 8), + SettingsListButton( + iconAssetName: Assets.svg.dollarSign, + iconSize: 18, + title: "Currency", + onPressed: () { + Navigator.of(context).pushNamed( + BaseCurrencySettingsView.routeName, + ); + }, + ), + const SizedBox(height: 8), + SettingsListButton( + iconAssetName: Assets.svg.language, + iconSize: 18, + title: "Language", + onPressed: () { + Navigator.of(context).pushNamed( + LanguageSettingsView.routeName, + ); + }, + ), + const SizedBox(height: 8), + SettingsListButton( + iconAssetName: Assets.svg.tor, + iconSize: 18, + title: "Tor Settings", + onPressed: () { + Navigator.of( + context, + ).pushNamed(TorSettingsView.routeName); + }, + ), + const SizedBox(height: 8), + SettingsListButton( + iconAssetName: Assets.svg.node, + iconSize: 16, + title: "Manage nodes", + onPressed: () { + Navigator.of( + context, + ).pushNamed(ManageNodesView.routeName); + }, ), - if (AppConfig.hasFeature( - AppFeature.themeSelection)) + const SizedBox(height: 8), SettingsListButton( - iconAssetName: Assets.svg.sun, + iconAssetName: Assets.svg.arrowRotate, iconSize: 18, - title: "Appearance", + title: "Syncing preferences", onPressed: () { Navigator.of(context).pushNamed( - AppearanceSettingsView.routeName, + SyncingPreferencesView.routeName, ); }, ), - if (Platform.isIOS) - const SizedBox( - height: 8, + const SizedBox(height: 8), + SettingsListButton( + iconAssetName: Assets.svg.arrowUpRight, + iconSize: 16, + title: "Startup", + onPressed: () { + Navigator.of(context).pushNamed( + StartupPreferencesView.routeName, + ); + }, + ), + if (AppConfig.hasFeature( + AppFeature.themeSelection, + )) + const SizedBox(height: 8), + if (AppConfig.hasFeature( + AppFeature.themeSelection, + )) + SettingsListButton( + iconAssetName: Assets.svg.sun, + iconSize: 18, + title: "Appearance", + onPressed: () { + Navigator.of(context).pushNamed( + AppearanceSettingsView.routeName, + ); + }, + ), + if (Platform.isIOS) const SizedBox(height: 8), + if (Platform.isIOS) + SettingsListButton( + iconAssetName: Assets.svg.circleAlert, + iconSize: 16, + title: "Delete account", + onPressed: () async { + await Navigator.of(context).pushNamed( + DeleteAccountView.routeName, + ); + }, + ), + const SizedBox(height: 8), + SettingsListButton( + iconAssetName: Assets.svg.ellipsis, + iconSize: 18, + title: "About", + onPressed: () { + Navigator.of( + context, + ).pushNamed(AboutView.routeName); + }, ), - if (Platform.isIOS) + const SizedBox(height: 8), SettingsListButton( - iconAssetName: Assets.svg.circleAlert, + iconAssetName: Assets.svg.solidSliders, iconSize: 16, - title: "Delete account", - onPressed: () async { - await Navigator.of(context).pushNamed( - DeleteAccountView.routeName, + title: "Advanced", + onPressed: () { + Navigator.of(context).pushNamed( + AdvancedSettingsView.routeName, ); }, ), - const SizedBox( - height: 8, - ), - SettingsListButton( - iconAssetName: Assets.svg.ellipsis, - iconSize: 18, - title: "About", - onPressed: () { - Navigator.of(context) - .pushNamed(AboutView.routeName); - }, - ), - const SizedBox( - height: 8, - ), - SettingsListButton( - iconAssetName: Assets.svg.solidSliders, - iconSize: 16, - title: "Advanced", - onPressed: () { - Navigator.of(context).pushNamed( - AdvancedSettingsView.routeName, - ); - }, - ), - const SizedBox( - height: 8, - ), - SettingsListButton( - iconAssetName: Assets.svg.questionMessage, - iconSize: 16, - title: "Support", - onPressed: () { - Navigator.of(context) - .pushNamed(SupportView.routeName); - }, - ), - // TextButton( - // style: Theme.of(context) - // .textButtonTheme - // .style - // ?.copyWith( - // backgroundColor: - // MaterialStateProperty.all( - // Theme.of(context).extension()!.accentColorDark - // ), - // ), - // child: Text( - // "fire test notification", - // style: STextStyles.button(context), - // ), - // onPressed: () async { - // NotificationApi.showNotification2( - // title: "Test notification", - // body: "My doggy wallet", - // walletId: - // "3c5e2d70-fcc3-11ec-86a3-31a106a81c3b", - // iconAssetName: - // Assets.svg.iconFor(coin: Coin.dogecoin), - // date: DateTime.now(), - // ); - // }, - // ), - ], + const SizedBox(height: 8), + SettingsListButton( + iconAssetName: Assets.svg.questionMessage, + iconSize: 16, + title: "Support", + onPressed: () { + Navigator.of( + context, + ).pushNamed(SupportView.routeName); + }, + ), + // TextButton( + // style: Theme.of(context) + // .textButtonTheme + // .style + // ?.copyWith( + // backgroundColor: + // MaterialStateProperty.all( + // Theme.of(context).extension()!.accentColorDark + // ), + // ), + // child: Text( + // "fire test notification", + // style: STextStyles.button(context), + // ), + // onPressed: () async { + // NotificationApi.showNotification2( + // title: "Test notification", + // body: "My doggy wallet", + // walletId: + // "3c5e2d70-fcc3-11ec-86a3-31a106a81c3b", + // iconAssetName: + // Assets.svg.iconFor(coin: Coin.dogecoin), + // date: DateTime.now(), + // ); + // }, + // ), + ], + ), ), - ), - const SizedBox( - height: 12, - ), - ], + const SizedBox(height: 12), + ], + ), ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ); diff --git a/lib/pages/settings_views/global_settings_view/hidden_settings.dart b/lib/pages/settings_views/global_settings_view/hidden_settings.dart index 99fb927cb..52b78cbcf 100644 --- a/lib/pages/settings_views/global_settings_view/hidden_settings.dart +++ b/lib/pages/settings_views/global_settings_view/hidden_settings.dart @@ -41,338 +41,344 @@ class HiddenSettings extends StatelessWidget { padding: const EdgeInsets.all(8.0), child: AppBarIconButton( size: 32, - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, shadows: const [], icon: SvgPicture.asset( Assets.svg.arrowLeft, width: 18, height: 18, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, ), onPressed: Navigator.of(context).pop, ), ), - title: Text( - "Dev options", - style: STextStyles.navBarTitle(context), - ), + title: Text("Dev options", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Consumer( - builder: (_, ref, __) { - return GestureDetector( - onTap: () async { - ref - .read(prefsChangeNotifierProvider) - .advancedFiroFeatures = - !ref - .read(prefsChangeNotifierProvider) - .advancedFiroFeatures; - }, - child: RoundedWhiteContainer( - child: Text( - ref.watch( - prefsChangeNotifierProvider.select( - (s) => s.advancedFiroFeatures, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Consumer( + builder: (_, ref, __) { + return GestureDetector( + onTap: () async { + ref + .read(prefsChangeNotifierProvider) + .advancedFiroFeatures = !ref + .read(prefsChangeNotifierProvider) + .advancedFiroFeatures; + }, + child: RoundedWhiteContainer( + child: Text( + ref.watch( + prefsChangeNotifierProvider.select( + (s) => s.advancedFiroFeatures, + ), + ) + ? "Hide advanced Firo features" + : "Show advanced Firo features", + style: STextStyles.button(context).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorDark, ), - ) - ? "Hide advanced Firo features" - : "Show advanced Firo features", - style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, ), ), - ), - ); - }, - ), - const SizedBox( - height: 12, - ), - Consumer( - builder: (_, ref, __) { - return GestureDetector( - onTap: () async { - final notifs = ref - .read(notificationsProvider) - .notifications; + ); + }, + ), + const SizedBox(height: 12), + Consumer( + builder: (_, ref, __) { + return GestureDetector( + onTap: () async { + final notifs = + ref + .read(notificationsProvider) + .notifications; - for (final n in notifs) { + for (final n in notifs) { + await ref + .read(notificationsProvider) + .delete(n, false); + } await ref .read(notificationsProvider) - .delete(n, false); - } - await ref - .read(notificationsProvider) - .delete(notifs[0], true); + .delete(notifs[0], true); - if (context.mounted) { - unawaited( - showFloatingFlushBar( - type: FlushBarType.success, - message: "Notification history deleted", - context: context, + if (context.mounted) { + unawaited( + showFloatingFlushBar( + type: FlushBarType.success, + message: "Notification history deleted", + context: context, + ), + ); + } + }, + child: RoundedWhiteContainer( + child: Text( + "Delete notifications", + style: STextStyles.button(context).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorDark, ), - ); - } - }, - child: RoundedWhiteContainer( - child: Text( - "Delete notifications", - style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, - ), - ), - ), - ); - }, - ), - const SizedBox( - height: 12, - ), - Consumer( - builder: (_, ref, __) { - return GestureDetector( - onTap: () async { - ref.read(prefsChangeNotifierProvider).logsPath = - null; - }, - child: RoundedWhiteContainer( - child: Text( - "Reset log location", - style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, ), ), - ), - ); - }, - ), - // const SizedBox( - // height: 12, - // ), - // Consumer(builder: (_, ref, __) { - // return GestureDetector( - // onTap: () async { - // final trades = - // ref.read(tradesServiceProvider).trades; - // - // for (final trade in trades) { - // ref.read(tradesServiceProvider).delete( - // trade: trade, shouldNotifyListeners: false); - // } - // ref.read(tradesServiceProvider).delete( - // trade: trades[0], shouldNotifyListeners: true); - // - // // ref.read(notificationsProvider).DELETE_EVERYTHING(); - // }, - // child: RoundedWhiteContainer( - // child: Text( - // "Delete trade history", - // style: STextStyles.button(context).copyWith( - // color: Theme.of(context).extension()!.accentColorDark - // ), - // ), - // ), - // ); - // }), - // const SizedBox( - // height: 12, - // ), - // Consumer( - // builder: (_, ref, __) { - // return GestureDetector( - // onTap: () async { - // await ref - // .read(debugServiceProvider) - // .deleteAllLogs(); - // - // if (context.mounted) { - // unawaited( - // showFloatingFlushBar( - // type: FlushBarType.success, - // message: "Debug Logs deleted", - // context: context, - // ), - // ); - // } - // }, - // child: RoundedWhiteContainer( - // child: Text( - // "Delete Debug Logs", - // style: STextStyles.button(context).copyWith( - // color: Theme.of(context) - // .extension()! - // .accentColorDark, - // ), - // ), - // ), - // ); - // }, - // ), - const SizedBox( - height: 12, - ), - // Consumer(builder: (_, ref, __) { - // return GestureDetector( - // onTap: () async { - // await showOneTimeTorHasBeenAddedDialogIfRequired( - // context, - // ); - // }, - // child: RoundedWhiteContainer( - // child: Text( - // "Test tor stacy popup", - // style: STextStyles.button(context).copyWith( - // color: Theme.of(context) - // .extension()! - // .accentColorDark), - // ), - // ), - // ); - // }), - // const SizedBox( - // height: 12, - // ), - // Consumer(builder: (_, ref, __) { - // return GestureDetector( - // onTap: () async { - // final box = await Hive.openBox( - // DB.boxNameOneTimeDialogsShown); - // await box.clear(); - // }, - // child: RoundedWhiteContainer( - // child: Text( - // "Reset tor stacy popup", - // style: STextStyles.button(context).copyWith( - // color: Theme.of(context) - // .extension()! - // .accentColorDark), - // ), - // ), - // ); - // }), - // const SizedBox( - // height: 12, - // ), - Consumer( - builder: (_, ref, __) { - if (ref.watch( - prefsChangeNotifierProvider - .select((value) => value.familiarity), - ) < - 6) { + ); + }, + ), + const SizedBox(height: 12), + Consumer( + builder: (_, ref, __) { return GestureDetector( onTap: () async { - final familiarity = ref + ref .read(prefsChangeNotifierProvider) - .familiarity; - if (familiarity < 6) { - ref - .read(prefsChangeNotifierProvider) - .familiarity = 6; - - Constants.exchangeForExperiencedUsers(6); - } + .logsPath = null; }, child: RoundedWhiteContainer( child: Text( - "Enable exchange", + "Reset log location", style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of(context) + .extension()! + .accentColorDark, ), ), ), ); - } else { - return Container(); - } - }, - ), - const SizedBox( - height: 12, - ), - Consumer( - builder: (_, ref, __) { - return GestureDetector( - onTap: () async { - await showDialog( - context: context, - builder: (_) => TorWarningDialog( - coin: Stellar(CryptoCurrencyNetwork.main), + }, + ), + // const SizedBox( + // height: 12, + // ), + // Consumer(builder: (_, ref, __) { + // return GestureDetector( + // onTap: () async { + // final trades = + // ref.read(tradesServiceProvider).trades; + // + // for (final trade in trades) { + // ref.read(tradesServiceProvider).delete( + // trade: trade, shouldNotifyListeners: false); + // } + // ref.read(tradesServiceProvider).delete( + // trade: trades[0], shouldNotifyListeners: true); + // + // // ref.read(notificationsProvider).DELETE_EVERYTHING(); + // }, + // child: RoundedWhiteContainer( + // child: Text( + // "Delete trade history", + // style: STextStyles.button(context).copyWith( + // color: Theme.of(context).extension()!.accentColorDark + // ), + // ), + // ), + // ); + // }), + // const SizedBox( + // height: 12, + // ), + // Consumer( + // builder: (_, ref, __) { + // return GestureDetector( + // onTap: () async { + // await ref + // .read(debugServiceProvider) + // .deleteAllLogs(); + // + // if (context.mounted) { + // unawaited( + // showFloatingFlushBar( + // type: FlushBarType.success, + // message: "Debug Logs deleted", + // context: context, + // ), + // ); + // } + // }, + // child: RoundedWhiteContainer( + // child: Text( + // "Delete Debug Logs", + // style: STextStyles.button(context).copyWith( + // color: Theme.of(context) + // .extension()! + // .accentColorDark, + // ), + // ), + // ), + // ); + // }, + // ), + const SizedBox(height: 12), + // Consumer(builder: (_, ref, __) { + // return GestureDetector( + // onTap: () async { + // await showOneTimeTorHasBeenAddedDialogIfRequired( + // context, + // ); + // }, + // child: RoundedWhiteContainer( + // child: Text( + // "Test tor stacy popup", + // style: STextStyles.button(context).copyWith( + // color: Theme.of(context) + // .extension()! + // .accentColorDark), + // ), + // ), + // ); + // }), + // const SizedBox( + // height: 12, + // ), + // Consumer(builder: (_, ref, __) { + // return GestureDetector( + // onTap: () async { + // final box = await Hive.openBox( + // DB.boxNameOneTimeDialogsShown); + // await box.clear(); + // }, + // child: RoundedWhiteContainer( + // child: Text( + // "Reset tor stacy popup", + // style: STextStyles.button(context).copyWith( + // color: Theme.of(context) + // .extension()! + // .accentColorDark), + // ), + // ), + // ); + // }), + // const SizedBox( + // height: 12, + // ), + Consumer( + builder: (_, ref, __) { + if (ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.familiarity, + ), + ) < + 6) { + return GestureDetector( + onTap: () async { + final familiarity = + ref + .read(prefsChangeNotifierProvider) + .familiarity; + if (familiarity < 6) { + ref + .read(prefsChangeNotifierProvider) + .familiarity = 6; + + Constants.exchangeForExperiencedUsers(6); + } + }, + child: RoundedWhiteContainer( + child: Text( + "Enable exchange", + style: STextStyles.button( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorDark, + ), + ), ), ); - }, - child: RoundedWhiteContainer( - child: Text( - "Show Tor warning popup", - style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + } else { + return Container(); + } + }, + ), + const SizedBox(height: 12), + Consumer( + builder: (_, ref, __) { + return GestureDetector( + onTap: () async { + await showDialog( + context: context, + builder: + (_) => TorWarningDialog( + coin: Stellar( + CryptoCurrencyNetwork.main, + ), + ), + ); + }, + child: RoundedWhiteContainer( + child: Text( + "Show Tor warning popup", + style: STextStyles.button(context).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorDark, + ), ), ), - ), - ); - }, - ), - // const SizedBox( - // height: 12, - // ), - // Consumer( - // builder: (_, ref, __) { - // return GestureDetector( - // onTap: () async { - // await showLoading( - // whileFuture: FiroCache.init(), - // context: context, - // rootNavigator: true, - // message: "initializing firo cache", - // ); - // }, - // child: RoundedWhiteContainer( - // child: Text( - // "init firo_cache", - // style: STextStyles.button(context).copyWith( - // color: Theme.of(context) - // .extension()! - // .accentColorDark, - // ), - // ), - // ), - // ); - // }, - // ), - ], + ); + }, + ), + // const SizedBox( + // height: 12, + // ), + // Consumer( + // builder: (_, ref, __) { + // return GestureDetector( + // onTap: () async { + // await showLoading( + // whileFuture: FiroCache.init(), + // context: context, + // rootNavigator: true, + // message: "initializing firo cache", + // ); + // }, + // child: RoundedWhiteContainer( + // child: Text( + // "init firo_cache", + // style: STextStyles.button(context).copyWith( + // color: Theme.of(context) + // .extension()! + // .accentColorDark, + // ), + // ), + // ), + // ); + // }, + // ), + ], + ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/language_view.dart b/lib/pages/settings_views/global_settings_view/language_view.dart index 8f1ca3012..9490530d5 100644 --- a/lib/pages/settings_views/global_settings_view/language_view.dart +++ b/lib/pages/settings_views/global_settings_view/language_view.dart @@ -59,20 +59,14 @@ class _LanguageViewState extends ConsumerState { BorderRadius? _borderRadius(int index) { if (index == 0 && listWithoutSelected.length == 1) { - return BorderRadius.circular( - Constants.size.circularBorderRadius, - ); + return BorderRadius.circular(Constants.size.circularBorderRadius); } else if (index == 0) { return BorderRadius.vertical( - top: Radius.circular( - Constants.size.circularBorderRadius, - ), + top: Radius.circular(Constants.size.circularBorderRadius), ); } else if (index == listWithoutSelected.length - 1) { return BorderRadius.vertical( - bottom: Radius.circular( - Constants.size.circularBorderRadius, - ), + bottom: Radius.circular(Constants.size.circularBorderRadius), ); } return null; @@ -103,8 +97,9 @@ class _LanguageViewState extends ConsumerState { @override Widget build(BuildContext context) { - current = ref - .watch(prefsChangeNotifierProvider.select((value) => value.language)); + current = ref.watch( + prefsChangeNotifierProvider.select((value) => value.language), + ); listWithoutSelected = languages; if (current.isNotEmpty) { @@ -127,101 +122,99 @@ class _LanguageViewState extends ConsumerState { } }, ), - title: Text( - "Language", - style: STextStyles.navBarTitle(context), - ), + title: Text("Language", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.only( - top: 12, - left: 16, - right: 16, - ), - child: NestedScrollView( - floatHeaderSlivers: true, - headerSliverBuilder: (context, innerBoxIsScrolled) { - return [ - SliverOverlapAbsorber( - handle: - NestedScrollView.sliverOverlapAbsorberHandleFor(context), - sliver: SliverToBoxAdapter( - child: Padding( - padding: const EdgeInsets.only(bottom: 16), - child: ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - controller: _searchController, - focusNode: _searchFocusNode, - onChanged: (newString) { - setState(() => filter = newString); - }, - style: STextStyles.field(context), - decoration: standardInputDecoration( - "Search", - _searchFocusNode, - context, - ).copyWith( - prefixIcon: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 10, - vertical: 16, - ), - child: SvgPicture.asset( - Assets.svg.search, - width: 16, - height: 16, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only(top: 12, left: 16, right: 16), + child: NestedScrollView( + floatHeaderSlivers: true, + headerSliverBuilder: (context, innerBoxIsScrolled) { + return [ + SliverOverlapAbsorber( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor( + context, + ), + sliver: SliverToBoxAdapter( + child: Padding( + padding: const EdgeInsets.only(bottom: 16), + child: ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, + controller: _searchController, + focusNode: _searchFocusNode, + onChanged: (newString) { + setState(() => filter = newString); + }, + style: STextStyles.field(context), + decoration: standardInputDecoration( + "Search", + _searchFocusNode, + context, + ).copyWith( + prefixIcon: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10, + vertical: 16, + ), + child: SvgPicture.asset( + Assets.svg.search, + width: 16, + height: 16, + ), ), - ), - suffixIcon: _searchController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _searchController.text = ""; - filter = ""; - }); - }, + suffixIcon: + _searchController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only( + right: 0, + ), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _searchController.text = ""; + filter = ""; + }); + }, + ), + ], ), - ], - ), - ), - ) - : null, + ), + ) + : null, + ), ), ), ), ), ), - ), - ]; - }, - body: Builder( - builder: (context) { - return CustomScrollView( - slivers: [ - SliverOverlapInjector( - handle: NestedScrollView.sliverOverlapAbsorberHandleFor( - context, + ]; + }, + body: Builder( + builder: (context) { + return CustomScrollView( + slivers: [ + SliverOverlapInjector( + handle: NestedScrollView.sliverOverlapAbsorberHandleFor( + context, + ), ), - ), - SliverList( - delegate: SliverChildBuilderDelegate( - (context, index) { + SliverList( + delegate: SliverChildBuilderDelegate((context, index) { return Container( decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .popupBG, + color: + Theme.of( + context, + ).extension()!.popupBG, borderRadius: _borderRadius(index), ), child: Padding( @@ -231,13 +224,14 @@ class _LanguageViewState extends ConsumerState { ), child: RoundedContainer( padding: const EdgeInsets.all(0), - color: index == 0 - ? Theme.of(context) - .extension()! - .currencyListItemBG - : Theme.of(context) - .extension()! - .popupBG, + color: + index == 0 + ? Theme.of(context) + .extension()! + .currencyListItemBG + : Theme.of( + context, + ).extension()!.popupBG, child: RawMaterialButton( onPressed: () async { onTap(index); @@ -257,9 +251,10 @@ class _LanguageViewState extends ConsumerState { width: 20, height: 20, child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, + activeColor: + Theme.of(context) + .extension()! + .radioButtonIconEnabled, value: true, groupValue: index == 0, onChanged: (_) { @@ -267,34 +262,32 @@ class _LanguageViewState extends ConsumerState { }, ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( listWithoutSelected[index], - key: (index == 0) - ? const Key( - "selectedLanguageSettingsLanguageText", - ) - : null, + key: + (index == 0) + ? const Key( + "selectedLanguageSettingsLanguageText", + ) + : null, style: STextStyles.largeMedium14( context, ), ), - const SizedBox( - height: 2, - ), + const SizedBox(height: 2), Text( listWithoutSelected[index], - key: (index == 0) - ? const Key( - "selectedLanguageSettingsLanguageTextDescription", - ) - : null, + key: + (index == 0) + ? const Key( + "selectedLanguageSettingsLanguageTextDescription", + ) + : null, style: STextStyles.itemSubtitle( context, ), @@ -308,13 +301,12 @@ class _LanguageViewState extends ConsumerState { ), ), ); - }, - childCount: listWithoutSelected.length, + }, childCount: listWithoutSelected.length), ), - ), - ], - ); - }, + ], + ); + }, + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart index 5703db754..61450faad 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart @@ -241,7 +241,7 @@ class _AddEditNodeViewState extends ConsumerState { final plainEnabled = formData.netOption == TorPlainNetworkOption.clear || formData.netOption == TorPlainNetworkOption.both; - + final forceNoTor = formData.forceNoTor ?? false; switch (viewType) { @@ -562,27 +562,29 @@ class _AddEditNodeViewState extends ConsumerState { ), ], ), - body: Padding( - padding: const EdgeInsets.only( - top: 12, - left: 12, - right: 12, - bottom: 12, - ), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(4), - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 8, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only( + top: 12, + left: 12, + right: 12, + bottom: 12, + ), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(4), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 8, + ), + child: IntrinsicHeight(child: child), ), - child: IntrinsicHeight(child: child), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/manage_nodes_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/manage_nodes_view.dart index a7756f662..8d8c1bc7b 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/manage_nodes_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/manage_nodes_view.dart @@ -27,9 +27,7 @@ import '../../../../widgets/rounded_white_container.dart'; import 'coin_nodes_view.dart'; class ManageNodesView extends ConsumerStatefulWidget { - const ManageNodesView({ - super.key, - }); + const ManageNodesView({super.key}); static const String routeName = "/manageNodes"; @@ -43,9 +41,7 @@ class _ManageNodesViewState extends ConsumerState { @override void initState() { _coins = _coins.toList(); - _coins.removeWhere( - (e) => e is Firo && e.network.isTestNet, - ); + _coins.removeWhere((e) => e is Firo && e.network.isTestNet); super.initState(); } @@ -60,9 +56,10 @@ class _ManageNodesViewState extends ConsumerState { prefsChangeNotifierProvider.select((value) => value.showTestNetCoins), ); - final coins = showTestNet - ? _coins - : _coins.where((e) => !e.network.isTestNet).toList(); + final coins = + showTestNet + ? _coins + : _coins.where((e) => !e.network.isTestNet).toList(); return Background( child: Scaffold( @@ -73,29 +70,24 @@ class _ManageNodesViewState extends ConsumerState { Navigator.of(context).pop(); }, ), - title: Text( - "Manage nodes", - style: STextStyles.navBarTitle(context), - ), + title: Text("Manage nodes", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.only( - top: 12, - left: 12, - right: 12, - ), - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - ...coins.map( - (coin) { - final count = ref - .watch( - nodeServiceChangeNotifierProvider - .select((value) => value.getNodesFor(coin)), - ) - .length; + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only(top: 12, left: 12, right: 12), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + ...coins.map((coin) { + final count = + ref + .watch( + nodeServiceChangeNotifierProvider.select( + (value) => value.getNodesFor(coin), + ), + ) + .length; return Padding( padding: const EdgeInsets.all(4), @@ -121,17 +113,11 @@ class _ManageNodesViewState extends ConsumerState { child: Row( children: [ SvgPicture.file( - File( - ref.watch( - coinIconProvider(coin), - ), - ), + File(ref.watch(coinIconProvider(coin))), width: 24, height: 24, ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -151,9 +137,9 @@ class _ManageNodesViewState extends ConsumerState { ), ), ); - }, - ), - ], + }), + ], + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart index 572c7d7a2..414ba8097 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart @@ -64,8 +64,10 @@ class _NodeDetailsViewState extends ConsumerState { bool _desktopReadOnly = true; Future _notifyWalletsOfUpdatedNode() async { - final wallets = - ref.read(pWallets).wallets.where((e) => e.info.coin == widget.coin); + final wallets = ref + .read(pWallets) + .wallets + .where((e) => e.info.coin == widget.coin); final prefs = ref.read(prefsChangeNotifierProvider); switch (prefs.syncType) { @@ -110,139 +112,140 @@ class _NodeDetailsViewState extends ConsumerState { final isDesktop = Util.isDesktop; final node = ref.watch( - nodeServiceChangeNotifierProvider - .select((value) => value.getNodeById(id: nodeId)), + nodeServiceChangeNotifierProvider.select( + (value) => value.getNodeById(id: nodeId), + ), ); final nodesForCoin = ref.watch( - nodeServiceChangeNotifierProvider - .select((value) => value.getNodesFor(coin)), + nodeServiceChangeNotifierProvider.select( + (value) => value.getNodesFor(coin), + ), ); final canDelete = nodesForCoin.length > 1; return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed(const Duration(milliseconds: 75)); - } - if (context.mounted) { - Navigator.of(context).pop(); - } - }, - ), - title: Text( - "Node details", - style: STextStyles.navBarTitle(context), - ), - actions: [ - // if (!nodeId.startsWith(DefaultNodes.defaultNodeIdPrefix)) - Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 10, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 75), + ); + } + if (context.mounted) { + Navigator.of(context).pop(); + } + }, + ), + title: Text( + "Node details", + style: STextStyles.navBarTitle(context), ), - child: AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - key: const Key("nodeDetailsEditNodeAppBarButtonKey"), - size: 36, - shadows: const [], - color: - Theme.of(context).extension()!.background, - icon: SvgPicture.asset( - Assets.svg.pencil, - color: Theme.of(context) - .extension()! - .accentColorDark, - width: 20, - height: 20, + actions: [ + // if (!nodeId.startsWith(DefaultNodes.defaultNodeIdPrefix)) + Padding( + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + right: 10, ), - onPressed: () { - Navigator.of(context).pushNamed( - AddEditNodeView.routeName, - arguments: Tuple4( - AddEditNodeViewType.edit, - coin, - nodeId, - popRouteName, + child: AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + key: const Key("nodeDetailsEditNodeAppBarButtonKey"), + size: 36, + shadows: const [], + color: + Theme.of( + context, + ).extension()!.background, + icon: SvgPicture.asset( + Assets.svg.pencil, + color: + Theme.of( + context, + ).extension()!.accentColorDark, + width: 20, + height: 20, + ), + onPressed: () { + Navigator.of(context).pushNamed( + AddEditNodeView.routeName, + arguments: Tuple4( + AddEditNodeViewType.edit, + coin, + nodeId, + popRouteName, + ), + ); + }, + ), + ), + ), + ], + ), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only(top: 12, left: 12, right: 12), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(4), + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 8, + ), + child: IntrinsicHeight(child: child), + ), ), ); }, ), ), ), - ], - ), - body: Padding( - padding: const EdgeInsets.only( - top: 12, - left: 12, - right: 12, - ), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(4), - child: ConstrainedBox( - constraints: - BoxConstraints(minHeight: constraints.maxHeight - 8), - child: IntrinsicHeight( - child: child, - ), - ), - ), - ); - }, ), ), - ), - ), child: ConditionalParent( condition: isDesktop, - builder: (child) => DesktopDialog( - maxWidth: 580, - maxHeight: double.infinity, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( + builder: + (child) => DesktopDialog( + maxWidth: 580, + maxHeight: double.infinity, + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - const SizedBox( - width: 8, - ), - const AppBarBackButton( - iconSize: 24, - size: 40, + Row( + children: [ + const SizedBox(width: 8), + const AppBarBackButton(iconSize: 24, size: 40), + Text( + "Node details", + style: STextStyles.desktopH3(context), + ), + ], ), - Text( - "Node details", - style: STextStyles.desktopH3(context), + Padding( + padding: const EdgeInsets.only( + left: 32, + right: 32, + top: 16, + bottom: 32, + ), + child: child, ), ], ), - Padding( - padding: const EdgeInsets.only( - left: 32, - right: 32, - top: 16, - bottom: 32, - ), - child: child, - ), - ], - ), - ), + ), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ @@ -253,44 +256,35 @@ class _NodeDetailsViewState extends ConsumerState { coin: coin, ), if (!isDesktop) const Spacer(), - if (isDesktop) - const SizedBox( - height: 22, - ), + if (isDesktop) const SizedBox(height: 22), if (isDesktop && canDelete) SizedBox( height: 56, - child: _desktopReadOnly - ? null - : Row( - children: [ - Expanded( - child: DeleteButton( - label: "Delete node", - desktopMed: true, - onPressed: () async { - Navigator.of(context).pop(); + child: + _desktopReadOnly + ? null + : Row( + children: [ + Expanded( + child: DeleteButton( + label: "Delete node", + desktopMed: true, + onPressed: () async { + Navigator.of(context).pop(); - await ref - .read(nodeServiceChangeNotifierProvider) - .delete( - node!.id, - true, - ); - }, + await ref + .read(nodeServiceChangeNotifierProvider) + .delete(node!.id, true); + }, + ), ), - ), - const SizedBox( - width: 16, - ), - const Spacer(), - ], - ), + const SizedBox(width: 16), + const Spacer(), + ], + ), ), if (isDesktop && !_desktopReadOnly && canDelete) - const SizedBox( - height: 45, - ), + const SizedBox(height: 45), Row( children: [ Expanded( @@ -298,9 +292,10 @@ class _NodeDetailsViewState extends ConsumerState { label: "Test connection", buttonHeight: isDesktop ? ButtonHeight.l : null, onPressed: () async { - final node = ref - .read(nodeServiceChangeNotifierProvider) - .getNodeById(id: nodeId)!; + final node = + ref + .read(nodeServiceChangeNotifierProvider) + .getNodeById(id: nodeId)!; final TorPlainNetworkOption netOption; if (ref.read(nodeFormDataProvider).netOption != null) { @@ -312,16 +307,17 @@ class _NodeDetailsViewState extends ConsumerState { ); } - final nodeFormData = NodeFormData() - ..useSSL = node.useSSL - ..trusted = node.trusted - ..name = node.name - ..host = node.host - ..login = node.loginName - ..port = node.port - ..isFailover = node.isFailover - ..netOption = netOption - ..forceNoTor = node.forceNoTor; + final nodeFormData = + NodeFormData() + ..useSSL = node.useSSL + ..trusted = node.trusted + ..name = node.name + ..host = node.host + ..login = node.loginName + ..port = node.port + ..isFailover = node.isFailover + ..netOption = netOption + ..forceNoTor = node.forceNoTor; nodeFormData.password = await node.getPassword( ref.read(secureStoreProvider), ); @@ -359,16 +355,13 @@ class _NodeDetailsViewState extends ConsumerState { }, ), ), - if (isDesktop) - const SizedBox( - width: 16, - ), + if (isDesktop) const SizedBox(width: 16), if (isDesktop) Expanded( child: - // !nodeId.startsWith(DefaultNodes.defaultNodeIdPrefix) - // ? - PrimaryButton( + // !nodeId.startsWith(DefaultNodes.defaultNodeIdPrefix) + // ? + PrimaryButton( label: _desktopReadOnly ? "Edit" : "Save", buttonHeight: ButtonHeight.l, onPressed: () async { @@ -389,15 +382,16 @@ class _NodeDetailsViewState extends ConsumerState { ref.read(nodeFormDataProvider).isFailover, torEnabled: ref.read(nodeFormDataProvider).netOption == - TorPlainNetworkOption.tor || - ref.read(nodeFormDataProvider).netOption == - TorPlainNetworkOption.both, + TorPlainNetworkOption.tor || + ref.read(nodeFormDataProvider).netOption == + TorPlainNetworkOption.both, clearnetEnabled: ref.read(nodeFormDataProvider).netOption == - TorPlainNetworkOption.clear || - ref.read(nodeFormDataProvider).netOption == - TorPlainNetworkOption.both, - forceNoTor: ref.read(nodeFormDataProvider).forceNoTor, + TorPlainNetworkOption.clear || + ref.read(nodeFormDataProvider).netOption == + TorPlainNetworkOption.both, + forceNoTor: + ref.read(nodeFormDataProvider).forceNoTor, ); await ref @@ -410,16 +404,12 @@ class _NodeDetailsViewState extends ConsumerState { await _notifyWalletsOfUpdatedNode(); } }, - ) + ), // : Container() - , ), ], ), - if (!isDesktop) - const SizedBox( - height: 16, - ), + if (!isDesktop) const SizedBox(height: 16), ], ), ), diff --git a/lib/pages/settings_views/global_settings_view/security_views/security_view.dart b/lib/pages/settings_views/global_settings_view/security_views/security_view.dart index b5aac24a9..5412189ec 100644 --- a/lib/pages/settings_views/global_settings_view/security_views/security_view.dart +++ b/lib/pages/settings_views/global_settings_view/security_views/security_view.dart @@ -212,211 +212,118 @@ class _SecurityViewState extends ConsumerState { ), title: Text("Security", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: () { - Navigator.push( - context, - RouteGenerator.getRoute( - shouldUseMaterialRoute: - RouteGenerator.useMaterialPageRoute, - builder: - (_) => const LockscreenView( - showBackButton: true, - routeOnSuccess: ChangePinView.routeName, - biometricsCancelButtonString: "CANCEL", - biometricsLocalizedReason: - "Authenticate to change PIN", - biometricsAuthenticationTitle: "Change PIN", - ), - settings: const RouteSettings( - name: "/changepinlockscreen", - ), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 20, ), - child: Row( - children: [ - Text( - "Change PIN", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - ], - ), - ), - ), - ), - const SizedBox(height: 8), - RoundedWhiteContainer( - child: Consumer( - builder: (_, ref, __) { - return RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: null, - // () { - // final useBio = - // ref.read(prefsChangeNotifierProvider).useBiometrics; - // - // debugPrint("useBio: $useBio"); - // ref.read(prefsChangeNotifierProvider).useBiometrics = - // !useBio; - // - // debugPrint( - // "useBio set to: ${ref.read(prefsChangeNotifierProvider).useBiometrics}"); - // }, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Enable biometric authentication", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.useBiometrics, - ), - ), - onValueChanged: (newValue) { - ref - .read(prefsChangeNotifierProvider) - .useBiometrics = newValue; - }, + onPressed: () { + Navigator.push( + context, + RouteGenerator.getRoute( + shouldUseMaterialRoute: + RouteGenerator.useMaterialPageRoute, + builder: + (_) => const LockscreenView( + showBackButton: true, + routeOnSuccess: ChangePinView.routeName, + biometricsCancelButtonString: "CANCEL", + biometricsLocalizedReason: + "Authenticate to change PIN", + biometricsAuthenticationTitle: "Change PIN", ), - ), - ], - ), - ), - ); - }, - ), - ), - const SizedBox(height: 8), - RoundedWhiteContainer( - child: Consumer( - builder: (_, ref, __) { - return RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + settings: const RouteSettings( + name: "/changepinlockscreen", + ), ), + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 20, ), - onPressed: null, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Randomize PIN Pad", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.randomizePIN, - ), - ), - onValueChanged: (newValue) { - ref - .read(prefsChangeNotifierProvider) - .randomizePIN = newValue; - }, - ), - ), - ], - ), + child: Row( + children: [ + Text( + "Change PIN", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + ], ), - ); - }, + ), + ), ), - ), - // The "autoPin" preference (whether to automatically accept a correct PIN). - const SizedBox(height: 8), - RoundedWhiteContainer( - child: Consumer( - builder: (_, ref, __) { - return RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + const SizedBox(height: 8), + RoundedWhiteContainer( + child: Consumer( + builder: (_, ref, __) { + return RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - ), - onPressed: null, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Auto-accept correct PIN", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.autoPin, + onPressed: null, + // () { + // final useBio = + // ref.read(prefsChangeNotifierProvider).useBiometrics; + // + // debugPrint("useBio: $useBio"); + // ref.read(prefsChangeNotifierProvider).useBiometrics = + // !useBio; + // + // debugPrint( + // "useBio set to: ${ref.read(prefsChangeNotifierProvider).useBiometrics}"); + // }, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Enable biometric authentication", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + SizedBox( + height: 20, + width: 40, + child: DraggableSwitchButton( + isOn: ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.useBiometrics, + ), ), + onValueChanged: (newValue) { + ref + .read(prefsChangeNotifierProvider) + .useBiometrics = newValue; + }, ), - onValueChanged: (newValue) { - ref - .read(prefsChangeNotifierProvider) - .autoPin = newValue; - }, ), - ), - ], + ], + ), ), - ), - ); - }, + ); + }, + ), ), - ), - if (!ref.watch(pDuress)) const SizedBox(height: 8), - if (!ref.watch(pDuress)) + const SizedBox(height: 8), RoundedWhiteContainer( child: Consumer( builder: (_, ref, __) { @@ -435,20 +342,24 @@ class _SecurityViewState extends ConsumerState { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - "Duress PIN", + "Randomize PIN Pad", style: STextStyles.titleBold12(context), textAlign: TextAlign.left, ), SizedBox( height: 20, width: 40, - child: DraggableSwitch( - value: ref.watch( + child: DraggableSwitchButton( + isOn: ref.watch( prefsChangeNotifierProvider.select( - (value) => value.hasDuressPin, + (value) => value.randomizePIN, ), ), - onChanged: _duressToggled, + onValueChanged: (newValue) { + ref + .read(prefsChangeNotifierProvider) + .randomizePIN = newValue; + }, ), ), ], @@ -458,19 +369,8 @@ class _SecurityViewState extends ConsumerState { }, ), ), - if (!ref.watch(pDuress) && - ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.hasDuressPin, - ), - )) + // The "autoPin" preference (whether to automatically accept a correct PIN). const SizedBox(height: 8), - if (!ref.watch(pDuress) && - ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.hasDuressPin, - ), - )) RoundedWhiteContainer( child: Consumer( builder: (_, ref, __) { @@ -489,23 +389,23 @@ class _SecurityViewState extends ConsumerState { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - "Biometrics opens duress", + "Auto-accept correct PIN", style: STextStyles.titleBold12(context), textAlign: TextAlign.left, ), SizedBox( height: 20, width: 40, - child: DraggableSwitch( - value: ref.watch( + child: DraggableSwitchButton( + isOn: ref.watch( prefsChangeNotifierProvider.select( - (value) => value.biometricsDuress, + (value) => value.autoPin, ), ), - onChanged: (newValue) { + onValueChanged: (newValue) { ref .read(prefsChangeNotifierProvider) - .biometricsDuress = newValue; + .autoPin = newValue; }, ), ), @@ -516,7 +416,111 @@ class _SecurityViewState extends ConsumerState { }, ), ), - ], + if (!ref.watch(pDuress)) const SizedBox(height: 8), + if (!ref.watch(pDuress)) + RoundedWhiteContainer( + child: Consumer( + builder: (_, ref, __) { + return RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: null, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Duress PIN", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + SizedBox( + height: 20, + width: 40, + child: DraggableSwitch( + value: ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.hasDuressPin, + ), + ), + onChanged: _duressToggled, + ), + ), + ], + ), + ), + ); + }, + ), + ), + if (!ref.watch(pDuress) && + ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.hasDuressPin, + ), + )) + const SizedBox(height: 8), + if (!ref.watch(pDuress) && + ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.hasDuressPin, + ), + )) + RoundedWhiteContainer( + child: Consumer( + builder: (_, ref, __) { + return RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: null, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Biometrics opens duress", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + SizedBox( + height: 20, + width: 40, + child: DraggableSwitch( + value: ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.biometricsDuress, + ), + ), + onChanged: (newValue) { + ref + .read(prefsChangeNotifierProvider) + .biometricsDuress = newValue; + }, + ), + ), + ], + ), + ), + ); + }, + ), + ), + ], + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/auto_backup_view.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/auto_backup_view.dart index f41891bb6..57785f5f4 100644 --- a/lib/pages/settings_views/global_settings_view/stack_backup_views/auto_backup_view.dart +++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/auto_backup_view.dart @@ -95,9 +95,9 @@ class _AutoBackupViewState extends ConsumerState { title: "Enable Auto Backup", message: "To enable Auto Backup, you need to create a backup file.", leftButton: TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), + style: Theme.of( + context, + ).extension()!.getSecondaryEnabledButtonStyle(context), child: Text( "Back", style: STextStyles.button(context).copyWith( @@ -110,13 +110,10 @@ class _AutoBackupViewState extends ConsumerState { }, ), rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - child: Text( - "Continue", - style: STextStyles.button(context), - ), + style: Theme.of( + context, + ).extension()!.getPrimaryEnabledButtonStyle(context), + child: Text("Continue", style: STextStyles.button(context)), onPressed: () { Navigator.of(context).pop(true); }, @@ -126,9 +123,9 @@ class _AutoBackupViewState extends ConsumerState { ); if (mounted) { if (result is bool && result) { - Navigator.of(context) - .pushNamed(CreateAutoBackupView.routeName) - .then((_) { + Navigator.of(context).pushNamed(CreateAutoBackupView.routeName).then(( + _, + ) { // set toggle to correct state if (_toggle != ref.read(prefsChangeNotifierProvider).isAutoBackupEnabled) { @@ -152,9 +149,9 @@ class _AutoBackupViewState extends ConsumerState { message: "You are turning off Auto Backup. You can turn it back on at any time. Your previous Auto Backup file will not be deleted. Remember to backup your wallets manually so you don't lose important information.", leftButton: TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), + style: Theme.of( + context, + ).extension()!.getSecondaryEnabledButtonStyle(context), child: Text( "Back", style: STextStyles.button(context).copyWith( @@ -167,13 +164,10 @@ class _AutoBackupViewState extends ConsumerState { }, ), rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - child: Text( - "Disable", - style: STextStyles.button(context), - ), + style: Theme.of( + context, + ).extension()!.getPrimaryEnabledButtonStyle(context), + child: Text("Disable", style: STextStyles.button(context)), onPressed: () { Navigator.of(context).pop(true); }, @@ -184,8 +178,9 @@ class _AutoBackupViewState extends ConsumerState { if (mounted) { if (result is bool && result) { ref.read(prefsChangeNotifierProvider).isAutoBackupEnabled = false; - Navigator.of(context) - .popUntil(ModalRoute.withName(AutoBackupView.routeName)); + Navigator.of( + context, + ).popUntil(ModalRoute.withName(AutoBackupView.routeName)); } else { toggleController.activate?.call(); } @@ -233,11 +228,11 @@ class _AutoBackupViewState extends ConsumerState { ); ref.listen( - prefsChangeNotifierProvider - .select((value) => value.backupFrequencyType), - (previous, BackupFrequencyType next) { - frequencyController.text = Format.prettyFrequencyType(next); - }); + prefsChangeNotifierProvider.select((value) => value.backupFrequencyType), + (previous, BackupFrequencyType next) { + frequencyController.text = Format.prettyFrequencyType(next); + }, + ); return Background( child: Scaffold( @@ -248,232 +243,220 @@ class _AutoBackupViewState extends ConsumerState { Navigator.of(context).pop(); }, ), - title: Text( - "Auto Backup", - style: STextStyles.navBarTitle(context), - ), + title: Text("Auto Backup", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: null, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 20, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Auto Backup", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - key: const Key("autoBackupToggleButtonKey"), - isOn: _toggle, - controller: toggleController, - onValueChanged: (newValue) async { - _toggle = newValue; + onPressed: null, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 20, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Auto Backup", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + SizedBox( + height: 20, + width: 40, + child: DraggableSwitchButton( + key: const Key("autoBackupToggleButtonKey"), + isOn: _toggle, + controller: toggleController, + onValueChanged: (newValue) async { + _toggle = newValue; - if (_toggle) { - attemptEnable(); - } else { - attemptDisable(); - } - }, + if (_toggle) { + attemptEnable(); + } else { + attemptDisable(); + } + }, + ), ), - ), - ], - ), - ), - ), - ), - const SizedBox( - height: 8, - ), - if (!isEnabledAutoBackup) - RoundedWhiteContainer( - child: RichText( - textAlign: TextAlign.left, - text: TextSpan( - style: STextStyles.label(context), - children: [ - const TextSpan( - text: - "Auto Backup is a custom ${AppConfig.appName} feature that offers a convenient backup of your data.\n\nTo ensure maximum security, we recommend using a unique password that you haven't used anywhere else on the internet before. Your password is not stored.\n\nFor more information, please see our website ", - ), - TextSpan( - text: "stackwallet.com.", - style: STextStyles.richLink(context), - recognizer: TapGestureRecognizer() - ..onTap = () { - launchUrl( - Uri.parse("https://stackwallet.com"), - mode: LaunchMode.externalApplication, - ); - }, - ), - ], + ], + ), ), ), ), - if (isEnabledAutoBackup) - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - RoundedWhiteContainer( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + const SizedBox(height: 8), + if (!isEnabledAutoBackup) + RoundedWhiteContainer( + child: RichText( + textAlign: TextAlign.left, + text: TextSpan( + style: STextStyles.label(context), children: [ - CustomTextButton( - text: "Back up now", - onTap: () { - ref.read(autoSWBServiceProvider).doBackup(); - }, + const TextSpan( + text: + "Auto Backup is a custom ${AppConfig.appName} feature that offers a convenient backup of your data.\n\nTo ensure maximum security, we recommend using a unique password that you haven't used anywhere else on the internet before. Your password is not stored.\n\nFor more information, please see our website ", ), - Text( - "Backed up ${prettySinceLastBackupString(ref.watch(prefsChangeNotifierProvider.select((value) => value.lastAutoBackup)))}", - style: STextStyles.itemSubtitle(context), + TextSpan( + text: "stackwallet.com.", + style: STextStyles.richLink(context), + recognizer: + TapGestureRecognizer() + ..onTap = () { + launchUrl( + Uri.parse("https://stackwallet.com"), + mode: LaunchMode.externalApplication, + ); + }, ), ], ), ), - const SizedBox( - height: 32, - ), - Text( - "Auto Backup file", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 10, - ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + ), + if (isEnabledAutoBackup) + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + RoundedWhiteContainer( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + CustomTextButton( + text: "Back up now", + onTap: () { + ref.read(autoSWBServiceProvider).doBackup(); + }, + ), + Text( + "Backed up ${prettySinceLastBackupString(ref.watch(prefsChangeNotifierProvider.select((value) => value.lastAutoBackup)))}", + style: STextStyles.itemSubtitle(context), + ), + ], + ), ), - child: TextField( - key: const Key("backupSavedToFileLocationTextFieldKey"), - focusNode: fileLocationFocusNode, - controller: fileLocationController, - enabled: false, - style: STextStyles.field(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark - .withOpacity(0.5), + const SizedBox(height: 32), + Text( + "Auto Backup file", + style: STextStyles.smallMed12(context), + ), + const SizedBox(height: 10), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - readOnly: true, - enableSuggestions: false, - autocorrect: false, - toolbarOptions: const ToolbarOptions( - copy: true, - cut: false, - paste: false, - selectAll: true, + child: TextField( + key: const Key( + "backupSavedToFileLocationTextFieldKey", + ), + focusNode: fileLocationFocusNode, + controller: fileLocationController, + enabled: false, + style: STextStyles.field(context).copyWith( + color: Theme.of(context) + .extension()! + .textDark + .withOpacity(0.5), + ), + readOnly: true, + enableSuggestions: false, + autocorrect: false, + toolbarOptions: const ToolbarOptions( + copy: true, + cut: false, + paste: false, + selectAll: true, + ), + decoration: standardInputDecoration( + "Saved to", + fileLocationFocusNode, + context, + ), ), - decoration: standardInputDecoration( - "Saved to", - fileLocationFocusNode, - context, + ), + const SizedBox(height: 10), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + key: const Key("backupPasswordFieldKey"), + focusNode: passwordFocusNode, + controller: passwordController, + enabled: false, + style: STextStyles.field(context).copyWith( + color: Theme.of(context) + .extension()! + .textDark + .withOpacity(0.5), + ), + obscureText: true, + enableSuggestions: false, + autocorrect: false, + toolbarOptions: const ToolbarOptions( + copy: true, + cut: false, + paste: false, + selectAll: true, + ), + decoration: standardInputDecoration( + "Passphrase", + passwordFocusNode, + context, + ), ), ), - ), - const SizedBox( - height: 10, - ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + const SizedBox(height: 12), + Text( + "Auto Backup frequency", + style: STextStyles.smallMed12(context), ), - child: TextField( - key: const Key("backupPasswordFieldKey"), - focusNode: passwordFocusNode, - controller: passwordController, + const SizedBox(height: 10), + TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, + key: const Key("backupFrequencyFieldKey"), + controller: frequencyController, enabled: false, style: STextStyles.field(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark - .withOpacity(0.5), + color: Theme.of( + context, + ).extension()!.textDark.withOpacity(0.5), ), - obscureText: true, - enableSuggestions: false, - autocorrect: false, toolbarOptions: const ToolbarOptions( copy: true, cut: false, paste: false, selectAll: true, ), - decoration: standardInputDecoration( - "Passphrase", - passwordFocusNode, - context, - ), ), - ), - const SizedBox( - height: 12, - ), - Text( - "Auto Backup frequency", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 10, - ), - TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - key: const Key("backupFrequencyFieldKey"), - controller: frequencyController, - enabled: false, - style: STextStyles.field(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark - .withOpacity(0.5), - ), - toolbarOptions: const ToolbarOptions( - copy: true, - cut: false, - paste: false, - selectAll: true, - ), - ), - const SizedBox( - height: 20, - ), - Center( - child: CustomTextButton( - text: "Edit Auto Backup", - onTap: () async { - Navigator.of(context) - .pushNamed(EditAutoBackupView.routeName); - }, + const SizedBox(height: 20), + Center( + child: CustomTextButton( + text: "Edit Auto Backup", + onTap: () async { + Navigator.of( + context, + ).pushNamed(EditAutoBackupView.routeName); + }, + ), ), - ), - ], - ), - ], + ], + ), + ], + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/create_auto_backup_view.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/create_auto_backup_view.dart index c75ac4a83..5616ccd9d 100644 --- a/lib/pages/settings_views/global_settings_view/stack_backup_views/create_auto_backup_view.dart +++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/create_auto_backup_view.dart @@ -41,9 +41,7 @@ import 'helpers/swb_file_system.dart'; import 'sub_views/backup_frequency_type_select_sheet.dart'; class CreateAutoBackupView extends ConsumerStatefulWidget { - const CreateAutoBackupView({ - super.key, - }); + const CreateAutoBackupView({super.key}); static const String routeName = "/createAutoBackup"; @@ -134,567 +132,587 @@ class _EnableAutoBackupViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Text( - "Create your backup file", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 10, - ), - if (!Platform.isAndroid && !Platform.isIOS) - TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - onTap: Platform.isAndroid || Platform.isIOS - ? null - : () async { - try { - await stackFileSystem.prepareStorage(); - - if (mounted) { - await stackFileSystem.pickDir(context); - } - - if (mounted) { - setState(() { - fileLocationController.text = - stackFileSystem.dirPath ?? ""; - }); - } - } catch (e, s) { - Logging.instance - .e("$e\n$s", error: e, stackTrace: s); - } - }, - controller: fileLocationController, - style: STextStyles.field(context), - decoration: InputDecoration( - hintText: "Save to...", - hintStyle: STextStyles.fieldLabel(context), - suffixIcon: UnconstrainedBox( - child: Row( - children: [ - const SizedBox( - width: 16, - ), - SvgPicture.asset( - Assets.svg.folder, - color: Theme.of(context) - .extension()! - .textDark3, - width: 16, - height: 16, - ), - const SizedBox( - width: 12, - ), - ], - ), - ), - ), - key: const Key( - "createBackupSaveToFileLocationTextFieldKey", - ), - readOnly: true, - toolbarOptions: const ToolbarOptions( - copy: true, - cut: false, - paste: false, - selectAll: false, - ), - onChanged: (newValue) {}, - ), - if (!Platform.isAndroid && !Platform.isIOS) - const SizedBox( - height: 10, - ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text( + "Create your backup file", + style: STextStyles.smallMed12(context), ), - child: TextField( - key: const Key("createBackupPasswordFieldKey1"), - focusNode: passwordFocusNode, - controller: passwordController, - style: STextStyles.field(context), - obscureText: hidePassword, - enableSuggestions: false, - autocorrect: false, - decoration: standardInputDecoration( - "Create passphrase", - passwordFocusNode, - context, - ).copyWith( - suffixIcon: UnconstrainedBox( - child: Row( - children: [ - const SizedBox( - width: 16, - ), - GestureDetector( - key: const Key( - "createBackupPasswordFieldShowPasswordButtonKey", - ), - onTap: () async { - setState(() { - hidePassword = !hidePassword; - }); + const SizedBox(height: 10), + if (!Platform.isAndroid && !Platform.isIOS) + TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, + onTap: + Platform.isAndroid || Platform.isIOS + ? null + : () async { + try { + await stackFileSystem + .prepareStorage(); + + if (mounted) { + await stackFileSystem.pickDir( + context, + ); + } + + if (mounted) { + setState(() { + fileLocationController.text = + stackFileSystem.dirPath ?? ""; + }); + } + } catch (e, s) { + Logging.instance.e( + "$e\n$s", + error: e, + stackTrace: s, + ); + } }, - child: SvgPicture.asset( - hidePassword - ? Assets.svg.eye - : Assets.svg.eyeSlash, - color: Theme.of(context) - .extension()! - .textDark3, + controller: fileLocationController, + style: STextStyles.field(context), + decoration: InputDecoration( + hintText: "Save to...", + hintStyle: STextStyles.fieldLabel(context), + suffixIcon: UnconstrainedBox( + child: Row( + children: [ + const SizedBox(width: 16), + SvgPicture.asset( + Assets.svg.folder, + color: + Theme.of(context) + .extension()! + .textDark3, width: 16, height: 16, ), - ), - const SizedBox( - width: 12, - ), - ], + const SizedBox(width: 12), + ], + ), ), ), + key: const Key( + "createBackupSaveToFileLocationTextFieldKey", + ), + readOnly: true, + toolbarOptions: const ToolbarOptions( + copy: true, + cut: false, + paste: false, + selectAll: false, + ), + onChanged: (newValue) {}, + ), + if (!Platform.isAndroid && !Platform.isIOS) + const SizedBox(height: 10), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - onChanged: (newValue) { - if (newValue.isEmpty) { + child: TextField( + key: const Key("createBackupPasswordFieldKey1"), + focusNode: passwordFocusNode, + controller: passwordController, + style: STextStyles.field(context), + obscureText: hidePassword, + enableSuggestions: false, + autocorrect: false, + decoration: standardInputDecoration( + "Create passphrase", + passwordFocusNode, + context, + ).copyWith( + suffixIcon: UnconstrainedBox( + child: Row( + children: [ + const SizedBox(width: 16), + GestureDetector( + key: const Key( + "createBackupPasswordFieldShowPasswordButtonKey", + ), + onTap: () async { + setState(() { + hidePassword = !hidePassword; + }); + }, + child: SvgPicture.asset( + hidePassword + ? Assets.svg.eye + : Assets.svg.eyeSlash, + color: + Theme.of(context) + .extension()! + .textDark3, + width: 16, + height: 16, + ), + ), + const SizedBox(width: 12), + ], + ), + ), + ), + onChanged: (newValue) { + if (newValue.isEmpty) { + setState(() { + passwordFeedback = ""; + }); + return; + } + final result = zxcvbn.evaluate(newValue); + String suggestionsAndTips = ""; + for (final sug + in result.feedback.suggestions!.toSet()) { + suggestionsAndTips += "$sug\n"; + } + suggestionsAndTips += result.feedback.warning!; + String feedback = + // "Password Strength: ${((result.score! / 4.0) * 100).toInt()}%\n" + suggestionsAndTips; + + passwordStrength = result.score! / 4; + + // hack fix to format back string returned from zxcvbn + if (feedback.contains("phrasesNo need")) { + feedback = feedback.replaceFirst( + "phrasesNo need", + "phrases\nNo need", + ); + } + + if (feedback.endsWith("\n")) { + feedback = feedback.substring( + 0, + feedback.length - 2, + ); + } + setState(() { - passwordFeedback = ""; + passwordFeedback = feedback; }); - return; - } - final result = zxcvbn.evaluate(newValue); - String suggestionsAndTips = ""; - for (final sug - in result.feedback.suggestions!.toSet()) { - suggestionsAndTips += "$sug\n"; - } - suggestionsAndTips += result.feedback.warning!; - String feedback = - // "Password Strength: ${((result.score! / 4.0) * 100).toInt()}%\n" - suggestionsAndTips; - - passwordStrength = result.score! / 4; - - // hack fix to format back string returned from zxcvbn - if (feedback.contains("phrasesNo need")) { - feedback = feedback.replaceFirst( - "phrasesNo need", - "phrases\nNo need", - ); - } - - if (feedback.endsWith("\n")) { - feedback = - feedback.substring(0, feedback.length - 2); - } - - setState(() { - passwordFeedback = feedback; - }); - }, - ), - ), - if (passwordFocusNode.hasFocus || - passwordRepeatFocusNode.hasFocus || - passwordController.text.isNotEmpty) - Padding( - padding: EdgeInsets.only( - left: 12, - right: 12, - top: passwordFeedback.isNotEmpty ? 4 : 0, + }, ), - child: passwordFeedback.isNotEmpty - ? Text( - passwordFeedback, - style: STextStyles.infoSmall(context), - ) - : null, ), - if (passwordFocusNode.hasFocus || - passwordRepeatFocusNode.hasFocus || - passwordController.text.isNotEmpty) - Padding( - padding: const EdgeInsets.only( - left: 12, - right: 12, - top: 10, - ), - child: ProgressBar( - key: const Key("createStackBackUpProgressBar"), - width: - MediaQuery.of(context).size.width - 32 - 24, - height: 5, - fillColor: passwordStrength < 0.51 - ? Theme.of(context) - .extension()! - .accentColorRed - : passwordStrength < 1 - ? Theme.of(context) - .extension()! - .accentColorYellow - : Theme.of(context) - .extension()! - .accentColorGreen, - backgroundColor: Theme.of(context) - .extension()! - .buttonBackSecondary, - percent: passwordStrength < 0.25 - ? 0.03 - : passwordStrength, + if (passwordFocusNode.hasFocus || + passwordRepeatFocusNode.hasFocus || + passwordController.text.isNotEmpty) + Padding( + padding: EdgeInsets.only( + left: 12, + right: 12, + top: passwordFeedback.isNotEmpty ? 4 : 0, + ), + child: + passwordFeedback.isNotEmpty + ? Text( + passwordFeedback, + style: STextStyles.infoSmall(context), + ) + : null, ), - ), - const SizedBox( - height: 10, - ), - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - key: const Key("createBackupPasswordFieldKey2"), - focusNode: passwordRepeatFocusNode, - controller: passwordRepeatController, - style: STextStyles.field(context), - obscureText: hidePassword, - enableSuggestions: false, - autocorrect: false, - decoration: standardInputDecoration( - "Confirm passphrase", - passwordRepeatFocusNode, - context, - ).copyWith( - suffixIcon: UnconstrainedBox( - child: Row( - children: [ - const SizedBox( - width: 16, - ), - GestureDetector( - key: const Key( - "createBackupPasswordFieldShowPasswordButtonKey", - ), - onTap: () async { - setState(() { - hidePassword = !hidePassword; - }); - }, - child: SvgPicture.asset( - hidePassword - ? Assets.svg.eye - : Assets.svg.eyeSlash, - color: Theme.of(context) + if (passwordFocusNode.hasFocus || + passwordRepeatFocusNode.hasFocus || + passwordController.text.isNotEmpty) + Padding( + padding: const EdgeInsets.only( + left: 12, + right: 12, + top: 10, + ), + child: ProgressBar( + key: const Key("createStackBackUpProgressBar"), + width: + MediaQuery.of(context).size.width - 32 - 24, + height: 5, + fillColor: + passwordStrength < 0.51 + ? Theme.of(context) .extension()! - .textDark3, - width: 16, - height: 16, - ), - ), - const SizedBox( - width: 12, - ), - ], - ), + .accentColorRed + : passwordStrength < 1 + ? Theme.of(context) + .extension()! + .accentColorYellow + : Theme.of(context) + .extension()! + .accentColorGreen, + backgroundColor: + Theme.of(context) + .extension()! + .buttonBackSecondary, + percent: + passwordStrength < 0.25 + ? 0.03 + : passwordStrength, ), ), - onChanged: (newValue) { - setState(() {}); - // TODO: ? check if passwords match? - }, - ), - ), - const SizedBox( - height: 32, - ), - Text( - "Auto Backup frequency", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 10, - ), - Stack( - children: [ - TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - readOnly: true, - textInputAction: TextInputAction.none, + const SizedBox(height: 10), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - Positioned.fill( - child: RawMaterialButton( - splashColor: Theme.of(context) - .extension()! - .highlight, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: () { - showModalBottomSheet( - backgroundColor: Colors.transparent, - context: context, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.vertical( - top: Radius.circular(20), - ), - ), - builder: (_) => - const BackupFrequencyTypeSelectSheet(), - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - ), + child: TextField( + key: const Key("createBackupPasswordFieldKey2"), + focusNode: passwordRepeatFocusNode, + controller: passwordRepeatController, + style: STextStyles.field(context), + obscureText: hidePassword, + enableSuggestions: false, + autocorrect: false, + decoration: standardInputDecoration( + "Confirm passphrase", + passwordRepeatFocusNode, + context, + ).copyWith( + suffixIcon: UnconstrainedBox( child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, children: [ - Text( - Format.prettyFrequencyType( - ref.watch( - prefsChangeNotifierProvider.select( - (value) => - value.backupFrequencyType, - ), - ), + const SizedBox(width: 16), + GestureDetector( + key: const Key( + "createBackupPasswordFieldShowPasswordButtonKey", ), - style: - STextStyles.itemSubtitle12(context), - ), - Padding( - padding: - const EdgeInsets.only(right: 4.0), + onTap: () async { + setState(() { + hidePassword = !hidePassword; + }); + }, child: SvgPicture.asset( - Assets.svg.chevronDown, - color: Theme.of(context) - .extension()! - .textSubtitle2, - width: 12, - height: 6, + hidePassword + ? Assets.svg.eye + : Assets.svg.eyeSlash, + color: + Theme.of(context) + .extension()! + .textDark3, + width: 16, + height: 16, ), ), + const SizedBox(width: 12), ], ), ), ), + onChanged: (newValue) { + setState(() {}); + // TODO: ? check if passwords match? + }, ), - ], - ), - const Spacer(), - const SizedBox( - height: 10, - ), - TextButton( - style: shouldEnableCreate - ? Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context) - : Theme.of(context) - .extension()! - .getPrimaryDisabledButtonStyle(context), - onPressed: !shouldEnableCreate - ? null - : () async { - final String pathToSave = - fileLocationController.text; - final String passphrase = - passwordController.text; - final String repeatPassphrase = - passwordRepeatController.text; - - if (pathToSave.isEmpty) { - showFloatingFlushBar( - type: FlushBarType.warning, - message: "Directory not chosen", - context: context, - ); - return; - } - if (!(await Directory(pathToSave).exists())) { - showFloatingFlushBar( - type: FlushBarType.warning, - message: "Directory does not exist", - context: context, - ); - return; - } - if (passphrase.isEmpty) { - showFloatingFlushBar( - type: FlushBarType.warning, - message: "A passphrase is required", - context: context, - ); - return; - } - if (passphrase != repeatPassphrase) { - showFloatingFlushBar( - type: FlushBarType.warning, - message: "Passphrase does not match", - context: context, - ); - return; - } - - showDialog( - context: context, - barrierDismissible: false, - builder: (_) => const StackDialog( - title: "Encrypting initial backup", - message: "This shouldn't take long", + ), + const SizedBox(height: 32), + Text( + "Auto Backup frequency", + style: STextStyles.smallMed12(context), + ), + const SizedBox(height: 10), + Stack( + children: [ + TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: + Util.isDesktop ? false : true, + readOnly: true, + textInputAction: TextInputAction.none, + ), + Positioned.fill( + child: RawMaterialButton( + splashColor: + Theme.of( + context, + ).extension()!.highlight, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - ); - - // make sure the dialog is able to be displayed for at least some time - final fut = Future.delayed( - const Duration(milliseconds: 300), - ); - - String adkString; - int adkVersion; - try { - final adk = - await compute(generateAdk, passphrase); - adkString = - Format.uint8listToString(adk.item2); - adkVersion = adk.item1; - } on Exception catch (e, s) { - final String err = - getErrorMessageFromSWBException(e); - Logging.instance - .e("$err\n$s", error: e, stackTrace: s); - // pop encryption progress dialog - Navigator.of(context).pop(); - showFloatingFlushBar( - type: FlushBarType.warning, - message: err, - context: context, - ); - return; - } catch (e, s) { - Logging.instance.e( - "", - error: e, - stackTrace: s, - ); - // pop encryption progress dialog - Navigator.of(context).pop(); - showFloatingFlushBar( - type: FlushBarType.warning, - message: "$e", + ), + onPressed: () { + showModalBottomSheet( + backgroundColor: Colors.transparent, context: context, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(20), + ), + ), + builder: + (_) => + const BackupFrequencyTypeSelectSheet(), ); - return; - } - - await secureStore.write( - key: "auto_adk_string", - value: adkString, - ); - await secureStore.write( - key: "auto_adk_version_string", - value: adkVersion.toString(), - ); - - final DateTime now = DateTime.now(); - final String fileToSave = - createAutoBackupFilename(pathToSave, now); - - final backup = - await SWB.createStackWalletJSON( - secureStorage: secureStore, - ); - - final bool result = - await SWB.encryptStackWalletWithADK( - fileToSave, - adkString, - jsonEncode(backup), - adkVersion, - ); - - // this future should already be complete unless there was an error encrypting - await Future.wait([fut]); - - if (mounted) { - // pop encryption progress dialog - Navigator.of(context).pop(); - - if (result) { - ref - .read(prefsChangeNotifierProvider) - .autoBackupLocation = pathToSave; - ref - .read(prefsChangeNotifierProvider) - .lastAutoBackup = now; - - ref - .read(prefsChangeNotifierProvider) - .isAutoBackupEnabled = true; + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12.0, + ), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + Format.prettyFrequencyType( + ref.watch( + prefsChangeNotifierProvider.select( + (value) => + value.backupFrequencyType, + ), + ), + ), + style: STextStyles.itemSubtitle12( + context, + ), + ), + Padding( + padding: const EdgeInsets.only( + right: 4.0, + ), + child: SvgPicture.asset( + Assets.svg.chevronDown, + color: + Theme.of(context) + .extension()! + .textSubtitle2, + width: 12, + height: 6, + ), + ), + ], + ), + ), + ), + ), + ], + ), + const Spacer(), + const SizedBox(height: 10), + TextButton( + style: + shouldEnableCreate + ? Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context) + : Theme.of(context) + .extension()! + .getPrimaryDisabledButtonStyle(context), + onPressed: + !shouldEnableCreate + ? null + : () async { + final String pathToSave = + fileLocationController.text; + final String passphrase = + passwordController.text; + final String repeatPassphrase = + passwordRepeatController.text; + + if (pathToSave.isEmpty) { + showFloatingFlushBar( + type: FlushBarType.warning, + message: "Directory not chosen", + context: context, + ); + return; + } + if (!(await Directory( + pathToSave, + ).exists())) { + showFloatingFlushBar( + type: FlushBarType.warning, + message: "Directory does not exist", + context: context, + ); + return; + } + if (passphrase.isEmpty) { + showFloatingFlushBar( + type: FlushBarType.warning, + message: "A passphrase is required", + context: context, + ); + return; + } + if (passphrase != repeatPassphrase) { + showFloatingFlushBar( + type: FlushBarType.warning, + message: "Passphrase does not match", + context: context, + ); + return; + } - await showDialog( + showDialog( context: context, barrierDismissible: false, - builder: (_) => Platform.isAndroid - ? StackOkDialog( - title: - "${AppConfig.prefix} Auto Backup enabled and saved to:", - message: fileToSave, - ) - : const StackOkDialog( - title: - "${AppConfig.prefix} Auto Backup enabled!", - ), + builder: + (_) => const StackDialog( + title: + "Encrypting initial backup", + message: + "This shouldn't take long", + ), ); - if (mounted) { - passwordController.text = ""; - passwordRepeatController.text = ""; - Navigator.of(context).popUntil( - ModalRoute.withName( - AutoBackupView.routeName, - ), + // make sure the dialog is able to be displayed for at least some time + final fut = Future.delayed( + const Duration(milliseconds: 300), + ); + + String adkString; + int adkVersion; + try { + final adk = await compute( + generateAdk, + passphrase, + ); + adkString = Format.uint8listToString( + adk.item2, + ); + adkVersion = adk.item1; + } on Exception catch (e, s) { + final String err = + getErrorMessageFromSWBException(e); + Logging.instance.e( + "$err\n$s", + error: e, + stackTrace: s, + ); + // pop encryption progress dialog + Navigator.of(context).pop(); + showFloatingFlushBar( + type: FlushBarType.warning, + message: err, + context: context, ); + return; + } catch (e, s) { + Logging.instance.e( + "", + error: e, + stackTrace: s, + ); + // pop encryption progress dialog + Navigator.of(context).pop(); + showFloatingFlushBar( + type: FlushBarType.warning, + message: "$e", + context: context, + ); + return; } - } else { - await showDialog( - context: context, - barrierDismissible: false, - builder: (_) => const StackOkDialog( - title: "Failed to enable Auto Backup", - ), + + await secureStore.write( + key: "auto_adk_string", + value: adkString, + ); + await secureStore.write( + key: "auto_adk_version_string", + value: adkVersion.toString(), ); - } - } - }, - child: Text( - "Enable Auto Backup", - style: STextStyles.button(context), + + final DateTime now = DateTime.now(); + final String fileToSave = + createAutoBackupFilename( + pathToSave, + now, + ); + + final backup = await SWB + .createStackWalletJSON( + secureStorage: secureStore, + ); + + final bool result = await SWB + .encryptStackWalletWithADK( + fileToSave, + adkString, + jsonEncode(backup), + adkVersion, + ); + + // this future should already be complete unless there was an error encrypting + await Future.wait([fut]); + + if (mounted) { + // pop encryption progress dialog + Navigator.of(context).pop(); + + if (result) { + ref + .read(prefsChangeNotifierProvider) + .autoBackupLocation = pathToSave; + ref + .read(prefsChangeNotifierProvider) + .lastAutoBackup = now; + + ref + .read(prefsChangeNotifierProvider) + .isAutoBackupEnabled = true; + + await showDialog( + context: context, + barrierDismissible: false, + builder: + (_) => + Platform.isAndroid + ? StackOkDialog( + title: + "${AppConfig.prefix} Auto Backup enabled and saved to:", + message: fileToSave, + ) + : const StackOkDialog( + title: + "${AppConfig.prefix} Auto Backup enabled!", + ), + ); + if (mounted) { + passwordController.text = ""; + passwordRepeatController.text = ""; + + Navigator.of(context).popUntil( + ModalRoute.withName( + AutoBackupView.routeName, + ), + ); + } + } else { + await showDialog( + context: context, + barrierDismissible: false, + builder: + (_) => const StackOkDialog( + title: + "Failed to enable Auto Backup", + ), + ); + } + } + }, + child: Text( + "Enable Auto Backup", + style: STextStyles.button(context), + ), ), - ), - ], + ], + ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/create_backup_information_view.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/create_backup_information_view.dart index 8b1c72ebd..3088b69ac 100644 --- a/lib/pages/settings_views/global_settings_view/stack_backup_views/create_backup_information_view.dart +++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/create_backup_information_view.dart @@ -9,12 +9,13 @@ */ import 'package:flutter/material.dart'; -import 'create_backup_view.dart'; + import '../../../../themes/stack_colors.dart'; import '../../../../utilities/text_styles.dart'; import '../../../../widgets/background.dart'; import '../../../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../../../widgets/rounded_white_container.dart'; +import 'create_backup_view.dart'; class CreateBackupInfoView extends StatelessWidget { const CreateBackupInfoView({super.key}); @@ -36,63 +37,59 @@ class CreateBackupInfoView extends StatelessWidget { Navigator.of(context).pop(); }, ), - title: Text( - "Create backup", - style: STextStyles.navBarTitle(context), - ), + title: Text("Create backup", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Center( - child: Text( - "Info", - style: STextStyles.pageTitleH2(context), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Center( + child: Text( + "Info", + style: STextStyles.pageTitleH2(context), + ), ), - ), - const SizedBox( - height: 16, - ), - RoundedWhiteContainer( - child: Text( - // TODO: need info - "{lorem ipsum}", - style: STextStyles.baseXS(context), + const SizedBox(height: 16), + RoundedWhiteContainer( + child: Text( + // TODO: need info + "{lorem ipsum}", + style: STextStyles.baseXS(context), + ), ), - ), - const SizedBox( - height: 16, - ), - const Spacer(), - TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - onPressed: () { - Navigator.of(context) - .pushNamed(CreateBackupView.routeName); - }, - child: Text( - "Next", - style: STextStyles.button(context), + const SizedBox(height: 16), + const Spacer(), + TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + onPressed: () { + Navigator.of( + context, + ).pushNamed(CreateBackupView.routeName); + }, + child: Text( + "Next", + style: STextStyles.button(context), + ), ), - ), - ], + ], + ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/create_backup_view.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/create_backup_view.dart index 944847a42..a04f0de24 100644 --- a/lib/pages/settings_views/global_settings_view/stack_backup_views/create_backup_view.dart +++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/create_backup_view.dart @@ -138,21 +138,21 @@ class _RestoreFromFileViewState extends State { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: child, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight(child: child), ), - ), - ); - }, + ); + }, + ), ), ), ), @@ -168,8 +168,9 @@ class _RestoreFromFileViewState extends State { padding: const EdgeInsets.only(bottom: 10), child: Text( "Choose file location", - style: - STextStyles.desktopTextExtraExtraSmall(context).copyWith( + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( color: Theme.of(context).extension()!.textDark3, ), @@ -190,30 +191,31 @@ class _RestoreFromFileViewState extends State { child: TextField( autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, - onTap: Platform.isAndroid || Platform.isIOS - ? null - : () async { - try { - await stackFileSystem.prepareStorage(); - - if (mounted) { - await stackFileSystem.pickDir(context); - } + onTap: + Platform.isAndroid || Platform.isIOS + ? null + : () async { + try { + await stackFileSystem.prepareStorage(); + + if (mounted) { + await stackFileSystem.pickDir(context); + } - if (mounted) { - setState(() { - fileLocationController.text = - stackFileSystem.dirPath ?? ""; - }); + if (mounted) { + setState(() { + fileLocationController.text = + stackFileSystem.dirPath ?? ""; + }); + } + } catch (e, s) { + Logging.instance.e( + "", + error: e, + stackTrace: s, + ); } - } catch (e, s) { - Logging.instance.e( - "", - error: e, - stackTrace: s, - ); - } - }, + }, controller: fileLocationController, style: STextStyles.field(context), decoration: InputDecoration( @@ -222,26 +224,24 @@ class _RestoreFromFileViewState extends State { suffixIcon: UnconstrainedBox( child: Row( children: [ - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), SvgPicture.asset( Assets.svg.folder, - color: Theme.of(context) - .extension()! - .textDark3, + color: + Theme.of( + context, + ).extension()!.textDark3, width: 16, height: 16, ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), ], ), ), ), key: const Key( - "createBackupSaveToFileLocationTextFieldKey"), + "createBackupSaveToFileLocationTextFieldKey", + ), readOnly: true, toolbarOptions: const ToolbarOptions( copy: true, @@ -257,16 +257,15 @@ class _RestoreFromFileViewState extends State { }, ), if (!Platform.isAndroid && !Platform.isIOS) - SizedBox( - height: !isDesktop ? 8 : 24, - ), + SizedBox(height: !isDesktop ? 8 : 24), if (isDesktop) Padding( padding: const EdgeInsets.only(bottom: 10.0), child: Text( "Create a passphrase", - style: - STextStyles.desktopTextExtraExtraSmall(context).copyWith( + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( color: Theme.of(context).extension()!.textDark3, ), @@ -295,9 +294,7 @@ class _RestoreFromFileViewState extends State { suffixIcon: UnconstrainedBox( child: Row( children: [ - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), GestureDetector( key: const Key( "createBackupPasswordFieldShowPasswordButtonKey", @@ -309,16 +306,15 @@ class _RestoreFromFileViewState extends State { }, child: SvgPicture.asset( hidePassword ? Assets.svg.eye : Assets.svg.eyeSlash, - color: Theme.of(context) - .extension()! - .textDark3, + color: + Theme.of( + context, + ).extension()!.textDark3, width: 16, height: 16, ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), ], ), ), @@ -369,46 +365,43 @@ class _RestoreFromFileViewState extends State { right: 12, top: passwordFeedback.isNotEmpty ? 4 : 0, ), - child: passwordFeedback.isNotEmpty - ? Text( - passwordFeedback, - style: STextStyles.infoSmall(context), - ) - : null, + child: + passwordFeedback.isNotEmpty + ? Text( + passwordFeedback, + style: STextStyles.infoSmall(context), + ) + : null, ), if (passwordFocusNode.hasFocus || passwordRepeatFocusNode.hasFocus || passwordController.text.isNotEmpty) Padding( - padding: const EdgeInsets.only( - left: 12, - right: 12, - top: 10, - ), + padding: const EdgeInsets.only(left: 12, right: 12, top: 10), child: ProgressBar( key: const Key("createStackBackUpProgressBar"), width: MediaQuery.of(context).size.width - 32 - 24, height: 5, - fillColor: passwordStrength < 0.51 - ? Theme.of(context) - .extension()! - .accentColorRed - : passwordStrength < 1 - ? Theme.of(context) - .extension()! - .accentColorYellow - : Theme.of(context) - .extension()! - .accentColorGreen, - backgroundColor: Theme.of(context) - .extension()! - .buttonBackSecondary, + fillColor: + passwordStrength < 0.51 + ? Theme.of( + context, + ).extension()!.accentColorRed + : passwordStrength < 1 + ? Theme.of( + context, + ).extension()!.accentColorYellow + : Theme.of( + context, + ).extension()!.accentColorGreen, + backgroundColor: + Theme.of( + context, + ).extension()!.buttonBackSecondary, percent: passwordStrength < 0.25 ? 0.03 : passwordStrength, ), ), - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -431,9 +424,7 @@ class _RestoreFromFileViewState extends State { suffixIcon: UnconstrainedBox( child: Row( children: [ - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), GestureDetector( key: const Key( "createBackupPasswordFieldShowPasswordButtonKey", @@ -445,16 +436,15 @@ class _RestoreFromFileViewState extends State { }, child: SvgPicture.asset( hidePassword ? Assets.svg.eye : Assets.svg.eyeSlash, - color: Theme.of(context) - .extension()! - .textDark3, + color: + Theme.of( + context, + ).extension()!.textDark3, width: 16, height: 16, ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), ], ), ), @@ -465,24 +455,24 @@ class _RestoreFromFileViewState extends State { }, ), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), if (!isDesktop) const Spacer(), !isDesktop ? Consumer( - builder: (context, ref, __) { - return TextButton( - style: shouldEnableCreate - ? Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context) - : Theme.of(context) - .extension()! - .getPrimaryDisabledButtonStyle(context), - onPressed: !shouldEnableCreate - ? null - : () async { + builder: (context, ref, __) { + return TextButton( + style: + shouldEnableCreate + ? Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context) + : Theme.of(context) + .extension()! + .getPrimaryDisabledButtonStyle(context), + onPressed: + !shouldEnableCreate + ? null + : () async { final String pathToSave = fileLocationController.text; final String passphrase = @@ -535,10 +525,11 @@ class _RestoreFromFileViewState extends State { showDialog( context: context, barrierDismissible: false, - builder: (_) => const StackDialog( - title: "Encrypting backup", - message: "This shouldn't take long", - ), + builder: + (_) => const StackDialog( + title: "Encrypting backup", + message: "This shouldn't take long", + ), ), ); // make sure the dialog is able to be displayed for at least 1 second @@ -554,12 +545,12 @@ class _RestoreFromFileViewState extends State { secureStorage: ref.read(secureStoreProvider), ); - final bool result = - await SWB.encryptStackWalletWithPassphrase( - fileToSave, - passphrase, - jsonEncode(backup), - ); + final bool result = await SWB + .encryptStackWalletWithPassphrase( + fileToSave, + passphrase, + jsonEncode(backup), + ); if (mounted) { // pop encryption progress dialog @@ -569,15 +560,17 @@ class _RestoreFromFileViewState extends State { await showDialog( context: context, barrierDismissible: false, - builder: (_) => Platform.isAndroid - ? StackOkDialog( - title: "Backup saved to:", - message: fileToSave, - ) - : const StackOkDialog( - title: - "Backup creation succeeded", - ), + builder: + (_) => + Platform.isAndroid + ? StackOkDialog( + title: "Backup saved to:", + message: fileToSave, + ) + : const StackOkDialog( + title: + "Backup creation succeeded", + ), ); passwordController.text = ""; passwordRepeatController.text = ""; @@ -586,32 +579,34 @@ class _RestoreFromFileViewState extends State { await showDialog( context: context, barrierDismissible: false, - builder: (_) => const StackOkDialog( - title: "Backup creation failed", - ), + builder: + (_) => const StackOkDialog( + title: "Backup creation failed", + ), ); } } }, - child: Text( - "Create backup", - style: STextStyles.button(context), - ), - ); - }, - ) + child: Text( + "Create backup", + style: STextStyles.button(context), + ), + ); + }, + ) : Row( - children: [ - Consumer( - builder: (context, ref, __) { - return PrimaryButton( - width: 183, - buttonHeight: ButtonHeight.m, - label: "Create backup", - enabled: shouldEnableCreate, - onPressed: !shouldEnableCreate - ? null - : () async { + children: [ + Consumer( + builder: (context, ref, __) { + return PrimaryButton( + width: 183, + buttonHeight: ButtonHeight.m, + label: "Create backup", + enabled: shouldEnableCreate, + onPressed: + !shouldEnableCreate + ? null + : () async { final String pathToSave = fileLocationController.text; final String passphrase = @@ -629,8 +624,9 @@ class _RestoreFromFileViewState extends State { ); return; } - if (!(await Directory(pathToSave) - .exists())) { + if (!(await Directory( + pathToSave, + ).exists())) { unawaited( showFloatingFlushBar( type: FlushBarType.warning, @@ -684,18 +680,16 @@ class _RestoreFromFileViewState extends State { "Encrypting initial backup", style: STextStyles.desktopH3( - context, - ), - ), - const SizedBox( - height: 40, + context, + ), ), + const SizedBox(height: 40), Text( "This shouldn't take long", - style: STextStyles - .desktopTextExtraExtraSmall( - context, - ), + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ), ), ], ), @@ -726,18 +720,19 @@ class _RestoreFromFileViewState extends State { final String fileToSave = "$pathToSave/stackbackup_${now.year}_${now.month}_${now.day}_${now.hour}_${now.minute}_${now.second}.swb"; - final backup = - await SWB.createStackWalletJSON( - secureStorage: - ref.read(secureStoreProvider), - ); + final backup = await SWB + .createStackWalletJSON( + secureStorage: ref.read( + secureStoreProvider, + ), + ); final bool result = await SWB .encryptStackWalletWithPassphrase( - fileToSave, - passphrase, - jsonEncode(backup), - ); + fileToSave, + passphrase, + jsonEncode(backup), + ); await Future.wait([fut]); @@ -763,10 +758,10 @@ class _RestoreFromFileViewState extends State { child: Padding( padding: const EdgeInsets.only( - left: 32, - right: 32, - bottom: 32, - ), + left: 32, + right: 32, + bottom: 32, + ), child: Column( mainAxisSize: MainAxisSize.min, @@ -779,15 +774,17 @@ class _RestoreFromFileViewState extends State { ), Text( "${AppConfig.prefix} backup saved to: \n", - style: STextStyles - .desktopH3(context), + style: + STextStyles.desktopH3( + context, + ), ), Text( fileToSave, - style: STextStyles - .desktopTextExtraExtraSmall( - context, - ), + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ), ), const SizedBox( height: 40, @@ -796,8 +793,7 @@ class _RestoreFromFileViewState extends State { children: [ // const Spacer(), Expanded( - child: - PrimaryButton( + child: PrimaryButton( label: "Ok", buttonHeight: ButtonHeight @@ -835,27 +831,26 @@ class _RestoreFromFileViewState extends State { await showDialog( context: context, barrierDismissible: false, - builder: (_) => const StackOkDialog( - title: "Backup creation failed", - ), + builder: + (_) => const StackOkDialog( + title: "Backup creation failed", + ), ); } } }, - ); - }, - ), - const SizedBox( - width: 16, - ), - SecondaryButton( - width: 183, - buttonHeight: ButtonHeight.m, - label: "Cancel", - onPressed: () {}, - ), - ], - ), + ); + }, + ), + const SizedBox(width: 16), + SecondaryButton( + width: 183, + buttonHeight: ButtonHeight.m, + label: "Cancel", + onPressed: () {}, + ), + ], + ), ], ), ), diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/edit_auto_backup_view.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/edit_auto_backup_view.dart index 53669d9f0..5ad7eab46 100644 --- a/lib/pages/settings_views/global_settings_view/stack_backup_views/edit_auto_backup_view.dart +++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/edit_auto_backup_view.dart @@ -47,9 +47,7 @@ import 'helpers/swb_file_system.dart'; import 'sub_views/backup_frequency_type_select_sheet.dart'; class EditAutoBackupView extends ConsumerStatefulWidget { - const EditAutoBackupView({ - super.key, - }); + const EditAutoBackupView({super.key}); static const String routeName = "/editAutoBackup"; @@ -142,10 +140,11 @@ class _EditAutoBackupViewState extends ConsumerState { showDialog( context: context, barrierDismissible: false, - builder: (_) => const StackDialog( - title: "Updating Auto Backup", - message: "This shouldn't take long", - ), + builder: + (_) => const StackDialog( + title: "Updating Auto Backup", + message: "This shouldn't take long", + ), ), ); // make sure the dialog is able to be displayed for at least 1 second @@ -220,29 +219,33 @@ class _EditAutoBackupViewState extends ConsumerState { await showDialog( context: context, barrierDismissible: false, - builder: (_) => Platform.isAndroid - ? StackOkDialog( - title: "${AppConfig.prefix} Auto Backup saved to:", - message: fileToSave, - ) - : const StackOkDialog( - title: "${AppConfig.prefix} Auto Backup saved"), + builder: + (_) => + Platform.isAndroid + ? StackOkDialog( + title: "${AppConfig.prefix} Auto Backup saved to:", + message: fileToSave, + ) + : const StackOkDialog( + title: "${AppConfig.prefix} Auto Backup saved", + ), ); if (mounted) { passwordController.text = ""; passwordRepeatController.text = ""; if (!Util.isDesktop) { - Navigator.of(context) - .popUntil(ModalRoute.withName(AutoBackupView.routeName)); + Navigator.of( + context, + ).popUntil(ModalRoute.withName(AutoBackupView.routeName)); } } } else { await showDialog( context: context, barrierDismissible: false, - builder: (_) => - const StackOkDialog(title: "Failed to update Auto Backup"), + builder: + (_) => const StackOkDialog(title: "Failed to update Auto Backup"), ); } } @@ -299,49 +302,47 @@ class _EditAutoBackupViewState extends ConsumerState { return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () { - Navigator.of(context).pop(); - }, - ), - title: Text( - "Edit Auto Backup", - style: STextStyles.navBarTitle(context), - ), - ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: child, - ), + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () { + Navigator.of(context).pop(); + }, + ), + title: Text( + "Edit Auto Backup", + style: STextStyles.navBarTitle(context), + ), + ), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight(child: child), + ), + ); + }, ), - ); - }, + ), + ), ), ), - ), - ), child: Column( crossAxisAlignment: isDesktop ? CrossAxisAlignment.start : CrossAxisAlignment.stretch, children: [ if (!isDesktop) - Text( - "Create your backup", - style: STextStyles.smallMed12(context), - ), + Text("Create your backup", style: STextStyles.smallMed12(context)), if (isDesktop) Text( "Choose file location", @@ -350,33 +351,32 @@ class _EditAutoBackupViewState extends ConsumerState { ), textAlign: TextAlign.left, ), - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), if (!Platform.isAndroid && !Platform.isIOS) TextField( autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, - onTap: Platform.isAndroid || Platform.isIOS - ? null - : () async { - try { - await stackFileSystem.prepareStorage(); - - if (mounted) { - await stackFileSystem.pickDir(context); + onTap: + Platform.isAndroid || Platform.isIOS + ? null + : () async { + try { + await stackFileSystem.prepareStorage(); + + if (mounted) { + await stackFileSystem.pickDir(context); + } + + if (mounted) { + setState(() { + fileLocationController.text = + stackFileSystem.dirPath ?? ""; + }); + } + } catch (e, s) { + Logging.instance.e("$e\n$s", error: e, stackTrace: s); } - - if (mounted) { - setState(() { - fileLocationController.text = - stackFileSystem.dirPath ?? ""; - }); - } - } catch (e, s) { - Logging.instance.e("$e\n$s", error: e, stackTrace: s); - } - }, + }, controller: fileLocationController, style: STextStyles.field(context), decoration: InputDecoration( @@ -385,20 +385,17 @@ class _EditAutoBackupViewState extends ConsumerState { suffixIcon: UnconstrainedBox( child: Row( children: [ - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), SvgPicture.asset( Assets.svg.folder, - color: Theme.of(context) - .extension()! - .textDark3, + color: + Theme.of( + context, + ).extension()!.textDark3, width: 16, height: 16, ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), ], ), ), @@ -413,10 +410,7 @@ class _EditAutoBackupViewState extends ConsumerState { ), onChanged: (newValue) {}, ), - if (isDesktop) - const SizedBox( - height: 24, - ), + if (isDesktop) const SizedBox(height: 24), if (isDesktop) Text( "Create a passphrase", @@ -426,9 +420,7 @@ class _EditAutoBackupViewState extends ConsumerState { textAlign: TextAlign.left, ), if (!Platform.isAndroid && !Platform.isIOS) - const SizedBox( - height: 10, - ), + const SizedBox(height: 10), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -450,9 +442,7 @@ class _EditAutoBackupViewState extends ConsumerState { suffixIcon: UnconstrainedBox( child: Row( children: [ - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), GestureDetector( key: const Key( "createBackupPasswordFieldShowPasswordButtonKey", @@ -464,16 +454,15 @@ class _EditAutoBackupViewState extends ConsumerState { }, child: SvgPicture.asset( hidePassword ? Assets.svg.eye : Assets.svg.eyeSlash, - color: Theme.of(context) - .extension()! - .textDark3, + color: + Theme.of( + context, + ).extension()!.textDark3, width: 16, height: 16, ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), ], ), ), @@ -524,46 +513,46 @@ class _EditAutoBackupViewState extends ConsumerState { right: 12, top: passwordFeedback.isNotEmpty ? 4 : 0, ), - child: passwordFeedback.isNotEmpty - ? Text( - passwordFeedback, - style: STextStyles.infoSmall(context), - ) - : null, + child: + passwordFeedback.isNotEmpty + ? Text( + passwordFeedback, + style: STextStyles.infoSmall(context), + ) + : null, ), if (passwordFocusNode.hasFocus || passwordRepeatFocusNode.hasFocus || passwordController.text.isNotEmpty) Padding( - padding: const EdgeInsets.only( - left: 12, - right: 12, - top: 10, - ), + padding: const EdgeInsets.only(left: 12, right: 12, top: 10), child: ProgressBar( key: const Key("createStackBackUpProgressBar"), - width: isDesktop - ? 492 - : MediaQuery.of(context).size.width - 32 - 24, + width: + isDesktop + ? 492 + : MediaQuery.of(context).size.width - 32 - 24, height: 5, - fillColor: passwordStrength < 0.51 - ? Theme.of(context).extension()!.accentColorRed - : passwordStrength < 1 - ? Theme.of(context) - .extension()! - .accentColorYellow - : Theme.of(context) - .extension()! - .accentColorGreen, - backgroundColor: Theme.of(context) - .extension()! - .buttonBackSecondary, + fillColor: + passwordStrength < 0.51 + ? Theme.of( + context, + ).extension()!.accentColorRed + : passwordStrength < 1 + ? Theme.of( + context, + ).extension()!.accentColorYellow + : Theme.of( + context, + ).extension()!.accentColorGreen, + backgroundColor: + Theme.of( + context, + ).extension()!.buttonBackSecondary, percent: passwordStrength < 0.25 ? 0.03 : passwordStrength, ), ), - SizedBox( - height: isDesktop ? 16 : 10, - ), + SizedBox(height: isDesktop ? 16 : 10), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -585,9 +574,7 @@ class _EditAutoBackupViewState extends ConsumerState { suffixIcon: UnconstrainedBox( child: Row( children: [ - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), GestureDetector( key: const Key( "createBackupPasswordFieldShowPasswordButtonKey", @@ -599,16 +586,15 @@ class _EditAutoBackupViewState extends ConsumerState { }, child: SvgPicture.asset( hidePassword ? Assets.svg.eye : Assets.svg.eyeSlash, - color: Theme.of(context) - .extension()! - .textDark3, + color: + Theme.of( + context, + ).extension()!.textDark3, width: 16, height: 16, ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), ], ), ), @@ -619,52 +605,46 @@ class _EditAutoBackupViewState extends ConsumerState { }, ), ), - SizedBox( - height: isDesktop ? 24 : 32, - ), + SizedBox(height: isDesktop ? 24 : 32), Text( "Auto Backup frequency", - style: isDesktop - ? STextStyles.desktopTextExtraSmall(context).copyWith( - color: - Theme.of(context).extension()!.textDark3, - ) - : STextStyles.smallMed12(context), - ), - const SizedBox( - height: 10, + style: + isDesktop + ? STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of(context).extension()!.textDark3, + ) + : STextStyles.smallMed12(context), ), + const SizedBox(height: 10), if (isDesktop) DropdownButtonHideUnderline( child: DropdownButton2( isExpanded: true, value: _currentDropDownValue, items: [ - ..._dropDownItems.map( - (e) { - String message = ""; - switch (e) { - case BackupFrequencyType.everyTenMinutes: - message = "Every 10 minutes"; - break; - case BackupFrequencyType.everyAppStart: - message = "Every app startup"; - break; - case BackupFrequencyType.afterClosingAWallet: - message = "After closing a cryptocurrency wallet"; - break; - } - - return DropdownMenuItem( - value: e, - child: Text( - message, - style: - STextStyles.desktopTextExtraExtraSmall(context), - ), - ); - }, - ), + ..._dropDownItems.map((e) { + String message = ""; + switch (e) { + case BackupFrequencyType.everyTenMinutes: + message = "Every 10 minutes"; + break; + case BackupFrequencyType.everyAppStart: + message = "Every app startup"; + break; + case BackupFrequencyType.afterClosingAWallet: + message = "After closing a cryptocurrency wallet"; + break; + } + + return DropdownMenuItem( + value: e, + child: Text( + message, + style: STextStyles.desktopTextExtraExtraSmall(context), + ), + ); + }), ], onChanged: (value) { if (value is BackupFrequencyType) { @@ -694,19 +674,17 @@ class _EditAutoBackupViewState extends ConsumerState { offset: const Offset(0, -10), elevation: 0, decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), ), ), menuItemStyleData: const MenuItemStyleData( - padding: EdgeInsets.symmetric( - horizontal: 16, - vertical: 8, - ), + padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8), ), ), ), @@ -759,9 +737,10 @@ class _EditAutoBackupViewState extends ConsumerState { padding: const EdgeInsets.only(right: 4.0), child: SvgPicture.asset( Assets.svg.chevronDown, - color: Theme.of(context) - .extension()! - .textSubtitle2, + color: + Theme.of( + context, + ).extension()!.textSubtitle2, width: 12, height: 6, ), @@ -774,9 +753,7 @@ class _EditAutoBackupViewState extends ConsumerState { ], ), if (!isDesktop) const Spacer(), - SizedBox( - height: isDesktop ? 24 : 10, - ), + SizedBox(height: isDesktop ? 24 : 10), if (isDesktop) Row( children: [ @@ -787,9 +764,7 @@ class _EditAutoBackupViewState extends ConsumerState { onPressed: Navigator.of(context).pop, ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: PrimaryButton( label: "Save", @@ -802,18 +777,16 @@ class _EditAutoBackupViewState extends ConsumerState { ), if (!isDesktop) TextButton( - style: shouldEnableCreate - ? Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context) - : Theme.of(context) - .extension()! - .getPrimaryDisabledButtonStyle(context), + style: + shouldEnableCreate + ? Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context) + : Theme.of(context) + .extension()! + .getPrimaryDisabledButtonStyle(context), onPressed: !shouldEnableCreate ? null : onSavePressed, - child: Text( - "Save", - style: STextStyles.button(context), - ), + child: Text("Save", style: STextStyles.button(context)), ), ], ), diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/restore_from_encrypted_string_view.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/restore_from_encrypted_string_view.dart index 9eff26a7e..5aded8ec6 100644 --- a/lib/pages/settings_views/global_settings_view/stack_backup_views/restore_from_encrypted_string_view.dart +++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/restore_from_encrypted_string_view.dart @@ -30,10 +30,7 @@ import 'helpers/restore_create_backup.dart'; import 'sub_views/stack_restore_progress_view.dart'; class RestoreFromEncryptedStringView extends ConsumerStatefulWidget { - const RestoreFromEncryptedStringView({ - super.key, - required this.encrypted, - }); + const RestoreFromEncryptedStringView({super.key, required this.encrypted}); static const String routeName = "/restoreFromEncryptedString"; @@ -95,189 +92,197 @@ class _RestoreFromEncryptedStringViewState style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - key: const Key("restoreFromFilePasswordFieldKey"), - focusNode: passwordFocusNode, - controller: passwordController, - style: STextStyles.field(context), - obscureText: hidePassword, - enableSuggestions: false, - autocorrect: false, - decoration: standardInputDecoration( - "Enter password", - passwordFocusNode, - context, - ).copyWith( - suffixIcon: UnconstrainedBox( - child: Row( - children: [ - const SizedBox( - width: 16, - ), - GestureDetector( - key: const Key( - "restoreFromFilePasswordFieldShowPasswordButtonKey", - ), - onTap: () async { - setState(() { - hidePassword = !hidePassword; - }); - }, - child: SvgPicture.asset( - hidePassword - ? Assets.svg.eye - : Assets.svg.eyeSlash, - color: Theme.of(context) - .extension()! - .textDark3, - width: 16, - height: 16, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + key: const Key( + "restoreFromFilePasswordFieldKey", + ), + focusNode: passwordFocusNode, + controller: passwordController, + style: STextStyles.field(context), + obscureText: hidePassword, + enableSuggestions: false, + autocorrect: false, + decoration: standardInputDecoration( + "Enter password", + passwordFocusNode, + context, + ).copyWith( + suffixIcon: UnconstrainedBox( + child: Row( + children: [ + const SizedBox(width: 16), + GestureDetector( + key: const Key( + "restoreFromFilePasswordFieldShowPasswordButtonKey", + ), + onTap: () async { + setState(() { + hidePassword = !hidePassword; + }); + }, + child: SvgPicture.asset( + hidePassword + ? Assets.svg.eye + : Assets.svg.eyeSlash, + color: + Theme.of(context) + .extension()! + .textDark3, + width: 16, + height: 16, + ), ), - ), - const SizedBox( - width: 12, - ), - ], + const SizedBox(width: 12), + ], + ), ), ), + onChanged: (newValue) { + setState(() {}); + }, ), - onChanged: (newValue) { - setState(() {}); - }, ), - ), - const SizedBox( - height: 16, - ), - const Spacer(), - TextButton( - style: passwordController.text.isEmpty - ? Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context) - : Theme.of(context) - .extension()! - .getPrimaryDisabledButtonStyle(context), - onPressed: passwordController.text.isEmpty - ? null - : () async { - final String passphrase = - passwordController.text; + const SizedBox(height: 16), + const Spacer(), + TextButton( + style: + passwordController.text.isEmpty + ? Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context) + : Theme.of(context) + .extension()! + .getPrimaryDisabledButtonStyle( + context, + ), + onPressed: + passwordController.text.isEmpty + ? null + : () async { + final String passphrase = + passwordController.text; - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 75), - ); - } + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 75), + ); + } - bool shouldPop = false; - showDialog( - barrierDismissible: false, - context: context, - builder: (_) => WillPopScope( - onWillPop: () async { - return shouldPop; - }, - child: Column( - crossAxisAlignment: - CrossAxisAlignment.stretch, - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - Material( - color: Colors.transparent, - child: Center( - child: Text( - "Decrypting ${AppConfig.prefix} backup file", - style: - STextStyles.pageTitleH2( - context, - ).copyWith( - color: Theme.of(context) - .extension< - StackColors>()! - .textWhite, - ), + bool shouldPop = false; + showDialog( + barrierDismissible: false, + context: context, + builder: + (_) => WillPopScope( + onWillPop: () async { + return shouldPop; + }, + child: Column( + crossAxisAlignment: + CrossAxisAlignment + .stretch, + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Material( + color: Colors.transparent, + child: Center( + child: Text( + "Decrypting ${AppConfig.prefix} backup file", + style: STextStyles.pageTitleH2( + context, + ).copyWith( + color: + Theme.of( + context, + ) + .extension< + StackColors + >()! + .textWhite, + ), + ), + ), + ), + const SizedBox(height: 64), + const Center( + child: LoadingIndicator( + width: 100, + ), + ), + ], ), ), - ), - const SizedBox( - height: 64, - ), - const Center( - child: LoadingIndicator( - width: 100, - ), - ), - ], - ), - ), - ); + ); - final String? jsonString = await compute( - SWB.decryptStackWalletStringWithPassphrase, - Tuple2(widget.encrypted, passphrase), - debugLabel: - "stack wallet decryption compute", - ); + final String? + jsonString = await compute( + SWB.decryptStackWalletStringWithPassphrase, + Tuple2(widget.encrypted, passphrase), + debugLabel: + "stack wallet decryption compute", + ); - if (mounted) { - // pop LoadingIndicator - shouldPop = true; - Navigator.of(context).pop(); + if (mounted) { + // pop LoadingIndicator + shouldPop = true; + Navigator.of(context).pop(); - passwordController.text = ""; + passwordController.text = ""; - if (jsonString == null) { - showFloatingFlushBar( - type: FlushBarType.warning, - message: - "Failed to decrypt backup file", - context: context, - ); - return; - } + if (jsonString == null) { + showFloatingFlushBar( + type: FlushBarType.warning, + message: + "Failed to decrypt backup file", + context: context, + ); + return; + } - Navigator.of(context).push( - RouteGenerator.getRoute( - builder: (_) => - StackRestoreProgressView( - jsonString: jsonString, - fromFile: true, - ), - ), - ); - } - }, - child: Text( - "Restore", - style: STextStyles.button(context), + Navigator.of(context).push( + RouteGenerator.getRoute( + builder: + (_) => + StackRestoreProgressView( + jsonString: jsonString, + fromFile: true, + ), + ), + ); + } + }, + child: Text( + "Restore", + style: STextStyles.button(context), + ), ), - ), - ], + ], + ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/restore_from_file_view.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/restore_from_file_view.dart index 400e6e08d..d0ce73db1 100644 --- a/lib/pages/settings_views/global_settings_view/stack_backup_views/restore_from_file_view.dart +++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/restore_from_file_view.dart @@ -110,21 +110,21 @@ class _RestoreFromFileViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: child, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight(child: child), ), - ), - ); - }, + ); + }, + ), ), ), ), @@ -140,8 +140,9 @@ class _RestoreFromFileViewState extends ConsumerState { padding: const EdgeInsets.only(bottom: 10.0), child: Text( "Choose file location", - style: - STextStyles.desktopTextExtraExtraSmall(context).copyWith( + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( color: Theme.of(context).extension()!.textDark3, ), @@ -183,20 +184,17 @@ class _RestoreFromFileViewState extends ConsumerState { suffixIcon: UnconstrainedBox( child: Row( children: [ - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), SvgPicture.asset( Assets.svg.folder, - color: Theme.of(context) - .extension()! - .textDark3, + color: + Theme.of( + context, + ).extension()!.textDark3, width: 16, height: 16, ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), ], ), ), @@ -211,16 +209,15 @@ class _RestoreFromFileViewState extends ConsumerState { ), onChanged: (newValue) {}, ), - SizedBox( - height: !isDesktop ? 8 : 24, - ), + SizedBox(height: !isDesktop ? 8 : 24), if (isDesktop) Padding( padding: const EdgeInsets.only(bottom: 10.0), child: Text( "Enter passphrase", - style: - STextStyles.desktopTextExtraExtraSmall(context).copyWith( + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( color: Theme.of(context).extension()!.textDark3, ), @@ -249,9 +246,7 @@ class _RestoreFromFileViewState extends ConsumerState { suffixIcon: UnconstrainedBox( child: Row( children: [ - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), GestureDetector( key: const Key( "restoreFromFilePasswordFieldShowPasswordButtonKey", @@ -263,16 +258,15 @@ class _RestoreFromFileViewState extends ConsumerState { }, child: SvgPicture.asset( hidePassword ? Assets.svg.eye : Assets.svg.eyeSlash, - color: Theme.of(context) - .extension()! - .textDark3, + color: + Theme.of( + context, + ).extension()!.textDark3, width: 16, height: 16, ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), ], ), ), @@ -282,24 +276,24 @@ class _RestoreFromFileViewState extends ConsumerState { }, ), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), if (!isDesktop) const Spacer(), !isDesktop ? TextButton( - style: passwordController.text.isEmpty || - fileLocationController.text.isEmpty - ? Theme.of(context) - .extension()! - .getPrimaryDisabledButtonStyle(context) - : Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - onPressed: passwordController.text.isEmpty || - fileLocationController.text.isEmpty - ? null - : () async { + style: + passwordController.text.isEmpty || + fileLocationController.text.isEmpty + ? Theme.of(context) + .extension()! + .getPrimaryDisabledButtonStyle(context) + : Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + onPressed: + passwordController.text.isEmpty || + fileLocationController.text.isEmpty + ? null + : () async { final String fileToRestore = fileLocationController.text; final String passphrase = passwordController.text; @@ -325,41 +319,42 @@ class _RestoreFromFileViewState extends ConsumerState { showDialog( barrierDismissible: false, context: context, - builder: (_) => WillPopScope( - onWillPop: () async { - return shouldPop; - }, - child: Column( - crossAxisAlignment: - CrossAxisAlignment.stretch, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Material( - color: Colors.transparent, - child: Center( - child: Text( - "Decrypting ${AppConfig.prefix} backup file", - style: STextStyles.pageTitleH2( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textWhite, + builder: + (_) => WillPopScope( + onWillPop: () async { + return shouldPop; + }, + child: Column( + crossAxisAlignment: + CrossAxisAlignment.stretch, + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Material( + color: Colors.transparent, + child: Center( + child: Text( + "Decrypting ${AppConfig.prefix} backup file", + style: STextStyles.pageTitleH2( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textWhite, + ), + ), ), ), - ), - ), - const SizedBox( - height: 64, - ), - const Center( - child: LoadingIndicator( - width: 100, - ), + const SizedBox(height: 64), + const Center( + child: LoadingIndicator(width: 100), + ), + ], ), - ], - ), - ), + ), ), ); @@ -387,31 +382,31 @@ class _RestoreFromFileViewState extends ConsumerState { await Navigator.of(context).push( RouteGenerator.getRoute( - builder: (_) => StackRestoreProgressView( - jsonString: jsonString, - shouldPushToHome: true, - ), + builder: + (_) => StackRestoreProgressView( + jsonString: jsonString, + shouldPushToHome: true, + ), ), ); } }, - child: Text( - "Restore", - style: STextStyles.button(context), - ), - ) + child: Text("Restore", style: STextStyles.button(context)), + ) : Row( - children: [ - PrimaryButton( - width: 183, - buttonHeight: ButtonHeight.m, - label: "Restore", - enabled: !(passwordController.text.isEmpty || - fileLocationController.text.isEmpty), - onPressed: passwordController.text.isEmpty || - fileLocationController.text.isEmpty - ? null - : () async { + children: [ + PrimaryButton( + width: 183, + buttonHeight: ButtonHeight.m, + label: "Restore", + enabled: + !(passwordController.text.isEmpty || + fileLocationController.text.isEmpty), + onPressed: + passwordController.text.isEmpty || + fileLocationController.text.isEmpty + ? null + : () async { final String fileToRestore = fileLocationController.text; final String passphrase = @@ -438,42 +433,45 @@ class _RestoreFromFileViewState extends ConsumerState { showDialog( barrierDismissible: false, context: context, - builder: (_) => WillPopScope( - onWillPop: () async { - return shouldPop; - }, - child: Column( - crossAxisAlignment: - CrossAxisAlignment.stretch, - mainAxisAlignment: - MainAxisAlignment.center, - children: [ - Material( - color: Colors.transparent, - child: Center( - child: Text( - "Decrypting ${AppConfig.prefix} backup file", - style: STextStyles.pageTitleH2( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textWhite, + builder: + (_) => WillPopScope( + onWillPop: () async { + return shouldPop; + }, + child: Column( + crossAxisAlignment: + CrossAxisAlignment.stretch, + mainAxisAlignment: + MainAxisAlignment.center, + children: [ + Material( + color: Colors.transparent, + child: Center( + child: Text( + "Decrypting ${AppConfig.prefix} backup file", + style: + STextStyles.pageTitleH2( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textWhite, + ), + ), ), ), - ), - ), - const SizedBox( - height: 64, - ), - const Center( - child: LoadingIndicator( - width: 100, - ), + const SizedBox(height: 64), + const Center( + child: LoadingIndicator( + width: 100, + ), + ), + ], ), - ], - ), - ), + ), ), ); @@ -530,16 +528,15 @@ class _RestoreFromFileViewState extends ConsumerState { children: [ Padding( padding: - const EdgeInsets - .all( - 32, - ), + const EdgeInsets.all( + 32, + ), child: Text( "Restore ${AppConfig.appName}", - style: STextStyles - .desktopH3( - context, - ), + style: + STextStyles.desktopH3( + context, + ), textAlign: TextAlign .center, @@ -550,15 +547,14 @@ class _RestoreFromFileViewState extends ConsumerState { ), Padding( padding: - const EdgeInsets - .symmetric( - horizontal: 32, - ), + const EdgeInsets.symmetric( + horizontal: 32, + ), child: StackRestoreProgressView( - jsonString: - jsonString, - ), + jsonString: + jsonString, + ), ), const SizedBox( height: 32, @@ -575,18 +571,16 @@ class _RestoreFromFileViewState extends ConsumerState { ); } }, - ), - const SizedBox( - width: 16, - ), - SecondaryButton( - width: 183, - buttonHeight: ButtonHeight.m, - label: "Cancel", - onPressed: () {}, - ), - ], - ), + ), + const SizedBox(width: 16), + SecondaryButton( + width: 183, + buttonHeight: ButtonHeight.m, + label: "Cancel", + onPressed: () {}, + ), + ], + ), ], ), ), diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/stack_backup_view.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/stack_backup_view.dart index da5c0f411..1bb9d1995 100644 --- a/lib/pages/settings_views/global_settings_view/stack_backup_views/stack_backup_view.dart +++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/stack_backup_view.dart @@ -24,9 +24,7 @@ import 'create_backup_view.dart'; import 'restore_from_file_view.dart'; class StackBackupView extends StatelessWidget { - const StackBackupView({ - super.key, - }); + const StackBackupView({super.key}); static const String routeName = "/stackBackup"; @@ -48,134 +46,129 @@ class StackBackupView extends StatelessWidget { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - ), - onPressed: () { - Navigator.of(context).pushNamed(AutoBackupView.routeName); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 20, - ), - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.backupAuto, - height: 28, - width: 28, - ), - const SizedBox( - width: 12, - ), - Text( - "Auto Backup", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - ], + onPressed: () { + Navigator.of(context).pushNamed(AutoBackupView.routeName); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 20, + ), + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.backupAuto, + height: 28, + width: 28, + ), + const SizedBox(width: 12), + Text( + "Auto Backup", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + ], + ), ), ), ), - ), - const SizedBox( - height: 8, - ), - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: () { - Navigator.of(context).pushNamed(CreateBackupView.routeName); - // .pushNamed(CreateBackupInfoView.routeName); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 20, + const SizedBox(height: 8), + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.backupAdd, - height: 28, - width: 28, - ), - const SizedBox( - width: 12, - ), - Text( - "Create manual backup", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - ], + onPressed: () { + Navigator.of( + context, + ).pushNamed(CreateBackupView.routeName); + // .pushNamed(CreateBackupInfoView.routeName); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 20, + ), + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.backupAdd, + height: 28, + width: 28, + ), + const SizedBox(width: 12), + Text( + "Create manual backup", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + ], + ), ), ), ), - ), - const SizedBox( - height: 8, - ), - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: () { - Navigator.of(context) - .pushNamed(RestoreFromFileView.routeName); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 20, + const SizedBox(height: 8), + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.backupRestore, - height: 28, - width: 28, - ), - const SizedBox( - width: 12, - ), - Text( - "Restore backup", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - ], + onPressed: () { + Navigator.of( + context, + ).pushNamed(RestoreFromFileView.routeName); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 20, + ), + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.backupRestore, + height: 28, + width: 28, + ), + const SizedBox(width: 12), + Text( + "Restore backup", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + ], + ), ), ), ), - ), - ], + ], + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/sub_views/recovery_phrase_view.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/sub_views/recovery_phrase_view.dart index dd1478b4a..dfd819506 100644 --- a/lib/pages/settings_views/global_settings_view/stack_backup_views/sub_views/recovery_phrase_view.dart +++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/sub_views/recovery_phrase_view.dart @@ -8,16 +8,19 @@ * */ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_svg/svg.dart'; + import '../../../../../notifications/show_flush_bar.dart'; -import '../../../../add_wallet_views/new_wallet_recovery_phrase_view/sub_widgets/mnemonic_table.dart'; import '../../../../../themes/stack_colors.dart'; import '../../../../../utilities/assets.dart'; import '../../../../../utilities/clipboard_interface.dart'; import '../../../../../utilities/text_styles.dart'; import '../../../../../widgets/custom_buttons/app_bar_icon_button.dart'; +import '../../../../add_wallet_views/new_wallet_recovery_phrase_view/sub_widgets/mnemonic_table.dart'; class RecoverPhraseView extends StatelessWidget { const RecoverPhraseView({ @@ -52,19 +55,18 @@ class RecoverPhraseView extends StatelessWidget { child: AppBarIconButton( color: Theme.of(context).extension()!.background, shadows: const [], - icon: SvgPicture.asset( - Assets.svg.copy, - width: 20, - height: 20, - ), + icon: SvgPicture.asset(Assets.svg.copy, width: 20, height: 20), onPressed: () async { - await clipboardInterface - .setData(ClipboardData(text: mnemonic.join(" "))); - showFloatingFlushBar( - type: FlushBarType.info, - message: "Copied to clipboard", - iconAsset: Assets.svg.copy, - context: context, + await clipboardInterface.setData( + ClipboardData(text: mnemonic.join(" ")), + ); + unawaited( + showFloatingFlushBar( + type: FlushBarType.info, + message: "Copied to clipboard", + iconAsset: Assets.svg.copy, + context: context, + ), ); }, ), @@ -72,41 +74,32 @@ class RecoverPhraseView extends StatelessWidget { ), ], ), - body: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const SizedBox( - height: 4, - ), - Text( - walletName, - textAlign: TextAlign.center, - style: STextStyles.label(context).copyWith( - fontSize: 12, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const SizedBox(height: 4), + Text( + walletName, + textAlign: TextAlign.center, + style: STextStyles.label(context).copyWith(fontSize: 12), ), - ), - const SizedBox( - height: 4, - ), - Text( - "Recovery Phrase", - textAlign: TextAlign.center, - style: STextStyles.pageTitleH1(context), - ), - const SizedBox( - height: 12, - ), - Expanded( - child: SingleChildScrollView( - child: MnemonicTable( - words: mnemonic, - isDesktop: false, + const SizedBox(height: 4), + Text( + "Recovery Phrase", + textAlign: TextAlign.center, + style: STextStyles.pageTitleH1(context), + ), + const SizedBox(height: 12), + Expanded( + child: SingleChildScrollView( + child: MnemonicTable(words: mnemonic, isDesktop: false), ), ), - ), - ], + ], + ), ), ), ); diff --git a/lib/pages/settings_views/global_settings_view/stack_backup_views/sub_views/stack_restore_progress_view.dart b/lib/pages/settings_views/global_settings_view/stack_backup_views/sub_views/stack_restore_progress_view.dart index 2c7ddd71e..7b71dc8c6 100644 --- a/lib/pages/settings_views/global_settings_view/stack_backup_views/sub_views/stack_restore_progress_view.dart +++ b/lib/pages/settings_views/global_settings_view/stack_backup_views/sub_views/stack_restore_progress_view.dart @@ -69,37 +69,34 @@ class _StackRestoreProgressViewState showDialog( barrierDismissible: false, context: context, - builder: (_) => WillPopScope( - onWillPop: () async { - return shouldPop; - }, - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Material( - color: Colors.transparent, - child: Center( - child: Text( - "Cancelling restore. Please wait.", - style: STextStyles.pageTitleH2(context).copyWith( - color: - Theme.of(context).extension()!.textWhite, + builder: + (_) => WillPopScope( + onWillPop: () async { + return shouldPop; + }, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Material( + color: Colors.transparent, + child: Center( + child: Text( + "Cancelling restore. Please wait.", + style: STextStyles.pageTitleH2(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textWhite, + ), + ), ), ), - ), - ), - const SizedBox( - height: 64, + const SizedBox(height: 64), + const Center(child: LoadingIndicator(width: 100)), + ], ), - const Center( - child: LoadingIndicator( - width: 100, - ), - ), - ], - ), - ), + ), ), ); @@ -111,12 +108,12 @@ class _StackRestoreProgressViewState if (mounted) { !isDesktop ? Navigator.of(context).popUntil( - ModalRoute.withName( - widget.fromFile - ? RestoreFromEncryptedStringView.routeName - : StackBackupView.routeName, - ), - ) + ModalRoute.withName( + widget.fromFile + ? RestoreFromEncryptedStringView.routeName + : StackBackupView.routeName, + ), + ) : Navigator.of(context).popUntil((_) => count++ >= 2); } } @@ -169,7 +166,7 @@ class _StackRestoreProgressViewState ref.read(secureStoreProvider), ); } catch (e, s) { - Logging.instance.w("$e\n$s", error: e, stackTrace: s,); + Logging.instance.w("$e\n$s", error: e, stackTrace: s); } if (finished != null && finished && uiState.done) { @@ -224,7 +221,9 @@ class _StackRestoreProgressViewState } void _addWalletsToHomeView() { - ref.read(pWallets).loadAfterStackRestore( + ref + .read(pWallets) + .loadAfterStackRestore( ref.read(prefsChangeNotifierProvider), ref.read(stackRestoringUIStateProvider).wallets, Util.isDesktop, @@ -277,59 +276,95 @@ class _StackRestoreProgressViewState style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only(left: 12, top: 12, right: 12), + child: child, ), - child: child, ), ), ); }, child: SingleChildScrollView( child: Padding( - padding: const EdgeInsets.only( - left: 4, - top: 4, - right: 4, - bottom: 4, - ), + padding: const EdgeInsets.only(left: 4, top: 4, right: 4, bottom: 4), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - "Settings", - style: STextStyles.itemSubtitle(context), - ), - const SizedBox( - height: 12, - ), + Text("Settings", style: STextStyles.itemSubtitle(context)), + const SizedBox(height: 12), Consumer( builder: (_, ref, __) { final state = ref.watch( - stackRestoringUIStateProvider - .select((value) => value.preferences), + stackRestoringUIStateProvider.select( + (value) => value.preferences, + ), ); return !isDesktop ? RestoringItemCard( + left: SizedBox( + width: 32, + height: 32, + child: RoundedContainer( + padding: const EdgeInsets.all(0), + color: + Theme.of( + context, + ).extension()!.buttonBackSecondary, + child: Center( + child: SvgPicture.asset( + Assets.svg.gear, + width: 16, + height: 16, + color: + Theme.of( + context, + ).extension()!.accentColorDark, + ), + ), + ), + ), + right: SizedBox( + width: 20, + height: 20, + child: _getIconForState(state), + ), + title: "Preferences", + subTitle: + state == StackRestoringStatus.failed + ? Text( + "Something went wrong", + style: STextStyles.errorSmall(context), + ) + : null, + ) + : RoundedContainer( + padding: EdgeInsets.zero, + color: + Theme.of(context).extension()!.popupBG, + borderColor: + Theme.of( + context, + ).extension()!.background, + child: RestoringItemCard( left: SizedBox( width: 32, height: 32, child: RoundedContainer( padding: const EdgeInsets.all(0), - color: Theme.of(context) - .extension()! - .buttonBackSecondary, + color: + Theme.of(context) + .extension()! + .buttonBackSecondary, child: Center( child: SvgPicture.asset( Assets.svg.gear, width: 16, height: 16, - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of(context) + .extension()! + .accentColorDark, ), ), ), @@ -340,84 +375,88 @@ class _StackRestoreProgressViewState child: _getIconForState(state), ), title: "Preferences", - subTitle: state == StackRestoringStatus.failed - ? Text( - "Something went wrong", - style: STextStyles.errorSmall(context), - ) - : null, - ) - : RoundedContainer( - padding: EdgeInsets.zero, - color: Theme.of(context) - .extension()! - .popupBG, - borderColor: Theme.of(context) - .extension()! - .background, - child: RestoringItemCard( - left: SizedBox( - width: 32, - height: 32, - child: RoundedContainer( - padding: const EdgeInsets.all(0), - color: Theme.of(context) - .extension()! - .buttonBackSecondary, - child: Center( - child: SvgPicture.asset( - Assets.svg.gear, - width: 16, - height: 16, - color: Theme.of(context) - .extension()! - .accentColorDark, - ), - ), - ), - ), - right: SizedBox( - width: 20, - height: 20, - child: _getIconForState(state), - ), - title: "Preferences", - subTitle: state == StackRestoringStatus.failed - ? Text( + subTitle: + state == StackRestoringStatus.failed + ? Text( "Something went wrong", style: STextStyles.errorSmall(context), ) - : null, - ), - ); + : null, + ), + ); }, ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Consumer( builder: (_, ref, __) { final state = ref.watch( - stackRestoringUIStateProvider - .select((value) => value.addressBook), + stackRestoringUIStateProvider.select( + (value) => value.addressBook, + ), ); return !isDesktop ? RestoringItemCard( + left: SizedBox( + width: 32, + height: 32, + child: RoundedContainer( + padding: const EdgeInsets.all(0), + color: + Theme.of( + context, + ).extension()!.buttonBackSecondary, + child: Center( + child: AddressBookIcon( + width: 16, + height: 16, + color: + Theme.of( + context, + ).extension()!.accentColorDark, + ), + ), + ), + ), + right: SizedBox( + width: 20, + height: 20, + child: _getIconForState(state), + ), + title: "Address book", + subTitle: + state == StackRestoringStatus.failed + ? Text( + "Something went wrong", + style: STextStyles.errorSmall(context), + ) + : null, + ) + : RoundedContainer( + padding: EdgeInsets.zero, + color: + Theme.of(context).extension()!.popupBG, + borderColor: + Theme.of( + context, + ).extension()!.background, + child: RestoringItemCard( left: SizedBox( width: 32, height: 32, child: RoundedContainer( padding: const EdgeInsets.all(0), - color: Theme.of(context) - .extension()! - .buttonBackSecondary, + color: + Theme.of(context) + .extension()! + .buttonBackSecondary, child: Center( child: AddressBookIcon( width: 16, height: 16, - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of(context) + .extension()! + .accentColorDark, ), ), ), @@ -428,84 +467,90 @@ class _StackRestoreProgressViewState child: _getIconForState(state), ), title: "Address book", - subTitle: state == StackRestoringStatus.failed - ? Text( - "Something went wrong", - style: STextStyles.errorSmall(context), - ) - : null, - ) - : RoundedContainer( - padding: EdgeInsets.zero, - color: Theme.of(context) - .extension()! - .popupBG, - borderColor: Theme.of(context) - .extension()! - .background, - child: RestoringItemCard( - left: SizedBox( - width: 32, - height: 32, - child: RoundedContainer( - padding: const EdgeInsets.all(0), - color: Theme.of(context) - .extension()! - .buttonBackSecondary, - child: Center( - child: AddressBookIcon( - width: 16, - height: 16, - color: Theme.of(context) - .extension()! - .accentColorDark, - ), - ), - ), - ), - right: SizedBox( - width: 20, - height: 20, - child: _getIconForState(state), - ), - title: "Address book", - subTitle: state == StackRestoringStatus.failed - ? Text( + subTitle: + state == StackRestoringStatus.failed + ? Text( "Something went wrong", style: STextStyles.errorSmall(context), ) - : null, - ), - ); + : null, + ), + ); }, ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Consumer( builder: (_, ref, __) { final state = ref.watch( - stackRestoringUIStateProvider - .select((value) => value.nodes), + stackRestoringUIStateProvider.select( + (value) => value.nodes, + ), ); return !isDesktop ? RestoringItemCard( + left: SizedBox( + width: 32, + height: 32, + child: RoundedContainer( + padding: const EdgeInsets.all(0), + color: + Theme.of( + context, + ).extension()!.buttonBackSecondary, + child: Center( + child: SvgPicture.asset( + Assets.svg.node, + width: 16, + height: 16, + color: + Theme.of( + context, + ).extension()!.accentColorDark, + ), + ), + ), + ), + right: SizedBox( + width: 20, + height: 20, + child: _getIconForState(state), + ), + title: "Nodes", + subTitle: + state == StackRestoringStatus.failed + ? Text( + "Something went wrong", + style: STextStyles.errorSmall(context), + ) + : null, + ) + : RoundedContainer( + padding: EdgeInsets.zero, + color: + Theme.of(context).extension()!.popupBG, + borderColor: + Theme.of( + context, + ).extension()!.background, + child: RestoringItemCard( left: SizedBox( width: 32, height: 32, child: RoundedContainer( padding: const EdgeInsets.all(0), - color: Theme.of(context) - .extension()! - .buttonBackSecondary, + color: + Theme.of(context) + .extension()! + .buttonBackSecondary, child: Center( child: SvgPicture.asset( Assets.svg.node, width: 16, height: 16, - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of(context) + .extension()! + .accentColorDark, ), ), ), @@ -516,85 +561,90 @@ class _StackRestoreProgressViewState child: _getIconForState(state), ), title: "Nodes", - subTitle: state == StackRestoringStatus.failed - ? Text( - "Something went wrong", - style: STextStyles.errorSmall(context), - ) - : null, - ) - : RoundedContainer( - padding: EdgeInsets.zero, - color: Theme.of(context) - .extension()! - .popupBG, - borderColor: Theme.of(context) - .extension()! - .background, - child: RestoringItemCard( - left: SizedBox( - width: 32, - height: 32, - child: RoundedContainer( - padding: const EdgeInsets.all(0), - color: Theme.of(context) - .extension()! - .buttonBackSecondary, - child: Center( - child: SvgPicture.asset( - Assets.svg.node, - width: 16, - height: 16, - color: Theme.of(context) - .extension()! - .accentColorDark, - ), - ), - ), - ), - right: SizedBox( - width: 20, - height: 20, - child: _getIconForState(state), - ), - title: "Nodes", - subTitle: state == StackRestoringStatus.failed - ? Text( + subTitle: + state == StackRestoringStatus.failed + ? Text( "Something went wrong", style: STextStyles.errorSmall(context), ) - : null, - ), - ); + : null, + ), + ); }, ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Consumer( builder: (_, ref, __) { final state = ref.watch( - stackRestoringUIStateProvider - .select((value) => value.trades), + stackRestoringUIStateProvider.select( + (value) => value.trades, + ), ); return !isDesktop ? RestoringItemCard( + left: SizedBox( + width: 32, + height: 32, + child: RoundedContainer( + padding: const EdgeInsets.all(0), + color: + Theme.of( + context, + ).extension()!.buttonBackSecondary, + child: Center( + child: SvgPicture.asset( + Assets.svg.arrowsTwoWay, + width: 16, + height: 16, + color: + Theme.of( + context, + ).extension()!.accentColorDark, + ), + ), + ), + ), + right: SizedBox( + width: 20, + height: 20, + child: _getIconForState(state), + ), + title: "Exchange history", + subTitle: + state == StackRestoringStatus.failed + ? Text( + "Something went wrong", + style: STextStyles.errorSmall(context), + ) + : null, + ) + : RoundedContainer( + padding: EdgeInsets.zero, + color: + Theme.of(context).extension()!.popupBG, + borderColor: + Theme.of( + context, + ).extension()!.background, + child: RestoringItemCard( left: SizedBox( width: 32, height: 32, child: RoundedContainer( padding: const EdgeInsets.all(0), - color: Theme.of(context) - .extension()! - .buttonBackSecondary, + color: + Theme.of(context) + .extension()! + .buttonBackSecondary, child: Center( child: SvgPicture.asset( Assets.svg.arrowsTwoWay, width: 16, height: 16, - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of(context) + .extension()! + .accentColorDark, ), ), ), @@ -605,123 +655,72 @@ class _StackRestoreProgressViewState child: _getIconForState(state), ), title: "Exchange history", - subTitle: state == StackRestoringStatus.failed - ? Text( - "Something went wrong", - style: STextStyles.errorSmall(context), - ) - : null, - ) - : RoundedContainer( - padding: EdgeInsets.zero, - color: Theme.of(context) - .extension()! - .popupBG, - borderColor: Theme.of(context) - .extension()! - .background, - child: RestoringItemCard( - left: SizedBox( - width: 32, - height: 32, - child: RoundedContainer( - padding: const EdgeInsets.all(0), - color: Theme.of(context) - .extension()! - .buttonBackSecondary, - child: Center( - child: SvgPicture.asset( - Assets.svg.arrowsTwoWay, - width: 16, - height: 16, - color: Theme.of(context) - .extension()! - .accentColorDark, - ), - ), - ), - ), - right: SizedBox( - width: 20, - height: 20, - child: _getIconForState(state), - ), - title: "Exchange history", - subTitle: state == StackRestoringStatus.failed - ? Text( + subTitle: + state == StackRestoringStatus.failed + ? Text( "Something went wrong", style: STextStyles.errorSmall(context), ) - : null, - ), - ); + : null, + ), + ); }, ), - const SizedBox( - height: 16, - ), - Text( - "Wallets", - style: STextStyles.itemSubtitle(context), - ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 16), + Text("Wallets", style: STextStyles.itemSubtitle(context)), + const SizedBox(height: 8), ...ref .watch( - stackRestoringUIStateProvider - .select((value) => value.walletStateProviders), + stackRestoringUIStateProvider.select( + (value) => value.walletStateProviders, + ), ) .values .map( (provider) => Padding( padding: const EdgeInsets.symmetric(vertical: 4), - child: RestoringWalletCard( - provider: provider, - ), + child: RestoringWalletCard(provider: provider), ), ), - const SizedBox( - height: 30, - ), + const SizedBox(height: 30), SizedBox( width: MediaQuery.of(context).size.width - 32, - child: !isDesktop - ? TextButton( - onPressed: () async { - if (_success) { - if (widget.shouldPushToHome) { - Navigator.of(context).popUntil( - ModalRoute.withName( - HomeView.routeName, - ), - ); + child: + !isDesktop + ? TextButton( + onPressed: () async { + if (_success) { + if (widget.shouldPushToHome) { + Navigator.of(context).popUntil( + ModalRoute.withName(HomeView.routeName), + ); + } else { + Navigator.of(context).pop(); + } } else { - Navigator.of(context).pop(); - } - } else { - if (await _requestCancel()) { - await _cancel(); + if (await _requestCancel()) { + await _cancel(); + } } - } - }, - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - child: Text( - _success ? "OK" : "Cancel restore process", - style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .buttonTextPrimary, + }, + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + child: Text( + _success ? "OK" : "Cancel restore process", + style: STextStyles.button(context).copyWith( + color: + Theme.of( + context, + ).extension()!.buttonTextPrimary, + ), ), - ), - ) - : Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - _success - ? PrimaryButton( + ) + : Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + _success + ? PrimaryButton( width: 248, buttonHeight: ButtonHeight.l, enabled: true, @@ -738,15 +737,18 @@ class _StackRestoreProgressViewState if (widget.shouldPushToHome) { unawaited( - Navigator.of(context) - .pushNamedAndRemoveUntil( + Navigator.of( + context, + ).pushNamedAndRemoveUntil( DesktopHomeView.routeName, (route) => false, ), ); } else { - Navigator.of(context, rootNavigator: true) - .popUntil( + Navigator.of( + context, + rootNavigator: true, + ).popUntil( ModalRoute.withName( DesktopHomeView.routeName, ), @@ -754,7 +756,7 @@ class _StackRestoreProgressViewState } }, ) - : SecondaryButton( + : SecondaryButton( width: 248, buttonHeight: ButtonHeight.l, enabled: true, @@ -765,8 +767,8 @@ class _StackRestoreProgressViewState } }, ), - ], - ), + ], + ), ), ], ), diff --git a/lib/pages/settings_views/global_settings_view/startup_preferences/startup_preferences_view.dart b/lib/pages/settings_views/global_settings_view/startup_preferences/startup_preferences_view.dart index 3970ff9c8..2e902ede6 100644 --- a/lib/pages/settings_views/global_settings_view/startup_preferences/startup_preferences_view.dart +++ b/lib/pages/settings_views/global_settings_view/startup_preferences/startup_preferences_view.dart @@ -79,188 +79,193 @@ class _StartupPreferencesViewState style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Padding( - padding: const EdgeInsets.all(4.0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: - MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Padding( + padding: const EdgeInsets.all(4.0), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - ), - onPressed: () { - ref - .read(prefsChangeNotifierProvider) - .gotoWalletOnStartup = false; - }, - child: Container( - color: Colors.transparent, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Row( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - SizedBox( - width: 20, - height: 20, - child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, - value: false, - groupValue: ref.watch( - prefsChangeNotifierProvider - .select( - (value) => - value.gotoWalletOnStartup, + onPressed: () { + ref + .read(prefsChangeNotifierProvider) + .gotoWalletOnStartup = false; + }, + child: Container( + color: Colors.transparent, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + SizedBox( + width: 20, + height: 20, + child: Radio( + activeColor: + Theme.of(context) + .extension< + StackColors + >()! + .radioButtonIconEnabled, + value: false, + groupValue: ref.watch( + prefsChangeNotifierProvider + .select( + (value) => + value + .gotoWalletOnStartup, + ), ), + onChanged: (value) { + if (value is bool) { + ref + .read( + prefsChangeNotifierProvider, + ) + .gotoWalletOnStartup = value; + } + }, ), - onChanged: (value) { - if (value is bool) { - ref - .read( - prefsChangeNotifierProvider, - ) - .gotoWalletOnStartup = - value; - } - }, ), - ), - const SizedBox( - width: 12, - ), - Flexible( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Home screen", - style: - STextStyles.titleBold12( - context, + const SizedBox(width: 12), + Flexible( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Home screen", + style: + STextStyles.titleBold12( + context, + ), + textAlign: TextAlign.left, ), - textAlign: TextAlign.left, - ), - Text( - "${AppConfig.appName} home screen", - style: - STextStyles.itemSubtitle( - context, + Text( + "${AppConfig.appName} home screen", + style: + STextStyles.itemSubtitle( + context, + ), + textAlign: TextAlign.left, ), - textAlign: TextAlign.left, - ), - ], + ], + ), ), - ), - ], + ], + ), ), ), ), ), - ), - Padding( - padding: const EdgeInsets.all(4), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: - MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + Padding( + padding: const EdgeInsets.all(4), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - ), - onPressed: () { - ref - .read(prefsChangeNotifierProvider) - .gotoWalletOnStartup = true; - }, - child: Container( - color: Colors.transparent, - child: Padding( - padding: const EdgeInsets.all(8), - child: Row( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - SizedBox( - width: 20, - height: 20, - child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, - value: true, - groupValue: ref.watch( - prefsChangeNotifierProvider - .select( - (value) => - value.gotoWalletOnStartup, + onPressed: () { + ref + .read(prefsChangeNotifierProvider) + .gotoWalletOnStartup = true; + }, + child: Container( + color: Colors.transparent, + child: Padding( + padding: const EdgeInsets.all(8), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + SizedBox( + width: 20, + height: 20, + child: Radio( + activeColor: + Theme.of(context) + .extension< + StackColors + >()! + .radioButtonIconEnabled, + value: true, + groupValue: ref.watch( + prefsChangeNotifierProvider + .select( + (value) => + value + .gotoWalletOnStartup, + ), ), + onChanged: (value) { + if (value is bool) { + ref + .read( + prefsChangeNotifierProvider, + ) + .gotoWalletOnStartup = value; + } + }, ), - onChanged: (value) { - if (value is bool) { - ref - .read( - prefsChangeNotifierProvider, - ) - .gotoWalletOnStartup = - value; - } - }, ), - ), - const SizedBox( - width: 12, - ), - Flexible( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Specific wallet", - style: - STextStyles.titleBold12( - context, + const SizedBox(width: 12), + Flexible( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Specific wallet", + style: + STextStyles.titleBold12( + context, + ), + textAlign: TextAlign.left, ), - textAlign: TextAlign.left, - ), - (safe && - ref.watch( - prefsChangeNotifierProvider - .select( - (value) => value - .startupWalletId, - ), - ) != - null) - ? Padding( + (safe && + ref.watch( + prefsChangeNotifierProvider + .select( + (value) => + value + .startupWalletId, + ), + ) != + null) + ? Padding( padding: - const EdgeInsets - .only(top: 12), + const EdgeInsets.only( + top: 12, + ), child: Row( children: [ SvgPicture.file( @@ -270,9 +275,10 @@ class _StartupPreferencesViewState ref.watch( pWalletCoin( ref.watch( - prefsChangeNotifierProvider - .select( - (value) => + prefsChangeNotifierProvider.select( + ( + value, + ) => value.startupWalletId!, ), ), @@ -291,115 +297,116 @@ class _StartupPreferencesViewState ref.watch( prefsChangeNotifierProvider .select( - (value) => - value - .startupWalletId!, - ), + ( + value, + ) => + value.startupWalletId!, + ), ), ), ), - style: STextStyles - .itemSubtitle( - context, - ), + style: + STextStyles.itemSubtitle( + context, + ), ), ], ), ) - : Text( + : Text( "Select a specific wallet to load into on startup", - style: STextStyles - .itemSubtitle( - context, - ), + style: + STextStyles.itemSubtitle( + context, + ), textAlign: TextAlign.left, ), - ], + ], + ), ), - ), - ], + ], + ), ), ), ), ), - ), - if (!ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.gotoWalletOnStartup, - ), - )) - const SizedBox( - height: 12, - ), - if (ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.gotoWalletOnStartup, - ), - )) - Container( - color: Colors.transparent, - child: Padding( - padding: const EdgeInsets.only( - left: 12.0, - right: 12, - bottom: 12, - ), - child: Row( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - const SizedBox( - width: 12 + 20, - height: 12, - ), - Flexible( - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: - MaterialTapTargetSize - .shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular( - Constants - .size.circularBorderRadius, + if (!ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.gotoWalletOnStartup, + ), + )) + const SizedBox(height: 12), + if (ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.gotoWalletOnStartup, + ), + )) + Container( + color: Colors.transparent, + child: Padding( + padding: const EdgeInsets.only( + left: 12.0, + right: 12, + bottom: 12, + ), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + const SizedBox( + width: 12 + 20, + height: 12, + ), + Flexible( + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: + MaterialTapTargetSize + .shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular( + Constants + .size + .circularBorderRadius, + ), ), - ), - onPressed: () { - Navigator.of(context).pushNamed( - StartupWalletSelectionView - .routeName, - ); - }, - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Select wallet...", - style: STextStyles.link2( - context, + onPressed: () { + Navigator.of(context).pushNamed( + StartupWalletSelectionView + .routeName, + ); + }, + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Select wallet...", + style: STextStyles.link2( + context, + ), + textAlign: TextAlign.left, ), - textAlign: TextAlign.left, - ), - ], + ], + ), ), ), - ), - ], + ], + ), ), ), - ), - ], + ], + ), ), - ), - ], + ], + ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/startup_preferences/startup_wallet_selection_view.dart b/lib/pages/settings_views/global_settings_view/startup_preferences/startup_wallet_selection_view.dart index 7c073c5ce..0caa4720d 100644 --- a/lib/pages/settings_views/global_settings_view/startup_preferences/startup_wallet_selection_view.dart +++ b/lib/pages/settings_views/global_settings_view/startup_preferences/startup_wallet_selection_view.dart @@ -13,6 +13,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; + import '../../../../providers/providers.dart'; import '../../../../themes/coin_icon_provider.dart'; import '../../../../themes/stack_colors.dart'; @@ -64,180 +65,179 @@ class _StartupWalletSelectionViewState ), ), ), - body: LayoutBuilder( - builder: (context, constraints) { - return Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, - ), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SizedBox( - height: 4, - ), - Text( - "Select a wallet to load into immediately on startup", - style: STextStyles.smallMed12(context), - ), - const SizedBox( - height: 12, - ), - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: Column( - children: [ - ...wallets.map( - (wallet) => Padding( - padding: const EdgeInsets.all(12), - child: Row( - key: Key( - "startupWalletSelectionGroupKey_${wallet.walletId}", - ), - children: [ - Container( - decoration: BoxDecoration( - color: ref - .watch( - pCoinColor( - ref.watch( - pWalletCoin( - wallet.walletId, + body: SafeArea( + child: LayoutBuilder( + builder: (context, constraints) { + return Padding( + padding: const EdgeInsets.only(left: 12, top: 12, right: 12), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 4), + Text( + "Select a wallet to load into immediately on startup", + style: STextStyles.smallMed12(context), + ), + const SizedBox(height: 12), + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: Column( + children: [ + ...wallets.map( + (wallet) => Padding( + padding: const EdgeInsets.all(12), + child: Row( + key: Key( + "startupWalletSelectionGroupKey_${wallet.walletId}", + ), + children: [ + Container( + decoration: BoxDecoration( + color: ref + .watch( + pCoinColor( + ref.watch( + pWalletCoin( + wallet.walletId, + ), ), ), + ) + .withOpacity(0.5), + borderRadius: + BorderRadius.circular( + Constants + .size + .circularBorderRadius, ), - ) - .withOpacity(0.5), - borderRadius: BorderRadius.circular( - Constants - .size.circularBorderRadius, ), - ), - child: Padding( - padding: const EdgeInsets.all(4), - child: SvgPicture.file( - File( - ref.watch( - coinIconProvider( - ref.watch( - pWalletCoin( - wallet.walletId, + child: Padding( + padding: const EdgeInsets.all(4), + child: SvgPicture.file( + File( + ref.watch( + coinIconProvider( + ref.watch( + pWalletCoin( + wallet.walletId, + ), ), ), ), ), + width: 20, + height: 20, ), - width: 20, - height: 20, ), ), - ), - const SizedBox( - width: 12, - ), - Expanded( - child: Column( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - ref.watch( - pWalletName(wallet.walletId), - ), - style: STextStyles.titleBold12( - context, + const SizedBox(width: 12), + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + ref.watch( + pWalletName( + wallet.walletId, + ), + ), + style: + STextStyles.titleBold12( + context, + ), ), - ), - // const SizedBox( - // height: 2, - // ), - // FutureBuilder( - // future: manager.totalBalance, - // builder: (builderContext, - // AsyncSnapshot snapshot) { - // if (snapshot.connectionState == - // ConnectionState.done && - // snapshot.hasData) { - // return Text( - // "${Format.localizedStringAsFixed( - // value: snapshot.data!, - // locale: ref.watch( - // localeServiceChangeNotifierProvider - // .select((value) => - // value.locale)), - // decimalPlaces: 8, - // )} ${manager.coin.ticker}", - // style: STextStyles.itemSubtitle(context), - // ); - // } else { - // return AnimatedText( - // stringsToLoopThrough: const [ - // "Loading balance", - // "Loading balance.", - // "Loading balance..", - // "Loading balance..." - // ], - // style: STextStyles.itemSubtitle(context), - // ); - // } - // }, - // ), - ], + // const SizedBox( + // height: 2, + // ), + // FutureBuilder( + // future: manager.totalBalance, + // builder: (builderContext, + // AsyncSnapshot snapshot) { + // if (snapshot.connectionState == + // ConnectionState.done && + // snapshot.hasData) { + // return Text( + // "${Format.localizedStringAsFixed( + // value: snapshot.data!, + // locale: ref.watch( + // localeServiceChangeNotifierProvider + // .select((value) => + // value.locale)), + // decimalPlaces: 8, + // )} ${manager.coin.ticker}", + // style: STextStyles.itemSubtitle(context), + // ); + // } else { + // return AnimatedText( + // stringsToLoopThrough: const [ + // "Loading balance", + // "Loading balance.", + // "Loading balance..", + // "Loading balance..." + // ], + // style: STextStyles.itemSubtitle(context), + // ); + // } + // }, + // ), + ], + ), ), - ), - SizedBox( - height: 20, - width: 20, - child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, - value: wallet.walletId, - groupValue: ref.watch( - prefsChangeNotifierProvider - .select( - (value) => - value.startupWalletId, + SizedBox( + height: 20, + width: 20, + child: Radio( + activeColor: + Theme.of(context) + .extension()! + .radioButtonIconEnabled, + value: wallet.walletId, + groupValue: ref.watch( + prefsChangeNotifierProvider + .select( + (value) => + value.startupWalletId, + ), ), + onChanged: (value) { + if (value is String) { + ref + .read( + prefsChangeNotifierProvider, + ) + .startupWalletId = value; + } + }, ), - onChanged: (value) { - if (value is String) { - ref - .read( - prefsChangeNotifierProvider, - ) - .startupWalletId = value; - } - }, ), - ), - ], + ], + ), ), ), - ), - ], + ], + ), ), - ), - ], + ], + ), ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ); diff --git a/lib/pages/settings_views/global_settings_view/support_view.dart b/lib/pages/settings_views/global_settings_view/support_view.dart index 8c348d99a..fcfc6ee18 100644 --- a/lib/pages/settings_views/global_settings_view/support_view.dart +++ b/lib/pages/settings_views/global_settings_view/support_view.dart @@ -10,6 +10,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:url_launcher/url_launcher.dart'; + import '../../../app_config.dart'; import '../../../themes/stack_colors.dart'; import '../../../utilities/assets.dart'; @@ -20,12 +22,9 @@ import '../../../widgets/background.dart'; import '../../../widgets/conditional_parent.dart'; import '../../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../../widgets/rounded_white_container.dart'; -import 'package:url_launcher/url_launcher.dart'; class SupportView extends StatelessWidget { - const SupportView({ - super.key, - }); + const SupportView({super.key}); static const String routeName = "/support"; @@ -48,14 +47,10 @@ class SupportView extends StatelessWidget { Navigator.of(context).pop(); }, ), - title: Text( - "Support", - style: STextStyles.navBarTitle(context), - ), + title: Text("Support", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: child, + body: SafeArea( + child: Padding(padding: const EdgeInsets.all(16), child: child), ), ), ); @@ -69,13 +64,7 @@ class SupportView extends StatelessWidget { style: STextStyles.smallMed12(context), ), ), - isDesktop - ? const SizedBox( - height: 24, - ) - : const SizedBox( - height: 12, - ), + isDesktop ? const SizedBox(height: 24) : const SizedBox(height: 12), AboutItem( linkUrl: "https://t.me/stackwallet", label: "Telegram", @@ -83,9 +72,7 @@ class SupportView extends StatelessWidget { iconAsset: Assets.socials.telegram, isDesktop: isDesktop, ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), AboutItem( linkUrl: "https://discord.com/invite/mRPZuXx3At", label: "Discord", @@ -93,9 +80,7 @@ class SupportView extends StatelessWidget { iconAsset: Assets.socials.discord, isDesktop: isDesktop, ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), AboutItem( linkUrl: "https://www.reddit.com/r/stackwallet/", label: "Reddit", @@ -103,9 +88,7 @@ class SupportView extends StatelessWidget { iconAsset: Assets.socials.reddit, isDesktop: isDesktop, ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), AboutItem( linkUrl: "https://twitter.com/stack_wallet", label: "Twitter", @@ -113,9 +96,7 @@ class SupportView extends StatelessWidget { iconAsset: Assets.socials.twitter, isDesktop: isDesktop, ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), AboutItem( linkUrl: "mailto:support@stackwallet.com", label: "Email", @@ -160,21 +141,13 @@ class AboutItem extends StatelessWidget { ), ), onPressed: () { - launchUrl( - Uri.parse(linkUrl), - mode: LaunchMode.externalApplication, - ); + launchUrl(Uri.parse(linkUrl), mode: LaunchMode.externalApplication); }, child: Padding( - padding: isDesktop - ? const EdgeInsets.symmetric( - horizontal: 20, - vertical: 15, - ) - : const EdgeInsets.symmetric( - horizontal: 12, - vertical: 20, - ), + padding: + isDesktop + ? const EdgeInsets.symmetric(horizontal: 20, vertical: 15) + : const EdgeInsets.symmetric(horizontal: 12, vertical: 20), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -182,31 +155,30 @@ class AboutItem extends StatelessWidget { children: [ ConditionalParent( condition: isDesktop, - builder: (child) => Container( - width: 40, - height: 40, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(10000), - color: Theme.of(context) - .extension()! - .buttonBackSecondary, - ), - child: Center( - child: child, - ), - ), + builder: + (child) => Container( + width: 40, + height: 40, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10000), + color: + Theme.of( + context, + ).extension()!.buttonBackSecondary, + ), + child: Center(child: child), + ), child: SvgPicture.asset( iconAsset, width: iconSize, height: iconSize, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Text( label, style: STextStyles.titleBold12(context), diff --git a/lib/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_options_view.dart b/lib/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_options_view.dart index b036f89f8..7a0644f4d 100644 --- a/lib/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_options_view.dart +++ b/lib/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_options_view.dart @@ -46,26 +46,23 @@ class SyncingOptionsView extends ConsumerWidget { Navigator.of(context).pop(); }, ), - title: Text( - "Syncing", - style: STextStyles.navBarTitle(context), - ), + title: Text("Syncing", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: child, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight(child: child), ), - ), - ); - }, + ); + }, + ), ), ), ), @@ -114,13 +111,15 @@ class SyncingOptionsView extends ConsumerWidget { width: 20, height: 20, child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, + activeColor: + Theme.of(context) + .extension()! + .radioButtonIconEnabled, value: SyncingType.currentWalletOnly, groupValue: ref.watch( - prefsChangeNotifierProvider - .select((value) => value.syncType), + prefsChangeNotifierProvider.select( + (value) => value.syncType, + ), ), onChanged: (value) { if (value is SyncingType) { @@ -131,9 +130,7 @@ class SyncingOptionsView extends ConsumerWidget { }, ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Flexible( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -192,13 +189,15 @@ class SyncingOptionsView extends ConsumerWidget { width: 20, height: 20, child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, + activeColor: + Theme.of(context) + .extension()! + .radioButtonIconEnabled, value: SyncingType.allWalletsOnStartup, groupValue: ref.watch( - prefsChangeNotifierProvider - .select((value) => value.syncType), + prefsChangeNotifierProvider.select( + (value) => value.syncType, + ), ), onChanged: (value) { if (value is SyncingType) { @@ -209,9 +208,7 @@ class SyncingOptionsView extends ConsumerWidget { }, ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Flexible( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -272,13 +269,15 @@ class SyncingOptionsView extends ConsumerWidget { width: 20, height: 20, child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, + activeColor: + Theme.of(context) + .extension()! + .radioButtonIconEnabled, value: SyncingType.selectedWalletsAtStartup, groupValue: ref.watch( - prefsChangeNotifierProvider - .select((value) => value.syncType), + prefsChangeNotifierProvider.select( + (value) => value.syncType, + ), ), onChanged: (value) { if (value is SyncingType) { @@ -289,9 +288,7 @@ class SyncingOptionsView extends ConsumerWidget { }, ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Flexible( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -316,16 +313,16 @@ class SyncingOptionsView extends ConsumerWidget { ), ), if (ref.watch( - prefsChangeNotifierProvider - .select((value) => value.syncType), + prefsChangeNotifierProvider.select( + (value) => value.syncType, + ), ) != SyncingType.selectedWalletsAtStartup) - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), if (ref.watch( - prefsChangeNotifierProvider - .select((value) => value.syncType), + prefsChangeNotifierProvider.select( + (value) => value.syncType, + ), ) == SyncingType.selectedWalletsAtStartup) Container( @@ -339,10 +336,7 @@ class SyncingOptionsView extends ConsumerWidget { child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const SizedBox( - width: 12 + 20, - height: 12, - ), + const SizedBox(width: 12 + 20, height: 12), Flexible( child: RawMaterialButton( // splashColor: Theme.of(context).extension()!.highlight, @@ -356,48 +350,50 @@ class SyncingOptionsView extends ConsumerWidget { onPressed: () { !isDesktop ? Navigator.of(context).pushNamed( - WalletSyncingOptionsView.routeName, - ) + WalletSyncingOptionsView.routeName, + ) : showDialog( - context: context, - useSafeArea: false, - barrierDismissible: true, - builder: (context) { - return DesktopDialog( - maxWidth: 600, - maxHeight: 800, - child: Column( - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment - .spaceBetween, - children: [ - Padding( - padding: - const EdgeInsets.all( - 32, - ), - child: Text( - "Select wallets to sync", - style: STextStyles - .desktopH3(context), - textAlign: - TextAlign.center, - ), + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return DesktopDialog( + maxWidth: 600, + maxHeight: 800, + child: Column( + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Padding( + padding: + const EdgeInsets.all( + 32, + ), + child: Text( + "Select wallets to sync", + style: + STextStyles.desktopH3( + context, + ), + textAlign: + TextAlign.center, ), - const DesktopDialogCloseButton(), - ], - ), - const Expanded( - child: - WalletSyncingOptionsView(), - ), - ], - ), - ); - }, - ); + ), + const DesktopDialogCloseButton(), + ], + ), + const Expanded( + child: + WalletSyncingOptionsView(), + ), + ], + ), + ); + }, + ); }, child: Column( crossAxisAlignment: CrossAxisAlignment.start, diff --git a/lib/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_preferences_view.dart b/lib/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_preferences_view.dart index 988d951f1..7c29aa9b0 100644 --- a/lib/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_preferences_view.dart +++ b/lib/pages/settings_views/global_settings_view/syncing_preferences_views/syncing_preferences_view.dart @@ -54,127 +54,136 @@ class SyncingPreferencesView extends ConsumerWidget { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedWhiteContainer( padding: const EdgeInsets.all(0), - materialTapTargetSize: - MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + padding: const EdgeInsets.all(0), + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - ), - onPressed: () { - Navigator.of(context) - .pushNamed(SyncingOptionsView.routeName); - }, - child: Padding( - padding: const EdgeInsets.all(12), - child: Row( - children: [ - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Syncing", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - Text( - _currentTypeDescription( - ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.syncType, + onPressed: () { + Navigator.of( + context, + ).pushNamed(SyncingOptionsView.routeName); + }, + child: Padding( + padding: const EdgeInsets.all(12), + child: Row( + children: [ + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Syncing", + style: STextStyles.titleBold12( + context, + ), + textAlign: TextAlign.left, + ), + Text( + _currentTypeDescription( + ref.watch( + prefsChangeNotifierProvider + .select( + (value) => value.syncType, + ), ), ), + style: STextStyles.itemSubtitle( + context, + ), + textAlign: TextAlign.left, ), - style: - STextStyles.itemSubtitle(context), - textAlign: TextAlign.left, - ), - ], - ), - const Spacer(), - ], + ], + ), + const Spacer(), + ], + ), ), ), ), - ), - const SizedBox( - height: 8, - ), - RoundedWhiteContainer( - child: Consumer( - builder: (_, ref, __) { - return RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: - MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + const SizedBox(height: 8), + RoundedWhiteContainer( + child: Consumer( + builder: (_, ref, __) { + return RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - ), - onPressed: null, - child: Padding( - padding: - const EdgeInsets.symmetric(vertical: 8), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - "AutoSync only on Wi-Fi", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: ref.watch( - prefsChangeNotifierProvider.select( - (value) => value.wifiOnly, + onPressed: null, + child: Padding( + padding: const EdgeInsets.symmetric( + vertical: 8, + ), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "AutoSync only on Wi-Fi", + style: STextStyles.titleBold12( + context, + ), + textAlign: TextAlign.left, + ), + SizedBox( + height: 20, + width: 40, + child: DraggableSwitchButton( + isOn: ref.watch( + prefsChangeNotifierProvider + .select( + (value) => value.wifiOnly, + ), ), + onValueChanged: (newValue) { + ref + .read( + prefsChangeNotifierProvider, + ) + .wifiOnly = newValue; + }, ), - onValueChanged: (newValue) { - ref - .read( - prefsChangeNotifierProvider, - ) - .wifiOnly = newValue; - }, ), - ), - ], + ], + ), ), - ), - ); - }, + ); + }, + ), ), - ), - ], + ], + ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/settings_views/global_settings_view/syncing_preferences_views/wallet_syncing_options_view.dart b/lib/pages/settings_views/global_settings_view/syncing_preferences_views/wallet_syncing_options_view.dart index f974226b6..c5916cf70 100644 --- a/lib/pages/settings_views/global_settings_view/syncing_preferences_views/wallet_syncing_options_view.dart +++ b/lib/pages/settings_views/global_settings_view/syncing_preferences_views/wallet_syncing_options_view.dart @@ -60,13 +60,11 @@ class WalletSyncingOptionsView extends ConsumerWidget { ), ), ), - body: Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only(left: 12, top: 12, right: 12), + child: child, ), - child: child, ), ), ); @@ -92,23 +90,20 @@ class WalletSyncingOptionsView extends ConsumerWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), Text( "Choose the wallets to sync automatically at startup", style: STextStyles.smallMed12(context), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), RoundedWhiteContainer( padding: const EdgeInsets.all(0), - borderColor: !isDesktop - ? Colors.transparent - : Theme.of(context) - .extension()! - .background, + borderColor: + !isDesktop + ? Colors.transparent + : Theme.of( + context, + ).extension()!.background, child: Column( children: [ ...walletInfos.map( @@ -141,9 +136,7 @@ class WalletSyncingOptionsView extends ConsumerWidget { ), ), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -153,11 +146,10 @@ class WalletSyncingOptionsView extends ConsumerWidget { Text( info.name, style: STextStyles.titleBold12( - context), - ), - const SizedBox( - height: 2, + context, + ), ), + const SizedBox(height: 2), Text( ref .watch( @@ -173,7 +165,8 @@ class WalletSyncingOptionsView extends ConsumerWidget { .total, ), style: STextStyles.itemSubtitle( - context), + context, + ), ), ], ), @@ -184,10 +177,10 @@ class WalletSyncingOptionsView extends ConsumerWidget { child: DraggableSwitchButton( isOn: ref .watch( - prefsChangeNotifierProvider - .select( - (value) => value - .walletIdsSyncOnStartup, + prefsChangeNotifierProvider.select( + (value) => + value + .walletIdsSyncOnStartup, ), ) .contains(info.walletId), @@ -195,11 +188,13 @@ class WalletSyncingOptionsView extends ConsumerWidget { // final syncType = ref // .read(prefsChangeNotifierProvider) // .syncType; - final ids = ref - .read( - prefsChangeNotifierProvider) - .walletIdsSyncOnStartup - .toList(); + final ids = + ref + .read( + prefsChangeNotifierProvider, + ) + .walletIdsSyncOnStartup + .toList(); if (value) { ids.add(info.walletId); } else { @@ -228,7 +223,8 @@ class WalletSyncingOptionsView extends ConsumerWidget { ref .read( - prefsChangeNotifierProvider) + prefsChangeNotifierProvider, + ) .walletIdsSyncOnStartup = ids; }, ), diff --git a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart index 245937fdf..24800936d 100644 --- a/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/tor_settings/tor_settings_view.dart @@ -34,9 +34,7 @@ import '../../../../widgets/stack_dialog.dart'; import '../../../../widgets/tor_subscription.dart'; class TorSettingsView extends ConsumerStatefulWidget { - const TorSettingsView({ - super.key, - }); + const TorSettingsView({super.key}); static const String routeName = "/torSettings"; @@ -59,17 +57,12 @@ class _TorSettingsViewState extends ConsumerState { Navigator.of(context).pop(); }, ), - title: Text( - "Tor settings", - style: STextStyles.navBarTitle(context), - ), + title: Text("Tor settings", style: STextStyles.navBarTitle(context)), actions: [ AspectRatio( aspectRatio: 1, child: AppBarIconButton( - icon: SvgPicture.asset( - Assets.svg.circleQuestion, - ), + icon: SvgPicture.asset(Assets.svg.circleQuestion), onPressed: () { showDialog( context: context, @@ -94,107 +87,107 @@ class _TorSettingsViewState extends ConsumerState { ), ], ), - body: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Padding( - padding: EdgeInsets.all(10.0), - child: TorAnimatedButton(), - ), - ], - ), - const SizedBox( - height: 30, - ), - const TorButton(), - const SizedBox( - height: 8, - ), - RoundedWhiteContainer( - child: Consumer( - builder: (_, ref, __) { - return RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: EdgeInsets.all(10.0), + child: TorAnimatedButton(), + ), + ], + ), + const SizedBox(height: 30), + const TorButton(), + const SizedBox(height: 8), + RoundedWhiteContainer( + child: Consumer( + builder: (_, ref, __) { + return RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - ), - onPressed: null, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - children: [ - Text( - "Tor killswitch", - style: STextStyles.titleBold12(context), - ), - const SizedBox(width: 8), - GestureDetector( - onTap: () { - showDialog( - context: context, - useSafeArea: false, - barrierDismissible: true, - builder: (context) { - return StackDialog( - title: "What is Tor killswitch?", - message: - "A security feature that protects your information from accidental exposure by" - " disconnecting your device from the Tor network if the" - " connection is disrupted or compromised.", - rightButton: SecondaryButton( - label: "Close", - onPressed: - Navigator.of(context).pop, - ), - ); - }, - ); - }, - child: SvgPicture.asset( - Assets.svg.circleInfo, - height: 16, - width: 16, - color: Theme.of(context) - .extension()! - .infoItemLabel, + onPressed: null, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Text( + "Tor killswitch", + style: STextStyles.titleBold12(context), ), + const SizedBox(width: 8), + GestureDetector( + onTap: () { + showDialog( + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return StackDialog( + title: "What is Tor killswitch?", + message: + "A security feature that protects your information from accidental exposure by" + " disconnecting your device from the Tor network if the" + " connection is disrupted or compromised.", + rightButton: SecondaryButton( + label: "Close", + onPressed: + Navigator.of(context).pop, + ), + ); + }, + ); + }, + child: SvgPicture.asset( + Assets.svg.circleInfo, + height: 16, + width: 16, + color: + Theme.of(context) + .extension()! + .infoItemLabel, + ), + ), + ], + ), + SizedBox( + height: 20, + width: 40, + child: DraggableSwitchButton( + isOn: ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.torKillSwitch, + ), + ), + onValueChanged: (newValue) { + ref + .read(prefsChangeNotifierProvider) + .torKillSwitch = newValue; + }, ), - ], - ), - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: ref.watch( - prefsChangeNotifierProvider - .select((value) => value.torKillSwitch), - ), - onValueChanged: (newValue) { - ref - .read(prefsChangeNotifierProvider) - .torKillSwitch = newValue; - }, ), - ), - ], + ], + ), ), - ), - ); - }, + ); + }, + ), ), - ), - ], + ], + ), ), ), ), @@ -248,11 +241,7 @@ class _TorAnimatedButtonState extends ConsumerState } Future _playPlug() async { - await _play( - from: "0.0", - to: "connecting-start", - repeat: false, - ); + await _play(from: "0.0", to: "connecting-start", repeat: false); } Future _playConnecting({double? start}) async { @@ -272,11 +261,7 @@ class _TorAnimatedButtonState extends ConsumerState } Future _playConnected() async { - await _play( - from: "connected-start", - to: "connected-end", - repeat: true, - ); + await _play(from: "connected-start", to: "connected-end", repeat: true); } Future _playDisconnect() async { @@ -358,10 +343,7 @@ class _TorAnimatedButtonState extends ConsumerState }, child: ConditionalParent( condition: _status != TorConnectionStatus.connecting, - builder: (child) => GestureDetector( - onTap: onTap, - child: child, - ), + builder: (child) => GestureDetector(onTap: onTap, child: child), child: Column( children: [ SizedBox( @@ -401,10 +383,7 @@ class TorButton extends ConsumerStatefulWidget { class _TorButtonState extends ConsumerState { late TorConnectionStatus _status; - Color _color( - TorConnectionStatus status, - StackColors colors, - ) { + Color _color(TorConnectionStatus status, StackColors colors) { switch (status) { case TorConnectionStatus.disconnected: return colors.textSubtitle3; @@ -417,10 +396,7 @@ class _TorButtonState extends ConsumerState { } } - String _label( - TorConnectionStatus status, - StackColors colors, - ) { + String _label(TorConnectionStatus status, StackColors colors) { switch (status) { case TorConnectionStatus.disconnected: return "Disconnected"; @@ -487,16 +463,10 @@ class _TorButtonState extends ConsumerState { padding: const EdgeInsets.symmetric(vertical: 8.0), child: Row( children: [ - Text( - "Tor status", - style: STextStyles.titleBold12(context), - ), + Text("Tor status", style: STextStyles.titleBold12(context)), const Spacer(), Text( - _label( - _status, - Theme.of(context).extension()!, - ), + _label(_status, Theme.of(context).extension()!), style: STextStyles.itemSubtitle(context).copyWith( color: _color( _status, @@ -523,10 +493,7 @@ class UpperCaseTorText extends ConsumerStatefulWidget { class _UpperCaseTorTextState extends ConsumerState { late TorConnectionStatus _status; - Color _color( - TorConnectionStatus status, - StackColors colors, - ) { + Color _color(TorConnectionStatus status, StackColors colors) { switch (status) { case TorConnectionStatus.disconnected: return colors.textSubtitle3; @@ -539,9 +506,7 @@ class _UpperCaseTorTextState extends ConsumerState { } } - String _label( - TorConnectionStatus status, - ) { + String _label(TorConnectionStatus status) { switch (status) { case TorConnectionStatus.disconnected: return "CONNECT"; @@ -570,16 +535,9 @@ class _UpperCaseTorTextState extends ConsumerState { }); }, child: Text( - _label( - _status, - ), - style: STextStyles.pageTitleH2( - context, - ).copyWith( - color: _color( - _status, - Theme.of(context).extension()!, - ), + _label(_status), + style: STextStyles.pageTitleH2(context).copyWith( + color: _color(_status, Theme.of(context).extension()!), ), ), ); diff --git a/lib/pages/settings_views/wallet_settings_view/frost_ms/frost_ms_options_view.dart b/lib/pages/settings_views/wallet_settings_view/frost_ms/frost_ms_options_view.dart index 3404b395e..812639eb4 100644 --- a/lib/pages/settings_views/wallet_settings_view/frost_ms/frost_ms_options_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/frost_ms/frost_ms_options_view.dart @@ -34,10 +34,7 @@ import 'frost_participants_view.dart'; import 'initiate_resharing/initiate_resharing_view.dart'; class FrostMSWalletOptionsView extends ConsumerWidget { - const FrostMSWalletOptionsView({ - super.key, - required this.walletId, - }); + const FrostMSWalletOptionsView({super.key, required this.walletId}); static const String routeName = "/frostMSWalletOptionsView"; @@ -49,44 +46,39 @@ class FrostMSWalletOptionsView extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { return ConditionalParent( condition: Util.isDesktop, - builder: (child) => DesktopScaffold( - background: Theme.of(context).extension()!.background, - appBar: const DesktopAppBar( - isCompactHeight: false, - leading: AppBarBackButton(), - trailing: ExitToMyStackButton(), - ), - body: SizedBox( - width: 480, - child: child, - ), - ), + builder: + (child) => DesktopScaffold( + background: Theme.of(context).extension()!.background, + appBar: const DesktopAppBar( + isCompactHeight: false, + leading: AppBarBackButton(), + trailing: ExitToMyStackButton(), + ), + body: SizedBox(width: 480, child: child), + ), child: ConditionalParent( condition: !Util.isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () { - Navigator.of(context).pop(); - }, - ), - title: Text( - "FROST Multisig options", - style: STextStyles.navBarTitle(context), + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () { + Navigator.of(context).pop(); + }, + ), + title: Text( + "FROST Multisig options", + style: STextStyles.navBarTitle(context), + ), + ), + body: SafeArea(child: child), ), ), - body: child, - ), - ), child: Padding( - padding: const EdgeInsets.only( - top: 12, - left: 16, - right: 16, - ), + padding: const EdgeInsets.only(top: 12, left: 16, right: 16), child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, @@ -105,9 +97,7 @@ class FrostMSWalletOptionsView extends ConsumerWidget { }, ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( padding: EdgeInsets.zero, child: SettingsListButton( @@ -116,11 +106,12 @@ class FrostMSWalletOptionsView extends ConsumerWidget { iconAssetName: Assets.svg.swap2, onPressed: () { // TODO: optimize this by creating watcher providers (similar to normal WalletInfo) - final frostInfo = ref - .read(mainDBProvider) - .isar - .frostWalletInfo - .getByWalletIdSync(walletId)!; + final frostInfo = + ref + .read(mainDBProvider) + .isar + .frostWalletInfo + .getByWalletIdSync(walletId)!; ref.read(pFrostMyName.state).state = frostInfo.myName; @@ -131,9 +122,7 @@ class FrostMSWalletOptionsView extends ConsumerWidget { }, ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), RoundedWhiteContainer( padding: EdgeInsets.zero, child: SettingsListButton( @@ -143,16 +132,18 @@ class FrostMSWalletOptionsView extends ConsumerWidget { iconSize: 16, onPressed: () { // TODO: optimize this by creating watcher providers (similar to normal WalletInfo) - final frostInfo = ref - .read(mainDBProvider) - .isar - .frostWalletInfo - .getByWalletIdSync(walletId)!; + final frostInfo = + ref + .read(mainDBProvider) + .isar + .frostWalletInfo + .getByWalletIdSync(walletId)!; ref.read(pFrostMyName.state).state = frostInfo.myName; - final wallet = ref.read(pWallets).getWallet(walletId) - as BitcoinFrostWallet; + final wallet = + ref.read(pWallets).getWallet(walletId) + as BitcoinFrostWallet; ref.read(pFrostScaffoldArgs.state).state = ( info: ( @@ -167,9 +158,9 @@ class FrostMSWalletOptionsView extends ConsumerWidget { callerRouteName: FrostMSWalletOptionsView.routeName, ); - Navigator.of(context).pushNamed( - FrostStepScaffold.routeName, - ); + Navigator.of( + context, + ).pushNamed(FrostStepScaffold.routeName); }, ), ), diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_backup_views/wallet_backup_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_backup_views/wallet_backup_view.dart index 75b8ca87b..d94cca088 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_backup_views/wallet_backup_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_backup_views/wallet_backup_view.dart @@ -62,7 +62,8 @@ class WalletBackupView extends ConsumerWidget { String config, String keys, ({String config, String keys})? prevGen, - })? frostWalletData; + })? + frostWalletData; final KeyDataInterface? keyData; @override @@ -80,10 +81,7 @@ class WalletBackupView extends ConsumerWidget { Navigator.of(context).pop(); }, ), - title: Text( - "Wallet backup", - style: STextStyles.navBarTitle(context), - ), + title: Text("Wallet backup", style: STextStyles.navBarTitle(context)), actions: [ if (keyData != null) Padding( @@ -93,7 +91,8 @@ class WalletBackupView extends ConsumerWidget { final XPrivData _ => "xpriv(s)", final CWKeyData _ => "keys", final ViewOnlyWalletData _ => "keys", - _ => throw UnimplementedError( + _ => + throw UnimplementedError( "Don't forget to add your KeyDataInterface here! ${keyData.runtimeType}", ), }, @@ -101,27 +100,24 @@ class WalletBackupView extends ConsumerWidget { Navigator.pushNamed( context, MobileKeyDataView.routeName, - arguments: ( - walletId: walletId, - keyData: keyData!, - ), + arguments: (walletId: walletId, keyData: keyData!), ); }, ), ), ], ), - body: Padding( - padding: const EdgeInsets.all(16), - child: frost - ? _FrostKeys( - frostWalletData: frostWalletData, - walletId: walletId, - ) - : _Mnemonic( - walletId: walletId, - mnemonic: mnemonic, - ), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: + frost + ? _FrostKeys( + frostWalletData: frostWalletData, + walletId: walletId, + ) + : _Mnemonic(walletId: walletId, mnemonic: mnemonic), + ), ), ), ); @@ -148,21 +144,15 @@ class _Mnemonic extends ConsumerWidget { Text( ref.watch(pWalletName(walletId)), textAlign: TextAlign.center, - style: STextStyles.label(context).copyWith( - fontSize: 12, - ), - ), - const SizedBox( - height: 4, + style: STextStyles.label(context).copyWith(fontSize: 12), ), + const SizedBox(height: 4), Text( "Recovery Phrase", textAlign: TextAlign.center, style: STextStyles.pageTitleH1(context), ), - const SizedBox( - height: 16, - ), + const SizedBox(height: 16), Container( decoration: BoxDecoration( color: Theme.of(context).extension()!.popupBG, @@ -182,25 +172,19 @@ class _Mnemonic extends ConsumerWidget { ), ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), Expanded( child: SingleChildScrollView( - child: MnemonicTable( - words: mnemonic, - isDesktop: false, - ), + child: MnemonicTable(words: mnemonic, isDesktop: false), ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), SecondaryButton( label: "Copy", onPressed: () async { - await clipboardInterface - .setData(ClipboardData(text: mnemonic.join(" "))); + await clipboardInterface.setData( + ClipboardData(text: mnemonic.join(" ")), + ); if (context.mounted) { unawaited( showFloatingFlushBar( @@ -213,9 +197,7 @@ class _Mnemonic extends ConsumerWidget { } }, ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), PrimaryButton( label: "Show QR Code", onPressed: () { @@ -237,25 +219,18 @@ class _Mnemonic extends ConsumerWidget { style: STextStyles.pageTitleH2(context), ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Center( child: RepaintBoundary( // key: _qrKey, child: SizedBox( width: width + 20, height: width + 20, - child: QR( - data: data, - size: width, - ), + child: QR(data: data, size: width), ), ), ), - const SizedBox( - height: 12, - ), + const SizedBox(height: 12), Center( child: SizedBox( width: width, @@ -266,15 +241,14 @@ class _Mnemonic extends ConsumerWidget { }, style: Theme.of(context) .extension()! - .getSecondaryEnabledButtonStyle( - context, - ), + .getSecondaryEnabledButtonStyle(context), child: Text( "Cancel", style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, ), ), ), @@ -293,11 +267,7 @@ class _Mnemonic extends ConsumerWidget { } class _FrostKeys extends StatelessWidget { - const _FrostKeys({ - super.key, - required this.walletId, - this.frostWalletData, - }); + const _FrostKeys({super.key, required this.walletId, this.frostWalletData}); final String walletId; final ({ @@ -305,7 +275,8 @@ class _FrostKeys extends StatelessWidget { String config, String keys, ({String config, String keys})? prevGen, - })? frostWalletData; + })? + frostWalletData; @override Widget build(BuildContext context) { @@ -314,9 +285,7 @@ class _FrostKeys extends StatelessWidget { builder: (builderContext, constraints) { return SingleChildScrollView( child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), + constraints: BoxConstraints(minHeight: constraints.maxHeight - 24), child: IntrinsicHeight( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, @@ -334,9 +303,7 @@ class _FrostKeys extends StatelessWidget { style: STextStyles.label(context), ), ), - const SizedBox( - height: 24, - ), + const SizedBox(height: 24), // DetailItem( // title: "My name", // detail: frostWalletData!.myName, @@ -354,32 +321,21 @@ class _FrostKeys extends StatelessWidget { DetailItem( title: "Multisig config", detail: frostWalletData!.config, - button: Util.isDesktop - ? IconCopyButton( - data: frostWalletData!.config, - ) - : SimpleCopyButton( - data: frostWalletData!.config, - ), - ), - const SizedBox( - height: 16, + button: + Util.isDesktop + ? IconCopyButton(data: frostWalletData!.config) + : SimpleCopyButton(data: frostWalletData!.config), ), + const SizedBox(height: 16), DetailItem( title: "Keys", detail: frostWalletData!.keys, - button: Util.isDesktop - ? IconCopyButton( - data: frostWalletData!.keys, - ) - : SimpleCopyButton( - data: frostWalletData!.keys, - ), + button: + Util.isDesktop + ? IconCopyButton(data: frostWalletData!.keys) + : SimpleCopyButton(data: frostWalletData!.keys), ), - if (prevGen) - const SizedBox( - height: 24, - ), + if (prevGen) const SizedBox(height: 24), if (prevGen) RoundedWhiteContainer( child: Text( @@ -387,37 +343,33 @@ class _FrostKeys extends StatelessWidget { style: STextStyles.label(context), ), ), - if (prevGen) - const SizedBox( - height: 12, - ), + if (prevGen) const SizedBox(height: 12), if (prevGen) DetailItem( title: "Previous multisig config", detail: frostWalletData!.prevGen!.config, - button: Util.isDesktop - ? IconCopyButton( - data: frostWalletData!.prevGen!.config, - ) - : SimpleCopyButton( - data: frostWalletData!.prevGen!.config, - ), - ), - if (prevGen) - const SizedBox( - height: 16, + button: + Util.isDesktop + ? IconCopyButton( + data: frostWalletData!.prevGen!.config, + ) + : SimpleCopyButton( + data: frostWalletData!.prevGen!.config, + ), ), + if (prevGen) const SizedBox(height: 16), if (prevGen) DetailItem( title: "Previous keys", detail: frostWalletData!.prevGen!.keys, - button: Util.isDesktop - ? IconCopyButton( - data: frostWalletData!.prevGen!.keys, - ) - : SimpleCopyButton( - data: frostWalletData!.prevGen!.keys, - ), + button: + Util.isDesktop + ? IconCopyButton( + data: frostWalletData!.prevGen!.keys, + ) + : SimpleCopyButton( + data: frostWalletData!.prevGen!.keys, + ), ), ], ), @@ -459,9 +411,7 @@ class MobileKeyDataView extends ConsumerWidget { final XPrivData _ => "xpriv(s)", final CWKeyData _ => "keys", final ViewOnlyWalletData _ => "keys", - _ => throw UnimplementedError( - "Don't forget to add your KeyDataInterface here!", - ), + _ => throw UnimplementedError("Don't forget to add your KeyDataInterface here!"), }}", style: STextStyles.navBarTitle(context), ), @@ -470,40 +420,40 @@ class MobileKeyDataView extends ConsumerWidget { child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: LayoutBuilder( - builder: (context, constraints) => SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints(minHeight: constraints.maxHeight), - child: IntrinsicHeight( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Expanded( - child: switch (keyData) { - final XPrivData e => WalletXPrivs( - walletId: walletId, - xprivData: e, - ), - final CWKeyData e => CNWalletKeys( - walletId: walletId, - cwKeyData: e, - ), - final ViewOnlyWalletData e => - ViewOnlyWalletDataWidget( - data: e, - ), - _ => throw UnimplementedError( - "Don't forget to add your KeyDataInterface here!", - ), - }, - ), - const SizedBox( - height: 16, + builder: + (context, constraints) => SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Expanded( + child: switch (keyData) { + final XPrivData e => WalletXPrivs( + walletId: walletId, + xprivData: e, + ), + final CWKeyData e => CNWalletKeys( + walletId: walletId, + cwKeyData: e, + ), + final ViewOnlyWalletData e => + ViewOnlyWalletDataWidget(data: e), + _ => + throw UnimplementedError( + "Don't forget to add your KeyDataInterface here!", + ), + }, + ), + const SizedBox(height: 16), + ], ), - ], + ), ), ), - ), - ), ), ), ), diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart index 5b3a2eb07..506f1167c 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_network_settings_view/wallet_network_settings_view.dart @@ -142,9 +142,7 @@ class _WalletNetworkSettingsViewState try { final wallet = ref.read(pWallets).getWallet(widget.walletId); - await wallet.recover( - isRescan: true, - ); + await wallet.recover(isRescan: true); if (mounted) { // pop rescanning dialog @@ -155,29 +153,31 @@ class _WalletNetworkSettingsViewState context: context, useSafeArea: false, barrierDismissible: true, - builder: (context) => ConditionalParent( - condition: isDesktop, - builder: (child) => DesktopDialog( - maxHeight: 150, - maxWidth: 500, - child: child, - ), - child: StackDialog( - title: "Rescan completed", - rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - child: Text( - "Ok", - style: STextStyles.itemSubtitle12(context), + builder: + (context) => ConditionalParent( + condition: isDesktop, + builder: + (child) => DesktopDialog( + maxHeight: 150, + maxWidth: 500, + child: child, + ), + child: StackDialog( + title: "Rescan completed", + rightButton: TextButton( + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle(context), + child: Text( + "Ok", + style: STextStyles.itemSubtitle12(context), + ), + onPressed: () { + Navigator.of(context, rootNavigator: isDesktop).pop(); + }, + ), ), - onPressed: () { - Navigator.of(context, rootNavigator: isDesktop).pop(); - }, ), - ), - ), ); } } catch (e) { @@ -192,22 +192,23 @@ class _WalletNetworkSettingsViewState context: context, useSafeArea: false, barrierDismissible: true, - builder: (context) => StackDialog( - title: "Rescan failed", - message: e.toString(), - rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - child: Text( - "Ok", - style: STextStyles.itemSubtitle12(context), + builder: + (context) => StackDialog( + title: "Rescan failed", + message: e.toString(), + rightButton: TextButton( + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle(context), + child: Text( + "Ok", + style: STextStyles.itemSubtitle12(context), + ), + onPressed: () { + Navigator.of(context, rootNavigator: isDesktop).pop(); + }, + ), ), - onPressed: () { - Navigator.of(context, rootNavigator: isDesktop).pop(); - }, - ), - ), ); } } @@ -246,26 +247,25 @@ class _WalletNetworkSettingsViewState eventBus = widget.eventBus != null ? widget.eventBus! : GlobalEventBus.instance; - _syncStatusSubscription = - eventBus.on().listen( - (event) async { - if (event.walletId == widget.walletId) { - setState(() { - _currentSyncStatus = event.newStatus; - }); - } - }, - ); + _syncStatusSubscription = eventBus + .on() + .listen((event) async { + if (event.walletId == widget.walletId) { + setState(() { + _currentSyncStatus = event.newStatus; + }); + } + }); - _refreshSubscription = eventBus.on().listen( - (event) async { - if (event.walletId == widget.walletId) { - setState(() { - _percent = event.percent.clamp(0.0, 1.0); - }); - } - }, - ); + _refreshSubscription = eventBus.on().listen(( + event, + ) async { + if (event.walletId == widget.walletId) { + setState(() { + _percent = event.percent.clamp(0.0, 1.0); + }); + } + }); final coin = ref.read(pWalletCoin(widget.walletId)); @@ -322,9 +322,10 @@ class _WalletNetworkSettingsViewState Widget build(BuildContext context) { final screenWidth = MediaQuery.of(context).size.width; - final progressLength = isDesktop - ? 430.0 - : screenWidth - (_padding * 2) - (_boxPadding * 3) - _iconSize; + final progressLength = + isDesktop + ? 430.0 + : screenWidth - (_padding * 2) - (_boxPadding * 3) - _iconSize; final coin = ref.watch(pWalletCoin(widget.walletId)); @@ -364,10 +365,7 @@ class _WalletNetworkSettingsViewState Navigator.of(context).pop(); }, ), - title: Text( - "Network", - style: STextStyles.navBarTitle(context), - ), + title: Text("Network", style: STextStyles.navBarTitle(context)), actions: [ if (ref.watch(pWalletCoin(widget.walletId)) is! Epiccash) Padding( @@ -384,14 +382,16 @@ class _WalletNetworkSettingsViewState ), size: 36, shadows: const [], - color: Theme.of(context) - .extension()! - .background, + color: + Theme.of( + context, + ).extension()!.background, icon: SvgPicture.asset( Assets.svg.verticalEllipsis, - color: Theme.of(context) - .extension()! - .accentColorDark, + color: + Theme.of( + context, + ).extension()!.accentColorDark, width: 20, height: 20, ), @@ -408,9 +408,10 @@ class _WalletNetworkSettingsViewState right: 10, child: Container( decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .popupBG, + color: + Theme.of( + context, + ).extension()!.popupBG, borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), @@ -461,18 +462,18 @@ class _WalletNetworkSettingsViewState ), ], ), - body: Padding( - padding: EdgeInsets.only( - top: 12, - left: _padding, - right: _padding, - ), - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - child, - ], + body: SafeArea( + child: Padding( + padding: EdgeInsets.only( + top: 12, + left: _padding, + right: _padding, + ), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [child], + ), ), ), ), @@ -488,9 +489,10 @@ class _WalletNetworkSettingsViewState Text( "Blockchain status", textAlign: TextAlign.left, - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context) - : STextStyles.smallMed12(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall(context) + : STextStyles.smallMed12(context), ), CustomTextButton( text: "Resync", @@ -500,17 +502,17 @@ class _WalletNetworkSettingsViewState ), ], ), - SizedBox( - height: isDesktop ? 12 : 9, - ), + SizedBox(height: isDesktop ? 12 : 9), if (_currentSyncStatus == WalletSyncStatus.synced) RoundedWhiteContainer( - borderColor: isDesktop - ? Theme.of(context).extension()!.background - : null, - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + borderColor: + isDesktop + ? Theme.of(context).extension()!.background + : null, + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( children: [ Container( @@ -528,15 +530,14 @@ class _WalletNetworkSettingsViewState Assets.svg.radio, height: isDesktop ? 19 : 14, width: isDesktop ? 19 : 14, - color: Theme.of(context) - .extension()! - .accentColorGreen, + color: + Theme.of( + context, + ).extension()!.accentColorGreen, ), ), ), - SizedBox( - width: _boxPadding, - ), + SizedBox(width: _boxPadding), Column( children: [ SizedBox( @@ -551,18 +552,18 @@ class _WalletNetworkSettingsViewState ], ), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), ProgressBar( width: progressLength, height: 5, - fillColor: Theme.of(context) - .extension()! - .accentColorGreen, - backgroundColor: Theme.of(context) - .extension()! - .textFieldDefaultBG, + fillColor: + Theme.of( + context, + ).extension()!.accentColorGreen, + backgroundColor: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, percent: 1, ), ], @@ -572,12 +573,14 @@ class _WalletNetworkSettingsViewState ), if (_currentSyncStatus == WalletSyncStatus.syncing) RoundedWhiteContainer( - borderColor: isDesktop - ? Theme.of(context).extension()!.background - : null, - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + borderColor: + isDesktop + ? Theme.of(context).extension()!.background + : null, + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( children: [ Container( @@ -595,15 +598,14 @@ class _WalletNetworkSettingsViewState Assets.svg.radioSyncing, height: 14, width: 14, - color: Theme.of(context) - .extension()! - .accentColorYellow, + color: + Theme.of( + context, + ).extension()!.accentColorYellow, ), ), ), - SizedBox( - width: _boxPadding, - ), + SizedBox(width: _boxPadding), Column( children: [ SizedBox( @@ -624,11 +626,13 @@ class _WalletNetworkSettingsViewState children: [ Text( _percentString(_percent), - style: - STextStyles.syncPercent(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorYellow, + style: STextStyles.syncPercent( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorYellow, ), ), if (coin is Monero || @@ -636,11 +640,13 @@ class _WalletNetworkSettingsViewState coin is Epiccash) Text( " (Blocks to go: ${_blocksRemaining == -1 ? "?" : _blocksRemaining})", - style: STextStyles.syncPercent(context) - .copyWith( - color: Theme.of(context) - .extension()! - .accentColorYellow, + style: STextStyles.syncPercent( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorYellow, ), ), ], @@ -648,18 +654,18 @@ class _WalletNetworkSettingsViewState ], ), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), ProgressBar( width: progressLength, height: 5, - fillColor: Theme.of(context) - .extension()! - .accentColorYellow, - backgroundColor: Theme.of(context) - .extension()! - .textFieldDefaultBG, + fillColor: + Theme.of( + context, + ).extension()!.accentColorYellow, + backgroundColor: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, percent: _percent, ), ], @@ -669,12 +675,14 @@ class _WalletNetworkSettingsViewState ), if (_currentSyncStatus == WalletSyncStatus.unableToSync) RoundedWhiteContainer( - borderColor: isDesktop - ? Theme.of(context).extension()!.background - : null, - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + borderColor: + isDesktop + ? Theme.of(context).extension()!.background + : null, + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Row( children: [ Container( @@ -692,15 +700,14 @@ class _WalletNetworkSettingsViewState Assets.svg.radioProblem, height: 14, width: 14, - color: Theme.of(context) - .extension()! - .accentColorRed, + color: + Theme.of( + context, + ).extension()!.accentColorRed, ), ), ), - SizedBox( - width: _boxPadding, - ), + SizedBox(width: _boxPadding), Column( children: [ SizedBox( @@ -711,34 +718,36 @@ class _WalletNetworkSettingsViewState Text( "Unable to synchronize", style: STextStyles.w600_12(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorRed, + color: + Theme.of( + context, + ).extension()!.accentColorRed, ), ), Text( "0%", style: STextStyles.syncPercent(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorRed, + color: + Theme.of( + context, + ).extension()!.accentColorRed, ), ), ], ), ), - const SizedBox( - height: 4, - ), + const SizedBox(height: 4), ProgressBar( width: progressLength, height: 5, - fillColor: Theme.of(context) - .extension()! - .accentColorRed, - backgroundColor: Theme.of(context) - .extension()! - .textFieldDefaultBG, + fillColor: + Theme.of( + context, + ).extension()!.accentColorRed, + backgroundColor: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, percent: 0, ), ], @@ -748,30 +757,29 @@ class _WalletNetworkSettingsViewState ), if (_currentSyncStatus == WalletSyncStatus.unableToSync) Padding( - padding: const EdgeInsets.only( - top: 12, - ), + padding: const EdgeInsets.only(top: 12), child: RoundedContainer( - color: Theme.of(context) - .extension()! - .warningBackground, + color: + Theme.of( + context, + ).extension()!.warningBackground, child: Text( "Please check your internet connection and make sure your current node is not having issues.", style: STextStyles.baseXS(context).copyWith( - color: Theme.of(context) - .extension()! - .warningForeground, + color: + Theme.of( + context, + ).extension()!.warningForeground, ), ), ), ), - SizedBox( - height: isDesktop ? 12 : 9, - ), + SizedBox(height: isDesktop ? 12 : 9), RoundedWhiteContainer( - borderColor: isDesktop - ? Theme.of(context).extension()!.background - : null, + borderColor: + isDesktop + ? Theme.of(context).extension()!.background + : null, padding: isDesktop ? const EdgeInsets.all(16) : const EdgeInsets.all(12), child: Row( @@ -780,9 +788,10 @@ class _WalletNetworkSettingsViewState Text( "Current height", textAlign: TextAlign.left, - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context) - : STextStyles.smallMed12(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall(context) + : STextStyles.smallMed12(context), ), Text( ref.watch(pWalletChainHeight(widget.walletId)).toString(), @@ -791,36 +800,37 @@ class _WalletNetworkSettingsViewState ], ), ), - SizedBox( - height: isDesktop ? 32 : 20, - ), + SizedBox(height: isDesktop ? 32 : 20), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Tor status", textAlign: TextAlign.left, - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context) - : STextStyles.smallMed12(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall(context) + : STextStyles.smallMed12(context), ), CustomTextButton( - text: ref.watch( - prefsChangeNotifierProvider.select((value) => value.useTor), - ) - ? "Disconnect" - : "Connect", + text: + ref.watch( + prefsChangeNotifierProvider.select( + (value) => value.useTor, + ), + ) + ? "Disconnect" + : "Connect", onTap: onTorTapped, ), ], ), - SizedBox( - height: isDesktop ? 12 : 9, - ), + SizedBox(height: isDesktop ? 12 : 9), RoundedWhiteContainer( - borderColor: isDesktop - ? Theme.of(context).extension()!.background - : null, + borderColor: + isDesktop + ? Theme.of(context).extension()!.background + : null, padding: isDesktop ? const EdgeInsets.all(16) : const EdgeInsets.all(12), child: Row( @@ -843,9 +853,10 @@ class _WalletNetworkSettingsViewState Assets.svg.tor, height: isDesktop ? 19 : 14, width: isDesktop ? 19 : 14, - color: Theme.of(context) - .extension()! - .accentColorGreen, + color: + Theme.of( + context, + ).extension()!.accentColorGreen, ), ), ), @@ -856,10 +867,9 @@ class _WalletNetworkSettingsViewState width: _iconSize, height: _iconSize, decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textDark - .withOpacity(0.08), + color: Theme.of( + context, + ).extension()!.textDark.withOpacity(0.08), borderRadius: BorderRadius.circular(_iconSize), ), child: Center( @@ -867,15 +877,14 @@ class _WalletNetworkSettingsViewState Assets.svg.tor, height: isDesktop ? 19 : 14, width: isDesktop ? 19 : 14, - color: Theme.of(context) - .extension()! - .textDark, + color: + Theme.of( + context, + ).extension()!.textDark, ), ), ), - SizedBox( - width: _boxPadding, - ), + SizedBox(width: _boxPadding), TorSubscription( onTorStatusChanged: (status) { setState(() { @@ -887,32 +896,37 @@ class _WalletNetworkSettingsViewState children: [ Text( "Tor status", - style: STextStyles.desktopTextExtraExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textDark, + style: STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, ), ), if (_torConnectionStatus == TorConnectionStatus.connected) Text( "Connected", - style: - STextStyles.desktopTextExtraExtraSmall(context), + style: STextStyles.desktopTextExtraExtraSmall( + context, + ), ), if (_torConnectionStatus == TorConnectionStatus.connecting) Text( "Connecting...", - style: - STextStyles.desktopTextExtraExtraSmall(context), + style: STextStyles.desktopTextExtraExtraSmall( + context, + ), ), if (_torConnectionStatus == TorConnectionStatus.disconnected) Text( "Disconnected", - style: - STextStyles.desktopTextExtraExtraSmall(context), + style: STextStyles.desktopTextExtraExtraSmall( + context, + ), ), ], ), @@ -920,18 +934,17 @@ class _WalletNetworkSettingsViewState ], ), ), - SizedBox( - height: isDesktop ? 32 : 20, - ), + SizedBox(height: isDesktop ? 32 : 20), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "${ref.watch(pWalletCoin(widget.walletId)).prettyName} nodes", textAlign: TextAlign.left, - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall(context) - : STextStyles.smallMed12(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall(context) + : STextStyles.smallMed12(context), ), CustomTextButton( text: "Add new node", @@ -949,22 +962,16 @@ class _WalletNetworkSettingsViewState ), ], ), - SizedBox( - height: isDesktop ? 12 : 8, - ), + SizedBox(height: isDesktop ? 12 : 8), NodesList( coin: ref.watch(pWalletCoin(widget.walletId)), popBackToRoute: WalletNetworkSettingsView.routeName, ), if (isDesktop && ref.watch(pWalletCoin(widget.walletId)) is! Epiccash) - const SizedBox( - height: 32, - ), + const SizedBox(height: 32), if (isDesktop && ref.watch(pWalletCoin(widget.walletId)) is! Epiccash) Padding( - padding: const EdgeInsets.only( - bottom: 12, - ), + padding: const EdgeInsets.only(bottom: 12), child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ @@ -978,12 +985,14 @@ class _WalletNetworkSettingsViewState ), if (isDesktop && ref.watch(pWalletCoin(widget.walletId)) is! Epiccash) RoundedWhiteContainer( - borderColor: isDesktop - ? Theme.of(context).extension()!.background - : null, - padding: isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), + borderColor: + isDesktop + ? Theme.of(context).extension()!.background + : null, + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), child: Expandable( onExpandChanged: (state) { setState(() { @@ -999,24 +1008,24 @@ class _WalletNetworkSettingsViewState width: _iconSize, height: _iconSize, decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, borderRadius: BorderRadius.circular(_iconSize), ), child: Center( child: SvgPicture.asset( Assets.svg.networkWired, width: 24, - color: Theme.of(context) - .extension()! - .textDark, + color: + Theme.of( + context, + ).extension()!.textDark, ), ), ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, @@ -1026,9 +1035,10 @@ class _WalletNetworkSettingsViewState style: STextStyles.desktopTextExtraExtraSmall( context, ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, + color: + Theme.of( + context, + ).extension()!.textDark, ), ), Text( @@ -1047,9 +1057,10 @@ class _WalletNetworkSettingsViewState : Assets.svg.chevronDown, width: 12, height: 6, - color: Theme.of(context) - .extension()! - .textSubtitle1, + color: + Theme.of( + context, + ).extension()!.textSubtitle1, ), ], ), diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart index 68436c634..4d88a4d91 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_view.dart @@ -190,410 +190,420 @@ class _WalletSettingsViewState extends ConsumerState { ), title: Text("Settings", style: STextStyles.navBarTitle(context)), ), - body: LayoutBuilder( - builder: (builderContext, constraints) { - return Padding( - padding: const EdgeInsets.only(left: 12, top: 12, right: 12), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( - padding: const EdgeInsets.all(4), - child: Column( - children: [ - SettingsListButton( - iconAssetName: Assets.svg.addressBook, - iconSize: 16, - title: "Address book", - onPressed: () { - Navigator.of(context).pushNamed( - AddressBookView.routeName, - arguments: coin, - ); - }, - ), - if (coin is FrostCurrency) + body: SafeArea( + child: LayoutBuilder( + builder: (builderContext, constraints) { + return Padding( + padding: const EdgeInsets.only(left: 12, top: 12, right: 12), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedWhiteContainer( + padding: const EdgeInsets.all(4), + child: Column( + children: [ + SettingsListButton( + iconAssetName: Assets.svg.addressBook, + iconSize: 16, + title: "Address book", + onPressed: () { + Navigator.of(context).pushNamed( + AddressBookView.routeName, + arguments: coin, + ); + }, + ), + if (coin is FrostCurrency) + const SizedBox(height: 8), + if (coin is FrostCurrency) + SettingsListButton( + iconAssetName: Assets.svg.addressBook2, + iconSize: 16, + title: "FROST Multisig settings", + onPressed: () { + Navigator.of(context).pushNamed( + FrostMSWalletOptionsView.routeName, + arguments: walletId, + ); + }, + ), const SizedBox(height: 8), - if (coin is FrostCurrency) SettingsListButton( - iconAssetName: Assets.svg.addressBook2, + iconAssetName: Assets.svg.node, iconSize: 16, - title: "FROST Multisig settings", + title: "Network", onPressed: () { Navigator.of(context).pushNamed( - FrostMSWalletOptionsView.routeName, - arguments: walletId, + WalletNetworkSettingsView.routeName, + arguments: Tuple3( + walletId, + _currentSyncStatus, + widget.initialNodeStatus, + ), ); }, ), - const SizedBox(height: 8), - SettingsListButton( - iconAssetName: Assets.svg.node, - iconSize: 16, - title: "Network", - onPressed: () { - Navigator.of(context).pushNamed( - WalletNetworkSettingsView.routeName, - arguments: Tuple3( - walletId, - _currentSyncStatus, - widget.initialNodeStatus, - ), - ); - }, - ), - if (canBackup) const SizedBox(height: 8), - if (canBackup) - Consumer( - builder: (_, ref, __) { - return SettingsListButton( - iconAssetName: Assets.svg.lock, - iconSize: 16, - title: "Wallet backup", - onPressed: () async { - // TODO: [prio=med] take wallets that don't have a mnemonic into account - - List? mnemonic; - ({ - String myName, - String config, - String keys, - ({String config, String keys})? - prevGen, - })? - frostWalletData; - if (wallet is BitcoinFrostWallet) { - final futures = [ - wallet.getSerializedKeys(), - wallet.getMultisigConfig(), - wallet.getSerializedKeysPrevGen(), - wallet.getMultisigConfigPrevGen(), - ]; - - final results = await Future.wait( - futures, - ); + if (canBackup) const SizedBox(height: 8), + if (canBackup) + Consumer( + builder: (_, ref, __) { + return SettingsListButton( + iconAssetName: Assets.svg.lock, + iconSize: 16, + title: "Wallet backup", + onPressed: () async { + // TODO: [prio=med] take wallets that don't have a mnemonic into account + + List? mnemonic; + ({ + String myName, + String config, + String keys, + ({String config, String keys})? + prevGen, + })? + frostWalletData; + if (wallet is BitcoinFrostWallet) { + final futures = [ + wallet.getSerializedKeys(), + wallet.getMultisigConfig(), + wallet + .getSerializedKeysPrevGen(), + wallet + .getMultisigConfigPrevGen(), + ]; - if (results.length == 4) { - frostWalletData = ( - myName: wallet.frostInfo.myName, - config: results[1]!, - keys: results[0]!, - prevGen: - results[2] == null || - results[3] == null - ? null - : ( - config: results[3]!, - keys: results[2]!, - ), + final results = await Future.wait( + futures, ); - } - } else { - if (wallet is MnemonicInterface) { - if (wallet - is ViewOnlyOptionInterface && - (wallet as ViewOnlyOptionInterface) - .isViewOnly) { - // TODO: is something needed here? - } else { - mnemonic = - await wallet - .getMnemonicAsWords(); + + if (results.length == 4) { + frostWalletData = ( + myName: + wallet.frostInfo.myName, + config: results[1]!, + keys: results[0]!, + prevGen: + results[2] == null || + results[3] == null + ? null + : ( + config: results[3]!, + keys: results[2]!, + ), + ); + } + } else { + if (wallet is MnemonicInterface) { + if (wallet + is ViewOnlyOptionInterface && + (wallet as ViewOnlyOptionInterface) + .isViewOnly) { + // TODO: is something needed here? + } else { + mnemonic = + await wallet + .getMnemonicAsWords(); + } } } - } - - KeyDataInterface? keyData; - if (wallet - is ViewOnlyOptionInterface && - wallet.isViewOnly) { - keyData = - await wallet - .getViewOnlyWalletData(); - } else if (wallet - is ExtendedKeysInterface) { - keyData = await wallet.getXPrivs(); - } else if (wallet - is LibMoneroWallet) { - keyData = await wallet.getKeys(); - } - - if (context.mounted) { - if (keyData != null && - wallet + + KeyDataInterface? keyData; + if (wallet is ViewOnlyOptionInterface && wallet.isViewOnly) { - await Navigator.push( - context, - RouteGenerator.getRoute( - shouldUseMaterialRoute: - RouteGenerator - .useMaterialPageRoute, - builder: - (_) => LockscreenView( - routeOnSuccessArguments: - ( - walletId: - walletId, - keyData: keyData, - ), - showBackButton: true, - routeOnSuccess: - MobileKeyDataView - .routeName, - biometricsCancelButtonString: - "CANCEL", - biometricsLocalizedReason: - "Authenticate to view recovery data", - biometricsAuthenticationTitle: - "View recovery data", - ), - settings: const RouteSettings( - name: - "/viewRecoveryDataLockscreen", + keyData = + await wallet + .getViewOnlyWalletData(); + } else if (wallet + is ExtendedKeysInterface) { + keyData = + await wallet.getXPrivs(); + } else if (wallet + is LibMoneroWallet) { + keyData = await wallet.getKeys(); + } + + if (context.mounted) { + if (keyData != null && + wallet + is ViewOnlyOptionInterface && + wallet.isViewOnly) { + await Navigator.push( + context, + RouteGenerator.getRoute( + shouldUseMaterialRoute: + RouteGenerator + .useMaterialPageRoute, + builder: + (_) => LockscreenView( + routeOnSuccessArguments: + ( + walletId: + walletId, + keyData: + keyData, + ), + showBackButton: true, + routeOnSuccess: + MobileKeyDataView + .routeName, + biometricsCancelButtonString: + "CANCEL", + biometricsLocalizedReason: + "Authenticate to view recovery data", + biometricsAuthenticationTitle: + "View recovery data", + ), + settings: const RouteSettings( + name: + "/viewRecoveryDataLockscreen", + ), ), - ), - ); - } else { - await Navigator.push( - context, - RouteGenerator.getRoute( - shouldUseMaterialRoute: - RouteGenerator - .useMaterialPageRoute, - builder: - (_) => LockscreenView( - routeOnSuccessArguments: ( - walletId: walletId, - mnemonic: - mnemonic ?? [], - frostWalletData: - frostWalletData, - keyData: keyData, + ); + } else { + await Navigator.push( + context, + RouteGenerator.getRoute( + shouldUseMaterialRoute: + RouteGenerator + .useMaterialPageRoute, + builder: + (_) => LockscreenView( + routeOnSuccessArguments: ( + walletId: walletId, + mnemonic: + mnemonic ?? [], + frostWalletData: + frostWalletData, + keyData: keyData, + ), + showBackButton: true, + routeOnSuccess: + WalletBackupView + .routeName, + biometricsCancelButtonString: + "CANCEL", + biometricsLocalizedReason: + "Authenticate to view recovery phrase", + biometricsAuthenticationTitle: + "View recovery phrase", ), - showBackButton: true, - routeOnSuccess: - WalletBackupView - .routeName, - biometricsCancelButtonString: - "CANCEL", - biometricsLocalizedReason: - "Authenticate to view recovery phrase", - biometricsAuthenticationTitle: - "View recovery phrase", - ), - settings: const RouteSettings( - name: - "/viewRecoverPhraseLockscreen", + settings: const RouteSettings( + name: + "/viewRecoverPhraseLockscreen", + ), ), - ), - ); + ); + } } - } - }, + }, + ); + }, + ), + const SizedBox(height: 8), + SettingsListButton( + iconAssetName: Assets.svg.downloadFolder, + title: "Wallet settings", + iconSize: 16, + onPressed: () { + Navigator.of(context).pushNamed( + WalletSettingsWalletSettingsView + .routeName, + arguments: walletId, ); }, ), - const SizedBox(height: 8), - SettingsListButton( - iconAssetName: Assets.svg.downloadFolder, - title: "Wallet settings", - iconSize: 16, - onPressed: () { - Navigator.of(context).pushNamed( - WalletSettingsWalletSettingsView - .routeName, - arguments: walletId, - ); - }, - ), - const SizedBox(height: 8), - SettingsListButton( - iconAssetName: Assets.svg.arrowRotate, - title: "Syncing preferences", - onPressed: () { - Navigator.of(context).pushNamed( - SyncingPreferencesView.routeName, - ); - }, - ), - if (xPubEnabled) const SizedBox(height: 8), - if (xPubEnabled) - Consumer( - builder: (_, ref, __) { - return SettingsListButton( - iconAssetName: Assets.svg.eye, - title: "Wallet xPub", - onPressed: () async { - final xpubData = await showLoading( - delay: const Duration( - milliseconds: 800, - ), - whileFuture: - (ref - .read(pWallets) - .getWallet(walletId) - as ExtendedKeysInterface) - .getXPubs(), - context: context, - message: "Loading xpubs", - rootNavigator: Util.isDesktop, - ); - if (context.mounted) { - await Navigator.of( - context, - ).pushNamed( - XPubView.routeName, - arguments: ( - widget.walletId, - xpubData, - ), - ); - } - }, + const SizedBox(height: 8), + SettingsListButton( + iconAssetName: Assets.svg.arrowRotate, + title: "Syncing preferences", + onPressed: () { + Navigator.of(context).pushNamed( + SyncingPreferencesView.routeName, ); }, ), - if (coin is Firo) const SizedBox(height: 8), - if (coin is Firo) - Consumer( - builder: (_, ref, __) { - return SettingsListButton( - iconAssetName: Assets.svg.eye, - title: "Clear electrumx cache", - onPressed: () async { - String? result; - await showDialog( - useSafeArea: false, - barrierDismissible: true, - context: context, - builder: - (_) => StackOkDialog( - title: - "Are you sure you want to clear " - "${coin.prettyName} electrumx cache?", - onOkPressed: (value) { - result = value; - }, - leftButton: SecondaryButton( - label: "Cancel", - onPressed: () { - Navigator.of( - context, - ).pop(); - }, - ), + if (xPubEnabled) const SizedBox(height: 8), + if (xPubEnabled) + Consumer( + builder: (_, ref, __) { + return SettingsListButton( + iconAssetName: Assets.svg.eye, + title: "Wallet xPub", + onPressed: () async { + final xpubData = await showLoading( + delay: const Duration( + milliseconds: 800, + ), + whileFuture: + (ref + .read(pWallets) + .getWallet( + walletId, + ) + as ExtendedKeysInterface) + .getXPubs(), + context: context, + message: "Loading xpubs", + rootNavigator: Util.isDesktop, + ); + if (context.mounted) { + await Navigator.of( + context, + ).pushNamed( + XPubView.routeName, + arguments: ( + widget.walletId, + xpubData, ), - ); - - if (result == "OK" && - context.mounted) { - await showLoading( - whileFuture: Future.wait([ - Future.delayed( - const Duration( - milliseconds: 1500, + ); + } + }, + ); + }, + ), + if (coin is Firo) const SizedBox(height: 8), + if (coin is Firo) + Consumer( + builder: (_, ref, __) { + return SettingsListButton( + iconAssetName: Assets.svg.eye, + title: "Clear electrumx cache", + onPressed: () async { + String? result; + await showDialog( + useSafeArea: false, + barrierDismissible: true, + context: context, + builder: + (_) => StackOkDialog( + title: + "Are you sure you want to clear " + "${coin.prettyName} electrumx cache?", + onOkPressed: (value) { + result = value; + }, + leftButton: SecondaryButton( + label: "Cancel", + onPressed: () { + Navigator.of( + context, + ).pop(); + }, + ), ), - ), - DB.instance - .clearSharedTransactionCache( - currency: coin, + ); + + if (result == "OK" && + context.mounted) { + await showLoading( + whileFuture: Future.wait([ + Future.delayed( + const Duration( + milliseconds: 1500, ), - if (coin is Firo) - FiroCacheCoordinator.clearSharedCache( - coin.network, ), - ]), - context: context, - message: "Clearing cache...", + DB.instance + .clearSharedTransactionCache( + currency: coin, + ), + if (coin is Firo) + FiroCacheCoordinator.clearSharedCache( + coin.network, + ), + ]), + context: context, + message: "Clearing cache...", + ); + } + }, + ); + }, + ), + if (coin is NanoCurrency) + const SizedBox(height: 8), + if (coin is NanoCurrency) + Consumer( + builder: (_, ref, __) { + return SettingsListButton( + iconAssetName: Assets.svg.eye, + title: "Change representative", + onPressed: () { + Navigator.of(context).pushNamed( + ChangeRepresentativeView + .routeName, + arguments: widget.walletId, ); - } - }, - ); - }, - ), - if (coin is NanoCurrency) - const SizedBox(height: 8), - if (coin is NanoCurrency) - Consumer( - builder: (_, ref, __) { - return SettingsListButton( - iconAssetName: Assets.svg.eye, - title: "Change representative", - onPressed: () { - Navigator.of(context).pushNamed( - ChangeRepresentativeView.routeName, - arguments: widget.walletId, - ); - }, - ); - }, - ), - // const SizedBox( - // height: 8, - // ), - // SettingsListButton( - // iconAssetName: Assets.svg.ellipsis, - // title: "Debug Info", - // onPressed: () { - // Navigator.of(context) - // .pushNamed(DebugView.routeName); - // }, - // ), - ], + }, + ); + }, + ), + // const SizedBox( + // height: 8, + // ), + // SettingsListButton( + // iconAssetName: Assets.svg.ellipsis, + // title: "Debug Info", + // onPressed: () { + // Navigator.of(context) + // .pushNamed(DebugView.routeName); + // }, + // ), + ], + ), ), - ), - const SizedBox(height: 12), - const Spacer(), - Consumer( - builder: (_, ref, __) { - return TextButton( - onPressed: () { - // TODO: [prio=med] needs more thought if this is still required - // ref - // .read(pWallets) - // .getWallet(walletId) - // .isActiveWallet = false; - ref - .read(transactionFilterProvider.state) - .state = null; - - Navigator.of(context).popUntil( - ModalRoute.withName(HomeView.routeName), - ); - }, - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - child: Text( - "Log out", - style: STextStyles.button(context).copyWith( - color: - Theme.of(context) - .extension()! - .accentColorDark, + const SizedBox(height: 12), + const Spacer(), + Consumer( + builder: (_, ref, __) { + return TextButton( + onPressed: () { + // TODO: [prio=med] needs more thought if this is still required + // ref + // .read(pWallets) + // .getWallet(walletId) + // .isActiveWallet = false; + ref + .read(transactionFilterProvider.state) + .state = null; + + Navigator.of(context).popUntil( + ModalRoute.withName(HomeView.routeName), + ); + }, + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle(context), + child: Text( + "Log out", + style: STextStyles.button(context).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorDark, + ), ), - ), - ); - }, - ), - ], + ); + }, + ), + ], + ), ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ); diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/change_representative_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/change_representative_view.dart index cfca56bf2..af3f9123e 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/change_representative_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/change_representative_view.dart @@ -128,8 +128,9 @@ class _ChangeRepresentativeViewState } Future _copy() async { - await _clipboardInterface - .setData(ClipboardData(text: representative ?? "")); + await _clipboardInterface.setData( + ClipboardData(text: representative ?? ""), + ); if (mounted) { unawaited( showFloatingFlushBar( @@ -146,107 +147,99 @@ class _ChangeRepresentativeViewState Widget build(BuildContext context) { return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: SafeArea( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () async { - Navigator.of(context).pop(); - }, - ), - title: Text( - "Wallet representative", - style: STextStyles.navBarTitle(context), - ), - actions: [ - Padding( - padding: const EdgeInsets.all(10), - child: AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - color: Theme.of(context) - .extension()! - .background, - shadows: const [], - icon: SvgPicture.asset( - Assets.svg.copy, - width: 24, - height: 24, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () async { + Navigator.of(context).pop(); + }, + ), + title: Text( + "Wallet representative", + style: STextStyles.navBarTitle(context), + ), + actions: [ + Padding( + padding: const EdgeInsets.all(10), + child: AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + color: + Theme.of( + context, + ).extension()!.background, + shadows: const [], + icon: SvgPicture.asset( + Assets.svg.copy, + width: 24, + height: 24, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, + ), + onPressed: () { + if (representative != null) { + _copy(); + } + }, ), - onPressed: () { - if (representative != null) { - _copy(); - } - }, ), ), + ], + ), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only(top: 12, left: 16, right: 16), + child: child, ), - ], - ), - body: Padding( - padding: const EdgeInsets.only( - top: 12, - left: 16, - right: 16, ), - child: child, ), ), - ), - ), child: ConditionalParent( condition: isDesktop, - builder: (child) => DesktopDialog( - maxWidth: 600, - maxHeight: double.infinity, - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + builder: + (child) => DesktopDialog( + maxWidth: 600, + maxHeight: double.infinity, + child: Column( children: [ - Padding( - padding: const EdgeInsets.only( - left: 32, - ), - child: Text( - "Change representative", - style: STextStyles.desktopH2(context), - ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "Change representative", + style: STextStyles.desktopH2(context), + ), + ), + DesktopDialogCloseButton( + onPressedOverride: + Navigator.of(context, rootNavigator: true).pop, + ), + ], ), - DesktopDialogCloseButton( - onPressedOverride: Navigator.of( - context, - rootNavigator: true, - ).pop, + AnimatedSize( + duration: const Duration(milliseconds: 150), + child: Padding( + padding: const EdgeInsets.fromLTRB(32, 0, 32, 32), + child: child, + ), ), ], ), - AnimatedSize( - duration: const Duration( - milliseconds: 150, - ), - child: Padding( - padding: const EdgeInsets.fromLTRB(32, 0, 32, 32), - child: child, - ), - ), - ], - ), - ), + ), child: Column( children: [ if (isDesktop) const SizedBox(height: 24), ConditionalParent( condition: !isDesktop, - builder: (child) => Expanded( - child: child, - ), + builder: (child) => Expanded(child: child), child: FutureBuilder( future: loadRepresentative(), builder: (context, AsyncSnapshot snapshot) { @@ -261,63 +254,54 @@ class _ChangeRepresentativeViewState child = const SizedBox( key: Key("loadingRepresentative"), height: height, - child: Center( - child: LoadingIndicator( - width: 100, - ), - ), + child: Center(child: LoadingIndicator(width: 100)), ); } else { child = Column( children: [ ConditionalParent( condition: !isDesktop, - builder: (child) => RoundedWhiteContainer( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - child, - ], - ), - ), + builder: + (child) => RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [child], + ), + ), child: ConditionalParent( condition: isDesktop, - builder: (child) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Current representative", - style: STextStyles.desktopTextExtraExtraSmall( - context, - ), - ), - const SizedBox( - height: 4, - ), - Row( + builder: + (child) => Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - child, + Text( + "Current representative", + style: + STextStyles.desktopTextExtraExtraSmall( + context, + ), + ), + const SizedBox(height: 4), + Row(children: [child]), ], ), - ], - ), child: SelectableText( representative!, - style: isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ) - : STextStyles.itemSubtitle12(context), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textDark, + ) + : STextStyles.itemSubtitle12(context), ), ), ), - const SizedBox( - height: 24, - ), + const SizedBox(height: 24), ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -326,15 +310,18 @@ class _ChangeRepresentativeViewState autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, controller: _textController, - style: isDesktop - ? STextStyles.desktopTextExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, - height: 1.8, - ) - : STextStyles.field(context), + style: + isDesktop + ? STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveText, + height: 1.8, + ) + : STextStyles.field(context), focusNode: _textFocusNode, decoration: standardInputDecoration( "Enter new representative", @@ -342,54 +329,50 @@ class _ChangeRepresentativeViewState context, desktopMed: isDesktop, ).copyWith( - contentPadding: isDesktop - ? const EdgeInsets.only( - left: 16, - top: 11, - bottom: 12, - right: 5, - ) - : null, - suffixIcon: _textController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _textController.text = ""; - }); - }, - ), - ], + contentPadding: + isDesktop + ? const EdgeInsets.only( + left: 16, + top: 11, + bottom: 12, + right: 5, + ) + : null, + suffixIcon: + _textController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only( + right: 0, ), - ), - ) - : null, + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _textController.text = ""; + }); + }, + ), + ], + ), + ), + ) + : null, ), ), ), if (isDesktop) const SizedBox(height: 60), if (!isDesktop) const Spacer(), - PrimaryButton( - label: "Save", - onPressed: _save, - ), - if (!isDesktop) - const SizedBox( - height: 16, - ), + PrimaryButton(label: "Save", onPressed: _save), + if (!isDesktop) const SizedBox(height: 16), ], ); } return AnimatedSwitcher( - duration: const Duration( - milliseconds: 200, - ), + duration: const Duration(milliseconds: 200), child: child, ); }, diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/delete_wallet_recovery_phrase_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/delete_wallet_recovery_phrase_view.dart index 16c48cbb6..03ba8cdf0 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/delete_wallet_recovery_phrase_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/delete_wallet_recovery_phrase_view.dart @@ -55,7 +55,8 @@ class DeleteWalletRecoveryPhraseView extends ConsumerStatefulWidget { String config, String keys, ({String config, String keys})? prevGen, - })? frostWalletData; + })? + frostWalletData; final ClipboardInterface clipboardInterface; @@ -79,45 +80,47 @@ class _DeleteWalletRecoveryPhraseViewState showDialog( barrierDismissible: true, context: context, - builder: (_) => StackDialog( - title: "Thanks! Your wallet will be deleted.", - leftButton: TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - onPressed: () { - Navigator.pop(context); - }, - child: Text( - "Cancel", - style: STextStyles.button(context).copyWith( - color: - Theme.of(context).extension()!.accentColorDark, + builder: + (_) => StackDialog( + title: "Thanks! Your wallet will be deleted.", + leftButton: TextButton( + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle(context), + onPressed: () { + Navigator.pop(context); + }, + child: Text( + "Cancel", + style: STextStyles.button(context).copyWith( + color: + Theme.of( + context, + ).extension()!.accentColorDark, + ), + ), ), - ), - ), - rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - onPressed: () async { - await ref.read(pWallets).deleteWallet( - ref.read(pWalletInfo(widget.walletId)), - ref.read(secureStoreProvider), - ); + rightButton: TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + onPressed: () async { + await ref + .read(pWallets) + .deleteWallet( + ref.read(pWalletInfo(widget.walletId)), + ref.read(secureStoreProvider), + ); - if (mounted) { - Navigator.of(context).popUntil( - ModalRoute.withName(HomeView.routeName), - ); - } - }, - child: Text( - "Ok", - style: STextStyles.button(context), + if (mounted) { + Navigator.of( + context, + ).popUntil(ModalRoute.withName(HomeView.routeName)); + } + }, + child: Text("Ok", style: STextStyles.button(context)), + ), ), - ), - ), ); } finally { _lock = false; @@ -159,13 +162,15 @@ class _DeleteWalletRecoveryPhraseViewState Assets.svg.copy, width: 20, height: 20, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, ), onPressed: () async { - await _clipboardInterface - .setData(ClipboardData(text: _mnemonic.join(" "))); + await _clipboardInterface.setData( + ClipboardData(text: _mnemonic.join(" ")), + ); if (context.mounted) { unawaited( showFloatingFlushBar( @@ -182,209 +187,218 @@ class _DeleteWalletRecoveryPhraseViewState ), ], ), - body: Padding( - padding: const EdgeInsets.all(16), - child: frost - ? LayoutBuilder( - builder: (builderContext, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( - child: Text( - "Please write down your backup data. Keep it safe and " - "never share it with anyone. " - "Your backup data is the only way you can access your " - "funds if you forget your PIN, lose your phone, etc." - "\n\n" - "${AppConfig.appName} does not keep nor is able to restore " - "your backup data. " - "Only you have access to your wallet.", - style: STextStyles.label(context), - ), - ), - const SizedBox( - height: 24, - ), - // DetailItem( - // title: "My name", - // detail: frostWalletData!.myName, - // button: Util.isDesktop - // ? IconCopyButton( - // data: frostWalletData!.myName, - // ) - // : SimpleCopyButton( - // data: frostWalletData!.myName, - // ), - // ), - // const SizedBox( - // height: 16, - // ), - DetailItem( - title: "Multisig config", - detail: widget.frostWalletData!.config, - button: Util.isDesktop - ? IconCopyButton( - data: widget.frostWalletData!.config, - ) - : SimpleCopyButton( - data: widget.frostWalletData!.config, - ), - ), - const SizedBox( - height: 16, - ), - DetailItem( - title: "Keys", - detail: widget.frostWalletData!.keys, - button: Util.isDesktop - ? IconCopyButton( - data: widget.frostWalletData!.keys, - ) - : SimpleCopyButton( - data: widget.frostWalletData!.keys, - ), - ), - if (prevGen) - const SizedBox( - height: 24, - ), - if (prevGen) - RoundedWhiteContainer( - child: Text( - "Previous generation info", - style: STextStyles.label(context), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: + frost + ? LayoutBuilder( + builder: (builderContext, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedWhiteContainer( + child: Text( + "Please write down your backup data. Keep it safe and " + "never share it with anyone. " + "Your backup data is the only way you can access your " + "funds if you forget your PIN, lose your phone, etc." + "\n\n" + "${AppConfig.appName} does not keep nor is able to restore " + "your backup data. " + "Only you have access to your wallet.", + style: STextStyles.label(context), + ), + ), + const SizedBox(height: 24), + // DetailItem( + // title: "My name", + // detail: frostWalletData!.myName, + // button: Util.isDesktop + // ? IconCopyButton( + // data: frostWalletData!.myName, + // ) + // : SimpleCopyButton( + // data: frostWalletData!.myName, + // ), + // ), + // const SizedBox( + // height: 16, + // ), + DetailItem( + title: "Multisig config", + detail: widget.frostWalletData!.config, + button: + Util.isDesktop + ? IconCopyButton( + data: + widget + .frostWalletData! + .config, + ) + : SimpleCopyButton( + data: + widget + .frostWalletData! + .config, + ), + ), + const SizedBox(height: 16), + DetailItem( + title: "Keys", + detail: widget.frostWalletData!.keys, + button: + Util.isDesktop + ? IconCopyButton( + data: + widget.frostWalletData!.keys, + ) + : SimpleCopyButton( + data: + widget.frostWalletData!.keys, + ), ), - ), - if (prevGen) - const SizedBox( - height: 12, - ), - if (prevGen) - DetailItem( - title: "Previous multisig config", - detail: - widget.frostWalletData!.prevGen!.config, - button: Util.isDesktop - ? IconCopyButton( - data: widget - .frostWalletData!.prevGen!.config, - ) - : SimpleCopyButton( - data: widget - .frostWalletData!.prevGen!.config, - ), - ), - if (prevGen) - const SizedBox( - height: 16, - ), - if (prevGen) - DetailItem( - title: "Previous keys", - detail: widget.frostWalletData!.prevGen!.keys, - button: Util.isDesktop - ? IconCopyButton( - data: widget - .frostWalletData!.prevGen!.keys, - ) - : SimpleCopyButton( - data: widget - .frostWalletData!.prevGen!.keys, - ), - ), + if (prevGen) const SizedBox(height: 24), + if (prevGen) + RoundedWhiteContainer( + child: Text( + "Previous generation info", + style: STextStyles.label(context), + ), + ), + if (prevGen) const SizedBox(height: 12), + if (prevGen) + DetailItem( + title: "Previous multisig config", + detail: + widget + .frostWalletData! + .prevGen! + .config, + button: + Util.isDesktop + ? IconCopyButton( + data: + widget + .frostWalletData! + .prevGen! + .config, + ) + : SimpleCopyButton( + data: + widget + .frostWalletData! + .prevGen! + .config, + ), + ), + if (prevGen) const SizedBox(height: 16), + if (prevGen) + DetailItem( + title: "Previous keys", + detail: + widget.frostWalletData!.prevGen!.keys, + button: + Util.isDesktop + ? IconCopyButton( + data: + widget + .frostWalletData! + .prevGen! + .keys, + ) + : SimpleCopyButton( + data: + widget + .frostWalletData! + .prevGen! + .keys, + ), + ), - const Spacer(), - const SizedBox( - height: 16, - ), - PrimaryButton( - label: "Continue", - onPressed: _continuePressed, + const Spacer(), + const SizedBox(height: 16), + PrimaryButton( + label: "Continue", + onPressed: _continuePressed, + ), + ], ), - ], + ), ), + ); + }, + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const SizedBox(height: 4), + Text( + ref.watch(pWalletName(widget.walletId)), + textAlign: TextAlign.center, + style: STextStyles.label( + context, + ).copyWith(fontSize: 12), ), - ), - ); - }, - ) - : Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const SizedBox( - height: 4, - ), - Text( - ref.watch(pWalletName(widget.walletId)), - textAlign: TextAlign.center, - style: STextStyles.label(context).copyWith( - fontSize: 12, - ), - ), - const SizedBox( - height: 4, - ), - Text( - "Recovery Phrase", - textAlign: TextAlign.center, - style: STextStyles.pageTitleH1(context), - ), - const SizedBox( - height: 16, - ), - Container( - decoration: BoxDecoration( - color: - Theme.of(context).extension()!.popupBG, - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + const SizedBox(height: 4), + Text( + "Recovery Phrase", + textAlign: TextAlign.center, + style: STextStyles.pageTitleH1(context), ), - ), - child: Padding( - padding: const EdgeInsets.all(12), - child: Text( - "Please write down your recovery phrase in the correct order and save it to keep your funds secure. You will also be asked to verify the words on the next screen.", - style: STextStyles.label(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + const SizedBox(height: 16), + Container( + decoration: BoxDecoration( + color: + Theme.of( + context, + ).extension()!.popupBG, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + child: Padding( + padding: const EdgeInsets.all(12), + child: Text( + "Please write down your recovery phrase in the correct order and save it to keep your funds secure. You will also be asked to verify the words on the next screen.", + style: STextStyles.label(context).copyWith( + color: + Theme.of( + context, + ).extension()!.accentColorDark, + ), + ), ), ), - ), - ), - const SizedBox( - height: 8, - ), - Expanded( - child: SingleChildScrollView( - child: MnemonicTable( - words: _mnemonic, - isDesktop: false, + const SizedBox(height: 8), + Expanded( + child: SingleChildScrollView( + child: MnemonicTable( + words: _mnemonic, + isDesktop: false, + ), + ), ), - ), - ), - const SizedBox( - height: 16, - ), - TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - onPressed: _continuePressed, - child: Text( - "Continue", - style: STextStyles.button(context), - ), + const SizedBox(height: 16), + TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + onPressed: _continuePressed, + child: Text( + "Continue", + style: STextStyles.button(context), + ), + ), + ], ), - ], - ), + ), ), ), ); diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/delete_wallet_warning_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/delete_wallet_warning_view.dart index 39a723d66..d6bc5f2e2 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/delete_wallet_warning_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/delete_wallet_warning_view.dart @@ -26,10 +26,7 @@ import 'delete_view_only_wallet_keys_view.dart'; import 'delete_wallet_recovery_phrase_view.dart'; class DeleteWalletWarningView extends ConsumerWidget { - const DeleteWalletWarningView({ - super.key, - required this.walletId, - }); + const DeleteWalletWarningView({super.key, required this.walletId}); static const String routeName = "/deleteWalletWarning"; @@ -47,143 +44,132 @@ class DeleteWalletWarningView extends ConsumerWidget { }, ), ), - body: Padding( - padding: const EdgeInsets.only( - top: 12, - left: 16, - right: 16, - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const SizedBox( - height: 32, - ), - Center( - child: Text( - "Attention!", - style: STextStyles.pageTitleH1(context), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only(top: 12, left: 16, right: 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const SizedBox(height: 32), + Center( + child: Text( + "Attention!", + style: STextStyles.pageTitleH1(context), + ), ), - ), - const SizedBox( - height: 16, - ), - RoundedContainer( - color: Theme.of(context) - .extension()! - .warningBackground, - child: Text( - "You are going to permanently delete your wallet.\n\n" - "If you delete your wallet, the only way you can have access" - " to your funds is by using your backup key.\n\n" - "${AppConfig.appName} does not keep nor is able to restore " - "your backup key or your wallet.\n\nPLEASE SAVE YOUR BACKUP KEY.", - style: STextStyles.baseXS(context).copyWith( - color: Theme.of(context) - .extension()! - .warningForeground, + const SizedBox(height: 16), + RoundedContainer( + color: + Theme.of( + context, + ).extension()!.warningBackground, + child: Text( + "You are going to permanently delete your wallet.\n\n" + "If you delete your wallet, the only way you can have access" + " to your funds is by using your backup key.\n\n" + "${AppConfig.appName} does not keep nor is able to restore " + "your backup key or your wallet.\n\nPLEASE SAVE YOUR BACKUP KEY.", + style: STextStyles.baseXS(context).copyWith( + color: + Theme.of( + context, + ).extension()!.warningForeground, + ), ), ), - ), - const Spacer(), - TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - onPressed: () { - Navigator.pop(context); - }, - child: Text( - "Cancel", - style: STextStyles.button(context).copyWith( - color: Theme.of(context) - .extension()! - .accentColorDark, + const Spacer(), + TextButton( + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle(context), + onPressed: () { + Navigator.pop(context); + }, + child: Text( + "Cancel", + style: STextStyles.button(context).copyWith( + color: + Theme.of( + context, + ).extension()!.accentColorDark, + ), ), ), - ), - const SizedBox( - height: 12, - ), - TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - onPressed: () async { - final wallet = ref.read(pWallets).getWallet(walletId); + const SizedBox(height: 12), + TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + onPressed: () async { + final wallet = ref.read(pWallets).getWallet(walletId); - // TODO: [prio=med] take wallets that don't have a mnemonic into account + // TODO: [prio=med] take wallets that don't have a mnemonic into account - List? mnemonic; - ({ - String myName, - String config, - String keys, - ({String config, String keys})? prevGen, - })? frostWalletData; - ViewOnlyWalletData? viewOnlyData; + List? mnemonic; + ({ + String myName, + String config, + String keys, + ({String config, String keys})? prevGen, + })? + frostWalletData; + ViewOnlyWalletData? viewOnlyData; - if (wallet is BitcoinFrostWallet) { - final futures = [ - wallet.getSerializedKeys(), - wallet.getMultisigConfig(), - wallet.getSerializedKeysPrevGen(), - wallet.getMultisigConfigPrevGen(), - ]; + if (wallet is BitcoinFrostWallet) { + final futures = [ + wallet.getSerializedKeys(), + wallet.getMultisigConfig(), + wallet.getSerializedKeysPrevGen(), + wallet.getMultisigConfigPrevGen(), + ]; - final results = await Future.wait(futures); + final results = await Future.wait(futures); - if (results.length == 4) { - frostWalletData = ( - myName: wallet.frostInfo.myName, - config: results[1]!, - keys: results[0]!, - prevGen: results[2] == null || results[3] == null - ? null - : ( - config: results[3]!, - keys: results[2]!, - ), - ); - } - } else { - if (wallet is ViewOnlyOptionInterface && - wallet.isViewOnly) { - viewOnlyData = await wallet.getViewOnlyWalletData(); - } else if (wallet is MnemonicInterface) { - mnemonic = await wallet.getMnemonicAsWords(); - } - } - if (context.mounted) { - if (viewOnlyData != null) { - await Navigator.of(context).pushNamed( - DeleteViewOnlyWalletKeysView.routeName, - arguments: ( - walletId: walletId, - data: viewOnlyData, - ), - ); + if (results.length == 4) { + frostWalletData = ( + myName: wallet.frostInfo.myName, + config: results[1]!, + keys: results[0]!, + prevGen: + results[2] == null || results[3] == null + ? null + : (config: results[3]!, keys: results[2]!), + ); + } } else { - await Navigator.of(context).pushNamed( - DeleteWalletRecoveryPhraseView.routeName, - arguments: ( - walletId: walletId, - mnemonicWords: mnemonic ?? [], - frostWalletData: frostWalletData, - ), - ); + if (wallet is ViewOnlyOptionInterface && + wallet.isViewOnly) { + viewOnlyData = await wallet.getViewOnlyWalletData(); + } else if (wallet is MnemonicInterface) { + mnemonic = await wallet.getMnemonicAsWords(); + } + } + if (context.mounted) { + if (viewOnlyData != null) { + await Navigator.of(context).pushNamed( + DeleteViewOnlyWalletKeysView.routeName, + arguments: (walletId: walletId, data: viewOnlyData), + ); + } else { + await Navigator.of(context).pushNamed( + DeleteWalletRecoveryPhraseView.routeName, + arguments: ( + walletId: walletId, + mnemonicWords: mnemonic ?? [], + frostWalletData: frostWalletData, + ), + ); + } } - } - }, - child: Text( - "View Backup Key", - style: STextStyles.button(context), + }, + child: Text( + "View Backup Key", + style: STextStyles.button(context), + ), ), - ), - const SizedBox( - height: 16, - ), - ], + const SizedBox(height: 16), + ], + ), ), ), ), diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/edit_refresh_height_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/edit_refresh_height_view.dart index 61d497452..f1d0aa5f9 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/edit_refresh_height_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/edit_refresh_height_view.dart @@ -22,10 +22,7 @@ import '../../../../widgets/stack_text_field.dart'; import '../../../../widgets/textfield_icon_button.dart'; class EditRefreshHeightView extends ConsumerStatefulWidget { - const EditRefreshHeightView({ - super.key, - required this.walletId, - }); + const EditRefreshHeightView({super.key, required this.walletId}); static const String routeName = "/editRefreshHeightView"; @@ -92,8 +89,10 @@ class _EditRefreshHeightViewState extends ConsumerState { void initState() { super.initState(); _wallet = ref.read(pWallets).getWallet(widget.walletId) as LibMoneroWallet; - _controller = TextEditingController() - ..text = _wallet.libMoneroWallet!.getRefreshFromBlockHeight().toString(); + _controller = + TextEditingController() + ..text = + _wallet.libMoneroWallet!.getRefreshFromBlockHeight().toString(); } @override @@ -119,10 +118,8 @@ class _EditRefreshHeightViewState extends ConsumerState { mainAxisAlignment: MainAxisAlignment.end, children: [ DesktopDialogCloseButton( - onPressedOverride: Navigator.of( - context, - rootNavigator: true, - ).pop, + onPressedOverride: + Navigator.of(context, rootNavigator: true).pop, ), ], ), @@ -130,9 +127,7 @@ class _EditRefreshHeightViewState extends ConsumerState { padding: const EdgeInsets.symmetric(horizontal: 32), child: child, ), - const SizedBox( - height: 32, - ), + const SizedBox(height: 32), ], ), ); @@ -155,9 +150,8 @@ class _EditRefreshHeightViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: child, + body: SafeArea( + child: Padding(padding: const EdgeInsets.all(16), child: child), ), ), ); @@ -173,11 +167,12 @@ class _EditRefreshHeightViewState extends ConsumerState { key: const Key("restoreHeightFieldKey"), controller: _controller, focusNode: _focusNode, - style: Util.isDesktop - ? STextStyles.desktopTextMedium(context).copyWith( - height: 2, - ) - : STextStyles.field(context), + style: + Util.isDesktop + ? STextStyles.desktopTextMedium( + context, + ).copyWith(height: 2) + : STextStyles.field(context), enableSuggestions: false, autocorrect: false, autofocus: true, @@ -188,48 +183,39 @@ class _EditRefreshHeightViewState extends ConsumerState { _focusNode, context, ).copyWith( - suffixIcon: _controller.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: ConditionalParent( - condition: Util.isDesktop, - builder: (child) => SizedBox( - height: 70, - child: child, - ), - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _controller.text = ""; - }); - }, - ), - ], + suffixIcon: + _controller.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: ConditionalParent( + condition: Util.isDesktop, + builder: + (child) => + SizedBox(height: 70, child: child), + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _controller.text = ""; + }); + }, + ), + ], + ), ), ), - ), - ) - : Util.isDesktop - ? const SizedBox( - height: 70, - ) + ) + : Util.isDesktop + ? const SizedBox(height: 70) : null, ), ), ), - Util.isDesktop - ? const SizedBox( - height: 32, - ) - : const Spacer(), - PrimaryButton( - label: "Save", - onPressed: _save, - ), + Util.isDesktop ? const SizedBox(height: 32) : const Spacer(), + PrimaryButton(label: "Save", onPressed: _save), ], ), ), diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/lelantus_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/lelantus_settings_view.dart index da8c328bf..accd91416 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/lelantus_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/lelantus_settings_view.dart @@ -31,10 +31,7 @@ import '../../../../widgets/desktop/secondary_button.dart'; import '../../../../widgets/stack_dialog.dart'; class LelantusSettingsView extends ConsumerStatefulWidget { - const LelantusSettingsView({ - super.key, - required this.walletId, - }); + const LelantusSettingsView({super.key, required this.walletId}); static const String routeName = "/lelantusSettings"; @@ -54,12 +51,12 @@ class _LelantusSettingsViewState extends ConsumerState { try { // Toggle enableLelantusScanning in wallet info. - await ref.read(pWalletInfo(widget.walletId)).updateOtherData( - newEntries: { - WalletInfoKeys.enableLelantusScanning: newValue, - }, - isar: ref.read(mainDBProvider).isar, - ); + await ref + .read(pWalletInfo(widget.walletId)) + .updateOtherData( + newEntries: {WalletInfoKeys.enableLelantusScanning: newValue}, + isar: ref.read(mainDBProvider).isar, + ); if (newValue) { await _doRescanMaybe(); } @@ -75,7 +72,8 @@ class _LelantusSettingsViewState extends ConsumerState { builder: (context) { return StackDialog( title: "Rescan may be required", - message: "A blockchain rescan may be required to fully recover all " + message: + "A blockchain rescan may be required to fully recover all " "lelantus history. This may take a while.", leftButton: SecondaryButton( label: "Rescan now", @@ -98,12 +96,14 @@ class _LelantusSettingsViewState extends ConsumerState { Exception? e; if (mounted) { await showLoading( - whileFuture: ref.read(pWallets).getWallet(widget.walletId).recover( - isRescan: true, - ), + whileFuture: ref + .read(pWallets) + .getWallet(widget.walletId) + .recover(isRescan: true), context: context, message: "Rescanning blockchain", - subMessage: "This may take a while." + subMessage: + "This may take a while." "\nPlease do not exit this screen.", rootNavigator: Util.isDesktop, onException: (ex) => e = ex, @@ -121,22 +121,26 @@ class _LelantusSettingsViewState extends ConsumerState { context: context, useSafeArea: false, barrierDismissible: true, - builder: (context) => StackDialog( - title: "Rescan failed", - message: e.toString(), - rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - child: Text( - "Ok", - style: STextStyles.itemSubtitle12(context), + builder: + (context) => StackDialog( + title: "Rescan failed", + message: e.toString(), + rightButton: TextButton( + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle(context), + child: Text( + "Ok", + style: STextStyles.itemSubtitle12(context), + ), + onPressed: () { + Navigator.of( + context, + rootNavigator: Util.isDesktop, + ).pop(); + }, + ), ), - onPressed: () { - Navigator.of(context, rootNavigator: Util.isDesktop).pop(); - }, - ), - ), ); } } finally { @@ -161,44 +165,47 @@ class _LelantusSettingsViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Row( - children: [ - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: ref.watch( - pWalletInfo(widget.walletId) - .select((value) => value.otherData), - )[WalletInfoKeys.enableLelantusScanning] as bool? ?? - false, - onValueChanged: _switchToggled, - ), - ), - const SizedBox( - width: 16, - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Scan for Lelantus transactions", - style: STextStyles.smallMed12(context), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Row( + children: [ + SizedBox( + height: 20, + width: 40, + child: DraggableSwitchButton( + isOn: + ref.watch( + pWalletInfo( + widget.walletId, + ).select((value) => value.otherData), + )[WalletInfoKeys.enableLelantusScanning] + as bool? ?? + false, + onValueChanged: _switchToggled, ), - // Text( - // detail, - // style: STextStyles.desktopTextExtraExtraSmall(context), - // ), - ], - ), - ], - ), - ], + ), + const SizedBox(width: 16), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Scan for Lelantus transactions", + style: STextStyles.smallMed12(context), + ), + // Text( + // detail, + // style: STextStyles.desktopTextExtraExtraSmall(context), + // ), + ], + ), + ], + ), + ], + ), ), ), ), diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/rbf_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/rbf_settings_view.dart index 088b33379..aefbe6e79 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/rbf_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/rbf_settings_view.dart @@ -11,10 +11,7 @@ import '../../../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../../../widgets/custom_buttons/draggable_switch_button.dart'; class RbfSettingsView extends ConsumerStatefulWidget { - const RbfSettingsView({ - super.key, - required this.walletId, - }); + const RbfSettingsView({super.key, required this.walletId}); static const String routeName = "/rbfSettings"; @@ -34,12 +31,12 @@ class _RbfSettingsViewState extends ConsumerState { try { // Toggle enableOptInRbf in wallet info. - await ref.read(pWalletInfo(widget.walletId)).updateOtherData( - newEntries: { - WalletInfoKeys.enableOptInRbf: newValue, - }, - isar: ref.read(mainDBProvider).isar, - ); + await ref + .read(pWalletInfo(widget.walletId)) + .updateOtherData( + newEntries: {WalletInfoKeys.enableOptInRbf: newValue}, + isar: ref.read(mainDBProvider).isar, + ); } finally { // ensure _switchRbfToggledLock is set to false no matter what _switchRbfToggledLock = false; @@ -57,46 +54,46 @@ class _RbfSettingsViewState extends ConsumerState { Navigator.of(context).pop(); }, ), - title: Text( - "RBF settings", - style: STextStyles.navBarTitle(context), - ), + title: Text("RBF settings", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Row( - children: [ - const SizedBox(width: 3), - SizedBox( - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: ref.watch( - pWalletInfo(widget.walletId) - .select((value) => value.otherData), - )[WalletInfoKeys.enableOptInRbf] as bool? ?? - false, - onValueChanged: _switchRbfToggled, - ), - ), - const SizedBox( - width: 16, - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Enable opt-in RBF", - style: STextStyles.w600_20(context), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Row( + children: [ + const SizedBox(width: 3), + SizedBox( + height: 20, + width: 40, + child: DraggableSwitchButton( + isOn: + ref.watch( + pWalletInfo( + widget.walletId, + ).select((value) => value.otherData), + )[WalletInfoKeys.enableOptInRbf] + as bool? ?? + false, + onValueChanged: _switchRbfToggled, ), - ], - ), - ], - ), - ], + ), + const SizedBox(width: 16), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Enable opt-in RBF", + style: STextStyles.w600_20(context), + ), + ], + ), + ], + ), + ], + ), ), ), ), diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/rename_wallet_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/rename_wallet_view.dart index 319cc067f..04991bbb3 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/rename_wallet_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/rename_wallet_view.dart @@ -12,6 +12,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; + import '../../../../notifications/show_flush_bar.dart'; import '../../../../providers/db/main_db_provider.dart'; import '../../../../themes/stack_colors.dart'; @@ -26,10 +27,7 @@ import '../../../../widgets/stack_text_field.dart'; import '../../../../widgets/textfield_icon_button.dart'; class RenameWalletView extends ConsumerStatefulWidget { - const RenameWalletView({ - super.key, - required this.walletId, - }); + const RenameWalletView({super.key, required this.walletId}); static const String routeName = "/renameWallet"; @@ -73,105 +71,104 @@ class _RenameWalletViewState extends ConsumerState { Navigator.of(context).pop(); }, ), - title: Text( - "Rename wallet", - style: STextStyles.navBarTitle(context), - ), + title: Text("Rename wallet", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - ClipRRect( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - child: TextField( - autocorrect: Util.isDesktop ? false : true, - enableSuggestions: Util.isDesktop ? false : true, - controller: _controller, - focusNode: _focusNode, - style: STextStyles.field(context), - onChanged: (_) => setState(() {}), - decoration: standardInputDecoration( - "Wallet name", - _focusNode, - context, - ).copyWith( - suffixIcon: _controller.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _controller.text = ""; - }); - }, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, + controller: _controller, + focusNode: _focusNode, + style: STextStyles.field(context), + onChanged: (_) => setState(() {}), + decoration: standardInputDecoration( + "Wallet name", + _focusNode, + context, + ).copyWith( + suffixIcon: + _controller.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _controller.text = ""; + }); + }, + ), + ], ), - ], - ), - ), - ) - : null, + ), + ) + : null, + ), ), ), - ), - const Spacer(), - TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - onPressed: () async { - final newName = _controller.text; + const Spacer(), + TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + onPressed: () async { + final newName = _controller.text; - String? errMessage; - try { - await ref.read(pWalletInfo(walletId)).updateName( - newName: newName, - isar: ref.read(mainDBProvider).isar, - ); - } catch (e) { - if (e - .toString() - .contains("Empty wallet name not allowed!")) { - errMessage = "Empty wallet name not allowed."; - } else { - errMessage = e.toString(); + String? errMessage; + try { + await ref + .read(pWalletInfo(walletId)) + .updateName( + newName: newName, + isar: ref.read(mainDBProvider).isar, + ); + } catch (e) { + if (e.toString().contains( + "Empty wallet name not allowed!", + )) { + errMessage = "Empty wallet name not allowed."; + } else { + errMessage = e.toString(); + } } - } - if (mounted) { - if (errMessage == null) { - Navigator.of(context).pop(); - unawaited( - showFloatingFlushBar( - type: FlushBarType.success, - message: "Wallet renamed", - context: context, - ), - ); - } else { - unawaited( - showFloatingFlushBar( - type: FlushBarType.warning, - message: "Wallet named \"$newName\" already exists", - context: context, - ), - ); + if (mounted) { + if (errMessage == null) { + Navigator.of(context).pop(); + unawaited( + showFloatingFlushBar( + type: FlushBarType.success, + message: "Wallet renamed", + context: context, + ), + ); + } else { + unawaited( + showFloatingFlushBar( + type: FlushBarType.warning, + message: "Wallet named \"$newName\" already exists", + context: context, + ), + ); + } } - } - }, - child: Text( - "Save", - style: STextStyles.button(context), + }, + child: Text("Save", style: STextStyles.button(context)), ), - ), - ], + ], + ), ), ), ), diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/spark_info.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/spark_info.dart index 934736311..99bd2f94c 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/spark_info.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/spark_info.dart @@ -10,10 +10,7 @@ import '../../../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../../../widgets/detail_item.dart'; class SparkInfoView extends ConsumerWidget { - const SparkInfoView({ - super.key, - required this.walletId, - }); + const SparkInfoView({super.key, required this.walletId}); static const String routeName = "/sparkInfo"; @@ -30,33 +27,32 @@ class SparkInfoView extends ConsumerWidget { Navigator.of(context).pop(); }, ), - title: Text( - "Spark Info", - style: STextStyles.navBarTitle(context), - ), + title: Text("Spark Info", style: STextStyles.navBarTitle(context)), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - FutureBuilder( - future: FiroCacheCoordinator.getSparkCacheSize( - ref.watch(pWalletCoin(walletId)).network, - ), - builder: (_, snapshot) { - String detail = "Loading..."; - if (snapshot.connectionState == ConnectionState.done) { - detail = snapshot.data ?? detail; - } + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + FutureBuilder( + future: FiroCacheCoordinator.getSparkCacheSize( + ref.watch(pWalletCoin(walletId)).network, + ), + builder: (_, snapshot) { + String detail = "Loading..."; + if (snapshot.connectionState == ConnectionState.done) { + detail = snapshot.data ?? detail; + } - return DetailItem( - title: "Spark electrumx cache size", - detail: detail, - ); - }, - ), - ], + return DetailItem( + title: "Spark electrumx cache size", + detail: detail, + ); + }, + ), + ], + ), ), ), ), diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart index 3917f743e..dc446fef6 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/wallet_settings_wallet_settings_view.dart @@ -180,49 +180,17 @@ class _WalletSettingsWalletSettingsViewState style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.only(top: 12, left: 16, right: 16), - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - onPressed: () { - Navigator.of(context).pushNamed( - RenameWalletView.routeName, - arguments: widget.walletId, - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - vertical: 20, - ), - child: Row( - children: [ - Text( - "Rename wallet", - style: STextStyles.titleBold12(context), - ), - ], - ), - ), - ), - ), - if (wallet is RbfInterface) const SizedBox(height: 8), - if (wallet is RbfInterface) + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only(top: 12, left: 16, right: 16), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ RoundedWhiteContainer( padding: const EdgeInsets.all(0), child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -231,7 +199,7 @@ class _WalletSettingsWalletSettingsViewState materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, onPressed: () { Navigator.of(context).pushNamed( - RbfSettingsView.routeName, + RenameWalletView.routeName, arguments: widget.walletId, ); }, @@ -243,7 +211,7 @@ class _WalletSettingsWalletSettingsViewState child: Row( children: [ Text( - "RBF settings", + "Rename wallet", style: STextStyles.titleBold12(context), ), ], @@ -251,186 +219,318 @@ class _WalletSettingsWalletSettingsViewState ), ), ), - if (wallet is MultiAddressInterface && !isViewOnlyNoAddressGen) - const SizedBox(height: 8), - if (wallet is MultiAddressInterface && !isViewOnlyNoAddressGen) - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + if (wallet is RbfInterface) const SizedBox(height: 8), + if (wallet is RbfInterface) + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + onPressed: () { + Navigator.of(context).pushNamed( + RbfSettingsView.routeName, + arguments: widget.walletId, + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12.0, + vertical: 20, + ), + child: Row( + children: [ + Text( + "RBF settings", + style: STextStyles.titleBold12(context), + ), + ], + ), ), ), - onPressed: _switchReuseAddressToggled, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - vertical: 20, + ), + if (wallet is MultiAddressInterface && + !isViewOnlyNoAddressGen) + const SizedBox(height: 8), + if (wallet is MultiAddressInterface && + !isViewOnlyNoAddressGen) + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Reuse receiving address", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - SizedBox( - height: 20, - width: 40, - child: IgnorePointer( - child: DraggableSwitchButton( - isOn: - ref.watch( - pWalletInfo(widget.walletId).select( - (value) => value.otherData, - ), - )[WalletInfoKeys.reuseAddress] - as bool? ?? - false, - controller: _switchController, + onPressed: _switchReuseAddressToggled, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12.0, + vertical: 20, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Reuse receiving address", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + SizedBox( + height: 20, + width: 40, + child: IgnorePointer( + child: DraggableSwitchButton( + isOn: + ref.watch( + pWalletInfo( + widget.walletId, + ).select( + (value) => value.otherData, + ), + )[WalletInfoKeys.reuseAddress] + as bool? ?? + false, + controller: _switchController, + ), ), ), - ), - ], + ], + ), ), ), ), - ), - if (!ref.watch(pDuress)) const SizedBox(height: 8), - if (!ref.watch(pDuress)) - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: _switchDuressToggled, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - vertical: 20, + if (!ref.watch(pDuress)) const SizedBox(height: 8), + if (!ref.watch(pDuress)) + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Show in duress", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - SizedBox( - height: 20, - width: 40, - child: IgnorePointer( - child: DraggableSwitch( - value: - ref.watch( - pWalletInfo(widget.walletId).select( - (value) => value.otherData, - ), - )[WalletInfoKeys - .duressMarkedVisibleWalletKey] - as bool? ?? - false, - onChanged: (_) => (), + onPressed: _switchDuressToggled, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12.0, + vertical: 20, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Show in duress", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + SizedBox( + height: 20, + width: 40, + child: IgnorePointer( + child: DraggableSwitch( + value: + ref.watch( + pWalletInfo( + widget.walletId, + ).select( + (value) => value.otherData, + ), + )[WalletInfoKeys + .duressMarkedVisibleWalletKey] + as bool? ?? + false, + onChanged: (_) => (), + ), ), ), - ), - ], + ], + ), ), ), ), - ), - if (wallet is LelantusInterface && !wallet.isViewOnly) - const SizedBox(height: 8), - if (wallet is LelantusInterface && !wallet.isViewOnly) - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - onPressed: () { - Navigator.of(context).pushNamed( - LelantusSettingsView.routeName, - arguments: widget.walletId, - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - vertical: 20, + if (wallet is LelantusInterface && !wallet.isViewOnly) + const SizedBox(height: 8), + if (wallet is LelantusInterface && !wallet.isViewOnly) + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - child: Row( - children: [ - Text( - "Lelantus settings", - style: STextStyles.titleBold12(context), - ), - ], + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + onPressed: () { + Navigator.of(context).pushNamed( + LelantusSettingsView.routeName, + arguments: widget.walletId, + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12.0, + vertical: 20, + ), + child: Row( + children: [ + Text( + "Lelantus settings", + style: STextStyles.titleBold12(context), + ), + ], + ), ), ), ), - ), - if (wallet is SparkInterface && !wallet.isViewOnly) - const SizedBox(height: 8), - if (wallet is SparkInterface && !wallet.isViewOnly) - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + if (wallet is SparkInterface && !wallet.isViewOnly) + const SizedBox(height: 8), + if (wallet is SparkInterface && !wallet.isViewOnly) + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + onPressed: () { + Navigator.of(context).pushNamed( + SparkInfoView.routeName, + arguments: widget.walletId, + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12.0, + vertical: 20, + ), + child: Row( + children: [ + Text( + "Spark info", + style: STextStyles.titleBold12(context), + ), + ], + ), ), ), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - onPressed: () { - Navigator.of(context).pushNamed( - SparkInfoView.routeName, - arguments: widget.walletId, - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - vertical: 20, + ), + if (wallet is LibMoneroWallet) const SizedBox(height: 8), + if (wallet is LibMoneroWallet) + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), ), - child: Row( - children: [ - Text( - "Spark info", - style: STextStyles.titleBold12(context), - ), - ], + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + onPressed: () { + Navigator.of(context).pushNamed( + EditRefreshHeightView.routeName, + arguments: widget.walletId, + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12.0, + vertical: 20, + ), + child: Row( + children: [ + Text( + "Restore height", + style: STextStyles.titleBold12(context), + ), + ], + ), ), ), ), - ), - if (wallet is LibMoneroWallet) const SizedBox(height: 8), - if (wallet is LibMoneroWallet) + const SizedBox(height: 8), RoundedWhiteContainer( padding: const EdgeInsets.all(0), child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), ), materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + padding: const EdgeInsets.all(0), onPressed: () { - Navigator.of(context).pushNamed( - EditRefreshHeightView.routeName, - arguments: widget.walletId, + showDialog( + barrierDismissible: true, + context: context, + builder: + (_) => StackDialog( + title: + "Do you want to delete ${ref.read(pWalletName(widget.walletId))}?", + leftButton: TextButton( + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonStyle(context), + onPressed: () { + Navigator.pop(context); + }, + child: Text( + "Cancel", + style: STextStyles.button(context).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorDark, + ), + ), + ), + rightButton: TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle(context), + onPressed: () { + Navigator.pop(context); + Navigator.push( + context, + RouteGenerator.getRoute( + shouldUseMaterialRoute: + RouteGenerator.useMaterialPageRoute, + builder: + (_) => LockscreenView( + routeOnSuccessArguments: + widget.walletId, + showBackButton: true, + routeOnSuccess: + DeleteWalletWarningView + .routeName, + biometricsCancelButtonString: + "CANCEL", + biometricsLocalizedReason: + "Authenticate to delete wallet", + biometricsAuthenticationTitle: + "Delete wallet", + ), + settings: const RouteSettings( + name: "/deleteWalletLockscreen", + ), + ), + ); + }, + child: Text( + "Delete", + style: STextStyles.button(context), + ), + ), + ), ); }, child: Padding( @@ -441,7 +541,7 @@ class _WalletSettingsWalletSettingsViewState child: Row( children: [ Text( - "Restore height", + "Delete wallet", style: STextStyles.titleBold12(context), ), ], @@ -449,100 +549,8 @@ class _WalletSettingsWalletSettingsViewState ), ), ), - const SizedBox(height: 8), - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - padding: const EdgeInsets.all(0), - onPressed: () { - showDialog( - barrierDismissible: true, - context: context, - builder: - (_) => StackDialog( - title: - "Do you want to delete ${ref.read(pWalletName(widget.walletId))}?", - leftButton: TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - onPressed: () { - Navigator.pop(context); - }, - child: Text( - "Cancel", - style: STextStyles.button(context).copyWith( - color: - Theme.of(context) - .extension()! - .accentColorDark, - ), - ), - ), - rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - onPressed: () { - Navigator.pop(context); - Navigator.push( - context, - RouteGenerator.getRoute( - shouldUseMaterialRoute: - RouteGenerator.useMaterialPageRoute, - builder: - (_) => LockscreenView( - routeOnSuccessArguments: - widget.walletId, - showBackButton: true, - routeOnSuccess: - DeleteWalletWarningView - .routeName, - biometricsCancelButtonString: - "CANCEL", - biometricsLocalizedReason: - "Authenticate to delete wallet", - biometricsAuthenticationTitle: - "Delete wallet", - ), - settings: const RouteSettings( - name: "/deleteWalletLockscreen", - ), - ), - ); - }, - child: Text( - "Delete", - style: STextStyles.button(context), - ), - ), - ), - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12.0, - vertical: 20, - ), - child: Row( - children: [ - Text( - "Delete wallet", - style: STextStyles.titleBold12(context), - ), - ], - ), - ), - ), - ), - ], + ], + ), ), ), ), diff --git a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/xpub_view.dart b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/xpub_view.dart index 2eddd3078..35a46d6b4 100644 --- a/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/xpub_view.dart +++ b/lib/pages/settings_views/wallet_settings_view/wallet_settings_wallet_settings/xpub_view.dart @@ -87,115 +87,106 @@ class XPubViewState extends ConsumerState { return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () async { - Navigator.of(context).pop(); - }, - ), - title: Text( - "Wallet xpub(s)", - style: STextStyles.navBarTitle(context), - ), - ), - body: Padding( - padding: const EdgeInsets.only( - top: 12, - left: 16, - right: 16, - ), - child: LayoutBuilder( - builder: (context, constraints) => SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints(minHeight: constraints.maxHeight), - child: IntrinsicHeight( - child: Column( - children: [ - Expanded( - child: child, - ), - const SizedBox( - height: 16, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () async { + Navigator.of(context).pop(); + }, + ), + title: Text( + "Wallet xpub(s)", + style: STextStyles.navBarTitle(context), + ), + ), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only(top: 12, left: 16, right: 16), + child: LayoutBuilder( + builder: + (context, constraints) => SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Column( + children: [ + Expanded(child: child), + const SizedBox(height: 16), + ], + ), + ), + ), ), - ], - ), ), ), ), ), ), - ), - ), child: ConditionalParent( condition: isDesktop, - builder: (child) => DesktopDialog( - maxWidth: 600, - maxHeight: double.infinity, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + builder: + (child) => DesktopDialog( + maxWidth: 600, + maxHeight: double.infinity, + child: Column( + mainAxisSize: MainAxisSize.min, children: [ - Padding( - padding: const EdgeInsets.only( - left: 32, - ), - child: Text( - "${ref.watch(pWalletName(widget.walletId))} xpub(s)", - style: STextStyles.desktopH2(context), - ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.only(left: 32), + child: Text( + "${ref.watch(pWalletName(widget.walletId))} xpub(s)", + style: STextStyles.desktopH2(context), + ), + ), + DesktopDialogCloseButton( + onPressedOverride: + Navigator.of(context, rootNavigator: true).pop, + ), + ], ), - DesktopDialogCloseButton( - onPressedOverride: Navigator.of( - context, - rootNavigator: true, - ).pop, + Flexible( + child: Padding( + padding: const EdgeInsets.fromLTRB(32, 0, 32, 32), + child: SingleChildScrollView(child: child), + ), ), ], ), - Flexible( - child: Padding( - padding: const EdgeInsets.fromLTRB(32, 0, 32, 32), - child: SingleChildScrollView( - child: child, - ), - ), - ), - ], - ), - ), + ), child: Column( mainAxisSize: Util.isDesktop ? MainAxisSize.min : MainAxisSize.max, crossAxisAlignment: CrossAxisAlignment.center, children: [ - SizedBox( - height: Util.isDesktop ? 12 : 16, - ), + SizedBox(height: Util.isDesktop ? 12 : 16), DetailItem( title: "Master fingerprint", detail: widget.xpubData.fingerprint, horizontal: true, - borderColor: Util.isDesktop - ? Theme.of(context) - .extension()! - .textFieldDefaultBG - : null, - ), - SizedBox( - height: Util.isDesktop ? 12 : 16, + borderColor: + Util.isDesktop + ? Theme.of( + context, + ).extension()!.textFieldDefaultBG + : null, ), + SizedBox(height: Util.isDesktop ? 12 : 16), DetailItemBase( horizontal: true, - borderColor: Util.isDesktop - ? Theme.of(context) - .extension()! - .textFieldDefaultBG - : null, + borderColor: + Util.isDesktop + ? Theme.of( + context, + ).extension()!.textFieldDefaultBG + : null, title: Text( "Derivation", style: STextStyles.itemSubtitle(context), @@ -226,9 +217,10 @@ class XPubViewState extends ConsumerState { isExpanded: true, buttonStyleData: ButtonStyleData( decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), @@ -241,9 +233,10 @@ class XPubViewState extends ConsumerState { Assets.svg.chevronDown, width: 12, height: 6, - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconRight, + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconRight, ), ), ), @@ -251,9 +244,10 @@ class XPubViewState extends ConsumerState { offset: const Offset(0, -10), elevation: 0, decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, ), @@ -269,46 +263,34 @@ class XPubViewState extends ConsumerState { ), ), ), - SizedBox( - height: Util.isDesktop ? 12 : 16, - ), + SizedBox(height: Util.isDesktop ? 12 : 16), QR( data: _current(_currentDropDownValue), - size: Util.isDesktop - ? 256 - : MediaQuery.of(context).size.width / 1.5, - ), - SizedBox( - height: Util.isDesktop ? 12 : 16, + size: + Util.isDesktop + ? 256 + : MediaQuery.of(context).size.width / 1.5, ), + SizedBox(height: Util.isDesktop ? 12 : 16), RoundedWhiteContainer( - borderColor: Util.isDesktop - ? Theme.of(context) - .extension()! - .textFieldDefaultBG - : null, + borderColor: + Util.isDesktop + ? Theme.of( + context, + ).extension()!.textFieldDefaultBG + : null, child: SelectableText( _current(_currentDropDownValue), style: STextStyles.w500_14(context), ), ), - SizedBox( - height: Util.isDesktop ? 12 : 16, - ), + SizedBox(height: Util.isDesktop ? 12 : 16), if (!Util.isDesktop) const Spacer(), Row( children: [ if (Util.isDesktop) const Spacer(), - if (Util.isDesktop) - const SizedBox( - width: 16, - ), - Expanded( - child: PrimaryButton( - label: "Copy", - onPressed: _copy, - ), - ), + if (Util.isDesktop) const SizedBox(width: 16), + Expanded(child: PrimaryButton(label: "Copy", onPressed: _copy)), ], ), ], diff --git a/lib/pages/spark_names/confirm_spark_name_transaction_view.dart b/lib/pages/spark_names/confirm_spark_name_transaction_view.dart index 011532708..c98409dfd 100644 --- a/lib/pages/spark_names/confirm_spark_name_transaction_view.dart +++ b/lib/pages/spark_names/confirm_spark_name_transaction_view.dart @@ -269,29 +269,31 @@ class _ConfirmSparkNameTransactionViewState style: STextStyles.navBarTitle(context), ), ), - body: LayoutBuilder( - builder: (builderContext, constraints) { - return Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, - ), - child: SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight - 24, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: child, + body: SafeArea( + child: LayoutBuilder( + builder: (builderContext, constraints) { + return Padding( + padding: const EdgeInsets.only( + left: 12, + top: 12, + right: 12, + ), + child: SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight - 24, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: child, + ), ), ), ), - ), - ); - }, + ); + }, + ), ), ), ), diff --git a/lib/pages/special/firo_rescan_recovery_error_dialog.dart b/lib/pages/special/firo_rescan_recovery_error_dialog.dart index fa59d841a..b703d69c2 100644 --- a/lib/pages/special/firo_rescan_recovery_error_dialog.dart +++ b/lib/pages/special/firo_rescan_recovery_error_dialog.dart @@ -28,17 +28,10 @@ import '../pinpad_views/lock_screen_view.dart'; import '../settings_views/wallet_settings_view/wallet_backup_views/wallet_backup_view.dart'; import '../settings_views/wallet_settings_view/wallet_settings_wallet_settings/delete_wallet_warning_view.dart'; -enum FiroRescanRecoveryErrorViewOption { - retry, - showMnemonic, - deleteWallet; -} +enum FiroRescanRecoveryErrorViewOption { retry, showMnemonic, deleteWallet } class FiroRescanRecoveryErrorView extends ConsumerStatefulWidget { - const FiroRescanRecoveryErrorView({ - super.key, - required this.walletId, - }); + const FiroRescanRecoveryErrorView({super.key, required this.walletId}); static const String routeName = "/firoRescanRecoveryErrorView"; @@ -71,20 +64,21 @@ class _FiroRescanRecoveryErrorViewState final result = await showDialog( context: context, barrierDismissible: false, - builder: (context) => Navigator( - initialRoute: DesktopDeleteWalletDialog.routeName, - onGenerateRoute: RouteGenerator.generateRoute, - onGenerateInitialRoutes: (_, __) { - return [ - RouteGenerator.generateRoute( - RouteSettings( - name: DesktopDeleteWalletDialog.routeName, - arguments: widget.walletId, - ), - ), - ]; - }, - ), + builder: + (context) => Navigator( + initialRoute: DesktopDeleteWalletDialog.routeName, + onGenerateRoute: RouteGenerator.generateRoute, + onGenerateInitialRoutes: (_, __) { + return [ + RouteGenerator.generateRoute( + RouteSettings( + name: DesktopDeleteWalletDialog.routeName, + arguments: widget.walletId, + ), + ), + ]; + }, + ), ); if (result == true) { @@ -119,82 +113,97 @@ class _FiroRescanRecoveryErrorViewState child: AspectRatio( aspectRatio: 1, child: AppBarIconButton( - semanticsLabel: "Delete wallet button. " + semanticsLabel: + "Delete wallet button. " "Start process of deleting current wallet.", key: const Key("walletViewRadioButton"), size: 36, shadows: const [], - color: Theme.of(context) - .extension()! - .background, + color: + Theme.of( + context, + ).extension()!.background, icon: SvgPicture.asset( Assets.svg.trash, width: 20, height: 20, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, ), onPressed: () async { - final walletName = - ref.read(pWalletName(widget.walletId)); + final walletName = ref.read( + pWalletName(widget.walletId), + ); await showDialog( barrierDismissible: true, context: context, - builder: (_) => StackDialog( - title: "Do you want to delete $walletName?", - leftButton: TextButton( - style: Theme.of(context) - .extension()! - .getSecondaryEnabledButtonStyle(context), - onPressed: () { - Navigator.pop(context); - }, - child: Text( - "Cancel", - style: STextStyles.button(context).copyWith( - color: Theme.of(context) + builder: + (_) => StackDialog( + title: "Do you want to delete $walletName?", + leftButton: TextButton( + style: Theme.of(context) .extension()! - .accentColorDark, - ), - ), - ), - rightButton: TextButton( - style: Theme.of(context) - .extension()! - .getPrimaryEnabledButtonStyle(context), - onPressed: () { - Navigator.pop(context); - Navigator.push( - context, - RouteGenerator.getRoute( - shouldUseMaterialRoute: - RouteGenerator.useMaterialPageRoute, - builder: (_) => LockscreenView( - routeOnSuccessArguments: - widget.walletId, - showBackButton: true, - routeOnSuccess: - DeleteWalletWarningView.routeName, - biometricsCancelButtonString: - "CANCEL", - biometricsLocalizedReason: - "Authenticate to delete wallet", - biometricsAuthenticationTitle: - "Delete wallet", - ), - settings: const RouteSettings( - name: "/deleteWalletLockscreen", + .getSecondaryEnabledButtonStyle( + context, + ), + onPressed: () { + Navigator.pop(context); + }, + child: Text( + "Cancel", + style: STextStyles.button( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .accentColorDark, ), ), - ); - }, - child: Text( - "Delete", - style: STextStyles.button(context), + ), + rightButton: TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonStyle( + context, + ), + onPressed: () { + Navigator.pop(context); + Navigator.push( + context, + RouteGenerator.getRoute( + shouldUseMaterialRoute: + RouteGenerator + .useMaterialPageRoute, + builder: + (_) => LockscreenView( + routeOnSuccessArguments: + widget.walletId, + showBackButton: true, + routeOnSuccess: + DeleteWalletWarningView + .routeName, + biometricsCancelButtonString: + "CANCEL", + biometricsLocalizedReason: + "Authenticate to delete wallet", + biometricsAuthenticationTitle: + "Delete wallet", + ), + settings: const RouteSettings( + name: "/deleteWalletLockscreen", + ), + ), + ); + }, + child: Text( + "Delete", + style: STextStyles.button(context), + ), + ), ), - ), - ), ); }, ), @@ -202,9 +211,11 @@ class _FiroRescanRecoveryErrorViewState ), ], ), - body: Padding( - padding: const EdgeInsets.all(16), - child: child, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: child, + ), ), ), ); @@ -217,25 +228,23 @@ class _FiroRescanRecoveryErrorViewState "Failed to rescan Firo wallet", style: STextStyles.pageTitleH2(context), ), - Util.isDesktop - ? const SizedBox( - height: 60, - ) - : const Spacer(), + Util.isDesktop ? const SizedBox(height: 60) : const Spacer(), BranchedParent( condition: Util.isDesktop, - conditionBranchBuilder: (children) => Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: children, - ), - otherBranchBuilder: (children) => Row( - children: [ - Expanded(child: children[0]), - children[1], - Expanded(child: children[2]), - ], - ), + conditionBranchBuilder: + (children) => Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: children, + ), + otherBranchBuilder: + (children) => Row( + children: [ + Expanded(child: children[0]), + children[1], + Expanded(child: children[2]), + ], + ), children: [ SecondaryButton( label: "Show mnemonic", @@ -245,24 +254,26 @@ class _FiroRescanRecoveryErrorViewState await showDialog( context: context, barrierDismissible: false, - builder: (context) => Navigator( - initialRoute: UnlockWalletKeysDesktop.routeName, - onGenerateRoute: RouteGenerator.generateRoute, - onGenerateInitialRoutes: (_, __) { - return [ - RouteGenerator.generateRoute( - RouteSettings( - name: UnlockWalletKeysDesktop.routeName, - arguments: widget.walletId, - ), - ), - ]; - }, - ), + builder: + (context) => Navigator( + initialRoute: UnlockWalletKeysDesktop.routeName, + onGenerateRoute: RouteGenerator.generateRoute, + onGenerateInitialRoutes: (_, __) { + return [ + RouteGenerator.generateRoute( + RouteSettings( + name: UnlockWalletKeysDesktop.routeName, + arguments: widget.walletId, + ), + ), + ]; + }, + ), ); } else { - final wallet = - ref.read(pWallets).getWallet(widget.walletId); + final wallet = ref + .read(pWallets) + .getWallet(widget.walletId); // TODO: [prio=low] take wallets that don't have a mnemonic into account if (wallet is MnemonicInterface) { final mnemonic = await wallet.getMnemonicAsWords(); @@ -280,20 +291,22 @@ class _FiroRescanRecoveryErrorViewState RouteGenerator.getRoute( shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute, - builder: (_) => LockscreenView( - routeOnSuccessArguments: ( - walletId: widget.walletId, - mnemonic: mnemonic, - keyData: keyData, - ), - showBackButton: true, - routeOnSuccess: WalletBackupView.routeName, - biometricsCancelButtonString: "CANCEL", - biometricsLocalizedReason: - "Authenticate to view recovery phrase", - biometricsAuthenticationTitle: - "View recovery phrase", - ), + builder: + (_) => LockscreenView( + routeOnSuccessArguments: ( + walletId: widget.walletId, + mnemonic: mnemonic, + keyData: keyData, + ), + showBackButton: true, + routeOnSuccess: + WalletBackupView.routeName, + biometricsCancelButtonString: "CANCEL", + biometricsLocalizedReason: + "Authenticate to view recovery phrase", + biometricsAuthenticationTitle: + "View recovery phrase", + ), settings: const RouteSettings( name: "/viewRecoverPhraseLockscreen", ), @@ -304,17 +317,12 @@ class _FiroRescanRecoveryErrorViewState } }, ), - const SizedBox( - width: 16, - height: 16, - ), + const SizedBox(width: 16, height: 16), PrimaryButton( label: "Retry", buttonHeight: Util.isDesktop ? ButtonHeight.l : null, onPressed: () { - Navigator.of(context).pop( - true, - ); + Navigator.of(context).pop(true); }, ), ], diff --git a/lib/pages/token_view/my_tokens_view.dart b/lib/pages/token_view/my_tokens_view.dart index eef37ced9..10e84751b 100644 --- a/lib/pages/token_view/my_tokens_view.dart +++ b/lib/pages/token_view/my_tokens_view.dart @@ -13,8 +13,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; -import '../add_wallet_views/add_token_view/edit_wallet_tokens_view.dart'; -import 'sub_widgets/my_tokens_list.dart'; + import '../../themes/stack_colors.dart'; import '../../utilities/assets.dart'; import '../../utilities/constants.dart'; @@ -27,12 +26,11 @@ import '../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../widgets/icon_widgets/x_icon.dart'; import '../../widgets/stack_text_field.dart'; import '../../widgets/textfield_icon_button.dart'; +import '../add_wallet_views/add_token_view/edit_wallet_tokens_view.dart'; +import 'sub_widgets/my_tokens_list.dart'; class MyTokensView extends ConsumerStatefulWidget { - const MyTokensView({ - super.key, - required this.walletId, - }); + const MyTokensView({super.key, required this.walletId}); static const String routeName = "/myTokens"; final String walletId; @@ -68,78 +66,80 @@ class _MyTokensViewState extends ConsumerState { return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: Scaffold( - backgroundColor: - Theme.of(context).extension()!.background, - appBar: AppBar( - backgroundColor: - Theme.of(context).extension()!.background, - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed(const Duration(milliseconds: 75)); - } - if (mounted) { - Navigator.of(context).pop(); - } - }, - ), - title: Text( - "${ref.watch( - pWalletName(widget.walletId), - )} Tokens", - style: STextStyles.navBarTitle(context), - ), - actions: [ - Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 20, + builder: + (child) => Background( + child: Scaffold( + backgroundColor: + Theme.of(context).extension()!.background, + appBar: AppBar( + backgroundColor: + Theme.of(context).extension()!.background, + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 75), + ); + } + if (mounted) { + Navigator.of(context).pop(); + } + }, + ), + title: Text( + "${ref.watch(pWalletName(widget.walletId))} Tokens", + style: STextStyles.navBarTitle(context), ), - child: AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - key: const Key("addTokenAppBarIconButtonKey"), - size: 36, - shadows: const [], - color: - Theme.of(context).extension()!.background, - icon: SvgPicture.asset( - Assets.svg.circlePlusFilled, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, - width: 20, - height: 20, + actions: [ + Padding( + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + right: 20, ), - onPressed: () async { - final result = await Navigator.of(context).pushNamed( - EditWalletTokensView.routeName, - arguments: widget.walletId, - ); + child: AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + key: const Key("addTokenAppBarIconButtonKey"), + size: 36, + shadows: const [], + color: + Theme.of( + context, + ).extension()!.background, + icon: SvgPicture.asset( + Assets.svg.circlePlusFilled, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, + width: 20, + height: 20, + ), + onPressed: () async { + final result = await Navigator.of(context).pushNamed( + EditWalletTokensView.routeName, + arguments: widget.walletId, + ); - if (mounted && result == 42) { - setState(() {}); - } - }, + if (mounted && result == 42) { + setState(() {}); + } + }, + ), + ), ), + ], + ), + body: SafeArea( + child: Padding( + padding: const EdgeInsets.only(left: 12, top: 12, right: 12), + child: child, ), ), - ], - ), - body: Padding( - padding: const EdgeInsets.only( - left: 12, - top: 12, - right: 12, ), - child: child, ), - ), - ), child: Column( children: [ Padding( @@ -148,14 +148,10 @@ class _MyTokensViewState extends ConsumerState { children: [ ConditionalParent( condition: isDesktop, - builder: (child) => Expanded( - child: child, - ), + builder: (child) => Expanded(child: child), child: ConditionalParent( condition: !isDesktop, - builder: (child) => Expanded( - child: child, - ), + builder: (child) => Expanded(child: child), child: ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -170,15 +166,18 @@ class _MyTokensViewState extends ConsumerState { _searchString = value; }); }, - style: isDesktop - ? STextStyles.desktopTextExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, - height: 1.8, - ) - : STextStyles.field(context), + style: + isDesktop + ? STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveText, + height: 1.8, + ) + : STextStyles.field(context), decoration: standardInputDecoration( "Search...", searchFieldFocusNode, @@ -196,26 +195,27 @@ class _MyTokensViewState extends ConsumerState { height: isDesktop ? 20 : 16, ), ), - suffixIcon: _searchController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _searchController.text = ""; - _searchString = ""; - }); - }, - ), - ], + suffixIcon: + _searchController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _searchController.text = ""; + _searchString = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), @@ -224,9 +224,7 @@ class _MyTokensViewState extends ConsumerState { ], ), ), - const SizedBox( - height: 8, - ), + const SizedBox(height: 8), Expanded( child: MyTokensList( walletId: widget.walletId, diff --git a/lib/pages/token_view/token_view.dart b/lib/pages/token_view/token_view.dart index b6acc49c5..6063bd49f 100644 --- a/lib/pages/token_view/token_view.dart +++ b/lib/pages/token_view/token_view.dart @@ -53,9 +53,10 @@ class _TokenViewState extends ConsumerState { @override void initState() { - initialSyncStatus = ref.read(pCurrentTokenWallet)!.refreshMutex.isLocked - ? WalletSyncStatus.syncing - : WalletSyncStatus.synced; + initialSyncStatus = + ref.read(pCurrentTokenWallet)!.refreshMutex.isLocked + ? WalletSyncStatus.syncing + : WalletSyncStatus.synced; super.initState(); } @@ -108,14 +109,13 @@ class _TokenViewState extends ConsumerState { ), size: 24, ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), Flexible( child: Text( ref.watch( - pCurrentTokenWallet - .select((value) => value!.tokenContract.name), + pCurrentTokenWallet.select( + (value) => value!.tokenContract.name, + ), ), style: STextStyles.navBarTitle(context), overflow: TextOverflow.ellipsis, @@ -135,9 +135,10 @@ class _TokenViewState extends ConsumerState { child: AppBarIconButton( icon: SvgPicture.asset( Assets.svg.verticalEllipsis, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, ), onPressed: () { // todo: context menu @@ -146,7 +147,8 @@ class _TokenViewState extends ConsumerState { arguments: Tuple2( ref.watch( pCurrentTokenWallet.select( - (value) => value!.tokenContract.address), + (value) => value!.tokenContract.address, + ), ), widget.walletId, ), @@ -157,93 +159,90 @@ class _TokenViewState extends ConsumerState { ), ], ), - body: Container( - color: Theme.of(context).extension()!.background, - child: Column( - children: [ - const SizedBox( - height: 10, - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: TokenSummary( - walletId: widget.walletId, - initialSyncStatus: initialSyncStatus, + body: SafeArea( + child: Container( + color: Theme.of(context).extension()!.background, + child: Column( + children: [ + const SizedBox(height: 10), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: TokenSummary( + walletId: widget.walletId, + initialSyncStatus: initialSyncStatus, + ), ), - ), - const SizedBox( - height: 20, - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Transactions", - style: STextStyles.itemSubtitle(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark3, + const SizedBox(height: 20), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Transactions", + style: STextStyles.itemSubtitle(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark3, + ), ), - ), - CustomTextButton( - text: "See all", - onTap: () { - Navigator.of(context).pushNamed( - AllTransactionsV2View.routeName, - arguments: ( - walletId: widget.walletId, - contractAddress: ref.watch( - pCurrentTokenWallet.select( - (value) => value!.tokenContract.address, + CustomTextButton( + text: "See all", + onTap: () { + Navigator.of(context).pushNamed( + AllTransactionsV2View.routeName, + arguments: ( + walletId: widget.walletId, + contractAddress: ref.watch( + pCurrentTokenWallet.select( + (value) => value!.tokenContract.address, + ), ), ), - ), - ); - }, - ), - ], - ), - ), - const SizedBox( - height: 12, - ), - Expanded( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: ClipRRect( - borderRadius: BorderRadius.vertical( - top: Radius.circular( - Constants.size.circularBorderRadius, - ), - bottom: Radius.circular( - // TokenView.navBarHeight / 2.0, - Constants.size.circularBorderRadius, + ); + }, ), - ), - child: Container( - decoration: BoxDecoration( - color: Colors.transparent, - borderRadius: BorderRadius.circular( + ], + ), + ), + const SizedBox(height: 12), + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: ClipRRect( + borderRadius: BorderRadius.vertical( + top: Radius.circular( + Constants.size.circularBorderRadius, + ), + bottom: Radius.circular( + // TokenView.navBarHeight / 2.0, Constants.size.circularBorderRadius, ), ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Expanded( - child: TokenTransactionsList( - walletId: widget.walletId, - ), + child: Container( + decoration: BoxDecoration( + color: Colors.transparent, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Expanded( + child: TokenTransactionsList( + walletId: widget.walletId, + ), + ), + ], + ), ), ), ), ), - ), - ], + ], + ), ), ), ), diff --git a/lib/pages/wallet_view/transaction_views/edit_note_view.dart b/lib/pages/wallet_view/transaction_views/edit_note_view.dart index 4d0c584eb..bcb6202ec 100644 --- a/lib/pages/wallet_view/transaction_views/edit_note_view.dart +++ b/lib/pages/wallet_view/transaction_views/edit_note_view.dart @@ -12,7 +12,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../models/isar/models/transaction_note.dart'; -import '../../../providers/db/main_db_provider.dart'; import '../../../providers/providers.dart'; import '../../../themes/stack_colors.dart'; import '../../../utilities/constants.dart'; @@ -28,11 +27,7 @@ import '../../../widgets/stack_text_field.dart'; import '../../../widgets/textfield_icon_button.dart'; class EditNoteView extends ConsumerStatefulWidget { - const EditNoteView({ - super.key, - required this.txid, - required this.walletId, - }); + const EditNoteView({super.key, required this.txid, required this.walletId}); static const String routeName = "/editNote"; @@ -57,9 +52,7 @@ class _EditNoteViewState extends ConsumerState { _noteController = TextEditingController(); _note = ref.read( - pTransactionNote( - (txid: widget.txid, walletId: widget.walletId), - ), + pTransactionNote((txid: widget.txid, walletId: widget.walletId)), ); _noteController.text = _note?.value ?? ""; super.initState(); @@ -76,63 +69,56 @@ class _EditNoteViewState extends ConsumerState { Widget build(BuildContext context) { return ConditionalParent( condition: !isDesktop, - builder: (child) => Background( - child: child, - ), + builder: (child) => Background(child: child), child: Scaffold( - backgroundColor: isDesktop - ? Colors.transparent - : Theme.of(context).extension()!.background, - appBar: isDesktop - ? null - : AppBar( - backgroundColor: - Theme.of(context).extension()!.background, - leading: AppBarBackButton( - onPressed: () async { - if (FocusScope.of(context).hasFocus) { - FocusScope.of(context).unfocus(); - await Future.delayed( - const Duration(milliseconds: 75), - ); - } - if (mounted) { - Navigator.of(context).pop(); - } - }, - ), - title: Text( - "Edit note", - style: STextStyles.navBarTitle(context), + backgroundColor: + isDesktop + ? Colors.transparent + : Theme.of(context).extension()!.background, + appBar: + isDesktop + ? null + : AppBar( + backgroundColor: + Theme.of(context).extension()!.background, + leading: AppBarBackButton( + onPressed: () async { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 75), + ); + } + if (mounted) { + Navigator.of(context).pop(); + } + }, + ), + title: Text( + "Edit note", + style: STextStyles.navBarTitle(context), + ), ), - ), body: MobileEditNoteScaffold( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ if (isDesktop) Padding( - padding: const EdgeInsets.only( - left: 32, - bottom: 12, - ), + padding: const EdgeInsets.only(left: 32, bottom: 12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Edit note", - style: STextStyles.desktopH3(context), - ), + Text("Edit note", style: STextStyles.desktopH3(context)), const DesktopDialogCloseButton(), ], ), ), Padding( - padding: isDesktop - ? const EdgeInsets.symmetric( - horizontal: 32, - ) - : const EdgeInsets.all(0), + padding: + isDesktop + ? const EdgeInsets.symmetric(horizontal: 32) + : const EdgeInsets.all(0), child: ClipRRect( borderRadius: BorderRadius.circular( Constants.size.circularBorderRadius, @@ -141,14 +127,18 @@ class _EditNoteViewState extends ConsumerState { autocorrect: Util.isDesktop ? false : true, enableSuggestions: Util.isDesktop ? false : true, controller: _noteController, - style: isDesktop - ? STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveText, - height: 1.8, - ) - : STextStyles.field(context), + style: + isDesktop + ? STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveText, + height: 1.8, + ) + : STextStyles.field(context), focusNode: noteFieldFocusNode, decoration: standardInputDecoration( "Note", @@ -156,33 +146,35 @@ class _EditNoteViewState extends ConsumerState { context, desktopMed: isDesktop, ).copyWith( - contentPadding: isDesktop - ? const EdgeInsets.only( - left: 16, - top: 11, - bottom: 12, - right: 5, - ) - : null, - suffixIcon: _noteController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _noteController.text = ""; - }); - }, - ), - ], + contentPadding: + isDesktop + ? const EdgeInsets.only( + left: 16, + top: 11, + bottom: 12, + right: 5, + ) + : null, + suffixIcon: + _noteController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _noteController.text = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), @@ -195,7 +187,9 @@ class _EditNoteViewState extends ConsumerState { child: PrimaryButton( label: "Save", onPressed: () async { - await ref.read(mainDBProvider).putTransactionNote( + await ref + .read(mainDBProvider) + .putTransactionNote( _note?.copyWith(value: _noteController.text) ?? TransactionNote( walletId: widget.walletId, @@ -213,7 +207,9 @@ class _EditNoteViewState extends ConsumerState { if (!isDesktop) TextButton( onPressed: () async { - await ref.read(mainDBProvider).putTransactionNote( + await ref + .read(mainDBProvider) + .putTransactionNote( _note?.copyWith(value: _noteController.text) ?? TransactionNote( walletId: widget.walletId, @@ -228,10 +224,7 @@ class _EditNoteViewState extends ConsumerState { style: Theme.of(context) .extension()! .getPrimaryEnabledButtonStyle(context), - child: Text( - "Save", - style: STextStyles.button(context), - ), + child: Text("Save", style: STextStyles.button(context)), ), ], ), @@ -242,10 +235,7 @@ class _EditNoteViewState extends ConsumerState { } class MobileEditNoteScaffold extends StatelessWidget { - const MobileEditNoteScaffold({ - super.key, - required this.child, - }); + const MobileEditNoteScaffold({super.key, required this.child}); final Widget child; @@ -254,24 +244,24 @@ class MobileEditNoteScaffold extends StatelessWidget { if (Util.isDesktop) { return child; } else { - return Padding( - padding: const EdgeInsets.all(12), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Padding( - padding: const EdgeInsets.all(4), - child: child, + return SafeArea( + child: Padding( + padding: const EdgeInsets.all(12), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints(minHeight: constraints.maxHeight), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.all(4), + child: child, + ), ), ), - ), - ); - }, + ); + }, + ), ), ); } diff --git a/lib/pages/wallet_view/transaction_views/transaction_details_view.dart b/lib/pages/wallet_view/transaction_views/transaction_details_view.dart index edd0bff14..7dc810ac8 100644 --- a/lib/pages/wallet_view/transaction_views/transaction_details_view.dart +++ b/lib/pages/wallet_view/transaction_views/transaction_details_view.dart @@ -22,7 +22,6 @@ import 'package:url_launcher/url_launcher.dart'; import '../../../models/isar/models/blockchain_data/transaction.dart'; import '../../../models/isar/models/ethereum/eth_contract.dart'; import '../../../notifications/show_flush_bar.dart'; -import '../../../providers/db/main_db_provider.dart'; import '../../../providers/global/address_book_service_provider.dart'; import '../../../providers/providers.dart'; import '../../../themes/stack_colors.dart'; @@ -419,405 +418,167 @@ class _TransactionDetailsViewState style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: - isDesktop - ? const EdgeInsets.only(left: 32) - : const EdgeInsets.all(12), - child: Column( - children: [ - if (isDesktop) - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Transaction details", - style: STextStyles.desktopH3(context), - ), - const DesktopDialogCloseButton(), - ], - ), - Expanded( - child: Padding( - padding: - isDesktop - ? const EdgeInsets.only(right: 32, bottom: 32) - : const EdgeInsets.all(0), - child: ConditionalParent( - condition: isDesktop, - builder: (child) { - return RoundedWhiteContainer( - borderColor: - isDesktop - ? Theme.of( - context, - ).extension()!.backgroundAppBar - : null, - padding: const EdgeInsets.all(0), - child: child, - ); - }, - child: SingleChildScrollView( - primary: isDesktop ? false : null, - child: Padding( - padding: - isDesktop - ? const EdgeInsets.all(0) - : const EdgeInsets.all(4), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(0) - : const EdgeInsets.all(12), - child: Container( - decoration: + body: ConditionalParent( + condition: !isDesktop, + builder: (child) => SafeArea(child: child), + child: Padding( + padding: + isDesktop + ? const EdgeInsets.only(left: 32) + : const EdgeInsets.all(12), + child: Column( + children: [ + if (isDesktop) + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Transaction details", + style: STextStyles.desktopH3(context), + ), + const DesktopDialogCloseButton(), + ], + ), + Expanded( + child: Padding( + padding: + isDesktop + ? const EdgeInsets.only(right: 32, bottom: 32) + : const EdgeInsets.all(0), + child: ConditionalParent( + condition: isDesktop, + builder: (child) { + return RoundedWhiteContainer( + borderColor: + isDesktop + ? Theme.of( + context, + ).extension()!.backgroundAppBar + : null, + padding: const EdgeInsets.all(0), + child: child, + ); + }, + child: SingleChildScrollView( + primary: isDesktop ? false : null, + child: Padding( + padding: + isDesktop + ? const EdgeInsets.all(0) + : const EdgeInsets.all(4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedWhiteContainer( + padding: isDesktop - ? BoxDecoration( - color: - Theme.of(context) - .extension()! - .backgroundAppBar, - borderRadius: BorderRadius.vertical( - top: Radius.circular( - Constants - .size - .circularBorderRadius, - ), - ), - ) - : null, - child: Padding( - padding: + ? const EdgeInsets.all(0) + : const EdgeInsets.all(12), + child: Container( + decoration: isDesktop - ? const EdgeInsets.all(12) - : const EdgeInsets.all(0), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - if (isDesktop) - Row( - children: [ - TxIcon( - transaction: _transaction, - currentHeight: currentHeight, - coin: coin, - ), - const SizedBox(width: 16), - SelectableText( - _transaction.isCancelled - ? coin is Ethereum - ? "Failed" - : "Cancelled" - : whatIsIt( - _transaction, - currentHeight, - ), - style: - STextStyles.desktopTextMedium( - context, - ), + ? BoxDecoration( + color: + Theme.of(context) + .extension()! + .backgroundAppBar, + borderRadius: BorderRadius.vertical( + top: Radius.circular( + Constants + .size + .circularBorderRadius, + ), ), - ], - ), - Column( - crossAxisAlignment: - isDesktop - ? CrossAxisAlignment.end - : CrossAxisAlignment.start, - children: [ - SelectableText( - "$amountPrefix${ref.watch(pAmountFormatter(coin)).format(amount, ethContract: ethContract)}", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.titleBold12( + ) + : null, + child: Padding( + padding: + isDesktop + ? const EdgeInsets.all(12) + : const EdgeInsets.all(0), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + if (isDesktop) + Row( + children: [ + TxIcon( + transaction: _transaction, + currentHeight: currentHeight, + coin: coin, + ), + const SizedBox(width: 16), + SelectableText( + _transaction.isCancelled + ? coin is Ethereum + ? "Failed" + : "Cancelled" + : whatIsIt( + _transaction, + currentHeight, + ), + style: + STextStyles.desktopTextMedium( context, ), + ), + ], ), - const SizedBox(height: 2), - if (price != null) + Column( + crossAxisAlignment: + isDesktop + ? CrossAxisAlignment.end + : CrossAxisAlignment.start, + children: [ SelectableText( - "$amountPrefix${(amount.decimal * price).toAmount(fractionDigits: 2).fiatString(locale: ref.watch(localeServiceChangeNotifierProvider.select((value) => value.locale)))} ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - ], - ), - if (!isDesktop) - TxIcon( - transaction: _transaction, - currentHeight: currentHeight, - coin: coin, - ), - ], - ), - ), - ), - ), - - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - "Status", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle(context), - ), - // Flexible( - // child: FittedBox( - // fit: BoxFit.scaleDown, - // child: - SelectableText( - _transaction.isCancelled - ? coin is Ethereum - ? "Failed" - : "Cancelled" - : whatIsIt(_transaction, currentHeight), - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - _transaction.type == - TransactionType - .outgoing - ? Theme.of(context) - .extension< - StackColors - >()! - .accentColorOrange - : Theme.of(context) - .extension< - StackColors - >()! - .accentColorGreen, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), - // ), - // ), - ], - ), - ), - if (!((coin is Monero || coin is Wownero) && - _transaction.type == - TransactionType.outgoing) && - !((coin is Firo) && - _transaction.subType == - TransactionSubType.mint)) - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - if (!((coin is Monero || coin is Wownero) && - _transaction.type == - TransactionType.outgoing) && - !((coin is Firo) && - _transaction.subType == - TransactionSubType.mint)) - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - ConditionalParent( - condition: kDebugMode, - builder: (child) { - return Row( - mainAxisAlignment: - MainAxisAlignment - .spaceBetween, - children: [ - child, - CustomTextButton( - text: "Info", - onTap: () { - if (isDesktop) { - showDialog( - context: context, - builder: - ( - _, - ) => DesktopDialog( - maxHeight: - double - .infinity, - child: AddressDetailsView( - addressId: - _transaction - .address - .value! - .id, - walletId: - widget - .walletId, - ), - ), - ); - } else { - Navigator.of( - context, - ).pushNamed( - AddressDetailsView - .routeName, - arguments: Tuple2( - _transaction - .address - .value! - .id, - widget.walletId, - ), - ); - } - }, - ), - ], - ); - }, - child: Text( - _transaction.type == - TransactionType.outgoing - ? "Sent to" - : "Receiving address", + "$amountPrefix${ref.watch(pAmountFormatter(coin)).format(amount, ethContract: ethContract)}", style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, ) - : STextStyles.itemSubtitle( + : STextStyles.titleBold12( context, ), ), - ), - const SizedBox(height: 8), - _transaction.type == - TransactionType.incoming - ? FutureBuilder( - future: fetchContactNameFor( - _transaction - .address - .value! - .value, - ), - builder: ( - builderContext, - AsyncSnapshot - snapshot, - ) { - String addressOrContactName = - _transaction - .address - .value! - .value; - if (snapshot.connectionState == - ConnectionState - .done && - snapshot.hasData) { - addressOrContactName = - snapshot.data!; - } - return SelectableText( - addressOrContactName, - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of( - context, - ) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ); - }, - ) - : SelectableText( - _transaction - .address - .value! - .value, + const SizedBox(height: 2), + if (price != null) + SelectableText( + "$amountPrefix${(amount.decimal * price).toAmount(fractionDigits: 2).fiatString(locale: ref.watch(localeServiceChangeNotifierProvider.select((value) => value.locale)))} ${ref.watch(prefsChangeNotifierProvider.select((value) => value.currency))}", style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, ) - : STextStyles.itemSubtitle12( + : STextStyles.itemSubtitle( context, ), ), - ], - ), + ], + ), + if (!isDesktop) + TxIcon( + transaction: _transaction, + currentHeight: currentHeight, + coin: coin, + ), + ], ), - if (isDesktop) - IconCopyButton( - data: _transaction.address.value!.value, - ), - ], + ), ), ), - if (coin is Epiccash) + isDesktop ? const _Divider() : const SizedBox(height: 12), - if (coin is Epiccash) RoundedWhiteContainer( padding: isDesktop @@ -826,219 +587,397 @@ class _TransactionDetailsViewState child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "On chain note", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - const SizedBox(height: 8), - SelectableText( - _transaction.otherData ?? "", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), + Text( + "Status", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + // Flexible( + // child: FittedBox( + // fit: BoxFit.scaleDown, + // child: + SelectableText( + _transaction.isCancelled + ? coin is Ethereum + ? "Failed" + : "Cancelled" + : whatIsIt( + _transaction, + currentHeight, ), - ], - ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + _transaction.type == + TransactionType + .outgoing + ? Theme.of(context) + .extension< + StackColors + >()! + .accentColorOrange + : Theme.of(context) + .extension< + StackColors + >()! + .accentColorGreen, + ) + : STextStyles.itemSubtitle12( + context, + ), ), - if (isDesktop) - IconCopyButton( - data: _transaction.otherData ?? "", - ), + // ), + // ), ], ), ), - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( + if (!((coin is Monero || coin is Wownero) && + _transaction.type == + TransactionType.outgoing) && + !((coin is Firo) && + _transaction.subType == + TransactionSubType.mint)) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (!((coin is Monero || coin is Wownero) && + _transaction.type == + TransactionType.outgoing) && + !((coin is Firo) && + _transaction.subType == + TransactionSubType.mint)) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ - Text( - (coin is Epiccash) - ? "Local Note" - : "Note ", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - isDesktop - ? IconPencilButton( - onPressed: () { - showDialog( - context: context, - builder: (context) { - return DesktopDialog( - maxWidth: 580, - maxHeight: 360, - child: EditNoteView( - txid: _transaction.txid, - walletId: walletId, + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + ConditionalParent( + condition: kDebugMode, + builder: (child) { + return Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + child, + CustomTextButton( + text: "Info", + onTap: () { + if (isDesktop) { + showDialog( + context: context, + builder: + ( + _, + ) => DesktopDialog( + maxHeight: + double + .infinity, + child: AddressDetailsView( + addressId: + _transaction + .address + .value! + .id, + walletId: + widget + .walletId, + ), + ), + ); + } else { + Navigator.of( + context, + ).pushNamed( + AddressDetailsView + .routeName, + arguments: Tuple2( + _transaction + .address + .value! + .id, + widget.walletId, + ), + ); + } + }, ), - ); - }, - ); - }, - ) - : GestureDetector( - onTap: () { - Navigator.of(context).pushNamed( - EditNoteView.routeName, - arguments: Tuple2( - _transaction.txid, - walletId, - ), - ); - }, - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.pencil, - width: 10, - height: 10, - color: - Theme.of(context) - .extension< - StackColors - >()! - .infoItemIcons, - ), - const SizedBox(width: 4), - Text( - "Edit", - style: STextStyles.link2( - context, + ], + ); + }, + child: Text( + _transaction.type == + TransactionType.outgoing + ? "Sent to" + : "Receiving address", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + ), + const SizedBox(height: 8), + _transaction.type == + TransactionType.incoming + ? FutureBuilder( + future: fetchContactNameFor( + _transaction + .address + .value! + .value, ), + builder: ( + builderContext, + AsyncSnapshot + snapshot, + ) { + String + addressOrContactName = + _transaction + .address + .value! + .value; + if (snapshot.connectionState == + ConnectionState + .done && + snapshot.hasData) { + addressOrContactName = + snapshot.data!; + } + return SelectableText( + addressOrContactName, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ); + }, + ) + : SelectableText( + _transaction + .address + .value! + .value, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), - ], - ), - ), + ], + ), + ), + if (isDesktop) + IconCopyButton( + data: + _transaction.address.value!.value, + ), ], ), - const SizedBox(height: 8), - SelectableText( - ref - .watch( - pTransactionNote(( - txid: _transaction.txid, - walletId: walletId, - )), - ) - ?.value ?? - "", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), - ], - ), - ), - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Column( + ), + if (coin is Epiccash) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (coin is Epiccash) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - "Date", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "On chain note", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + const SizedBox(height: 8), + SelectableText( + _transaction.otherData ?? "", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + ], + ), ), - if (isDesktop) const SizedBox(height: 2), if (isDesktop) - SelectableText( - Format.extractDateFrom( - _transaction.timestamp, - ), + IconCopyButton( + data: _transaction.otherData ?? "", + ), + ], + ), + ), + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + (coin is Epiccash) + ? "Local Note" + : "Note ", style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( context, - ).copyWith( + ) + : STextStyles.itemSubtitle( + context, + ), + ), + isDesktop + ? IconPencilButton( + onPressed: () { + showDialog( + context: context, + builder: (context) { + return DesktopDialog( + maxWidth: 580, + maxHeight: 360, + child: EditNoteView( + txid: _transaction.txid, + walletId: walletId, + ), + ); + }, + ); + }, + ) + : GestureDetector( + onTap: () { + Navigator.of(context).pushNamed( + EditNoteView.routeName, + arguments: Tuple2( + _transaction.txid, + walletId, + ), + ); + }, + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.pencil, + width: 10, + height: 10, color: Theme.of(context) .extension< StackColors >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, + .infoItemIcons, ), - ), - ], - ), - if (!isDesktop) + const SizedBox(width: 4), + Text( + "Edit", + style: STextStyles.link2( + context, + ), + ), + ], + ), + ), + ], + ), + const SizedBox(height: 8), SelectableText( - Format.extractDateFrom( - _transaction.timestamp, - ), + ref + .watch( + pTransactionNote(( + txid: _transaction.txid, + walletId: walletId, + )), + ) + ?.value ?? + "", style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( @@ -1055,96 +994,44 @@ class _TransactionDetailsViewState context, ), ), - if (isDesktop) - IconCopyButton( - data: Format.extractDateFrom( - _transaction.timestamp, - ), - ), - ], + ], + ), ), - ), - if (coin is! NanoCurrency) isDesktop ? const _Divider() : const SizedBox(height: 12), - if (coin is! NanoCurrency) RoundedWhiteContainer( padding: isDesktop ? const EdgeInsets.all(16) : const EdgeInsets.all(12), - child: Builder( - builder: (context) { - final String feeString = - showFeePending - ? _transaction.isConfirmed( - currentHeight, - minConfirms, - ) - ? ref - .watch( - pAmountFormatter(coin), - ) - .format( - fee, - withUnitName: isTokenTx, - ) - : "Pending" - : ref - .watch(pAmountFormatter(coin)) - .format( - fee, - withUnitName: isTokenTx, - ); - - return Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Transaction fee", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - if (isDesktop) - const SizedBox(height: 2), - if (isDesktop) - SelectableText( - feeString, - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), - ], + Text( + "Date", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), - if (!isDesktop) + if (isDesktop) + const SizedBox(height: 2), + if (isDesktop) SelectableText( - feeString, + Format.extractDateFrom( + _transaction.timestamp, + ), style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( @@ -1161,62 +1048,73 @@ class _TransactionDetailsViewState context, ), ), - if (isDesktop) - IconCopyButton(data: feeString), ], - ); - }, - ), - ), - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - Builder( - builder: (context) { - final String height; - final String confirmations; - final confirms = _transaction.getConfirmations( - currentHeight, - ); - - if (widget.coin is Bitcoincash || - widget.coin is Ecash) { - height = - _transaction.height != null && - _transaction.height! > 0 - ? "${_transaction.height!}" - : "Pending"; - confirmations = confirms.toString(); - } else if (widget.coin is Epiccash && - _transaction.slateId == null) { - confirmations = "Unknown"; - height = "Unknown"; - } else { - final confirmed = _transaction.isConfirmed( - currentHeight, - minConfirms, - ); - if (widget.coin is! Epiccash && confirmed) { - height = - "${_transaction.height == 0 ? "Unknown" : _transaction.height}"; - } else { - height = - confirms > 0 - ? "${_transaction.height}" - : "Pending"; - } - - confirmations = confirms.toString(); - } + ), + if (!isDesktop) + SelectableText( + Format.extractDateFrom( + _transaction.timestamp, + ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + if (isDesktop) + IconCopyButton( + data: Format.extractDateFrom( + _transaction.timestamp, + ), + ), + ], + ), + ), + if (coin is! NanoCurrency) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (coin is! NanoCurrency) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Builder( + builder: (context) { + final String feeString = + showFeePending + ? _transaction.isConfirmed( + currentHeight, + minConfirms, + ) + ? ref + .watch( + pAmountFormatter(coin), + ) + .format( + fee, + withUnitName: isTokenTx, + ) + : "Pending" + : ref + .watch(pAmountFormatter(coin)) + .format( + fee, + withUnitName: isTokenTx, + ); - return Column( - children: [ - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( + return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: @@ -1227,7 +1125,7 @@ class _TransactionDetailsViewState CrossAxisAlignment.start, children: [ Text( - "Block height", + "Transaction fee", style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( @@ -1241,7 +1139,7 @@ class _TransactionDetailsViewState const SizedBox(height: 2), if (isDesktop) SelectableText( - height, + feeString, style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( @@ -1264,7 +1162,7 @@ class _TransactionDetailsViewState ), if (!isDesktop) SelectableText( - height, + feeString, style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( @@ -1282,144 +1180,310 @@ class _TransactionDetailsViewState ), ), if (isDesktop) - IconCopyButton(data: height), + IconCopyButton(data: feeString), ], - ), - ), - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Confirmations", + ); + }, + ), + ), + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + Builder( + builder: (context) { + final String height; + final String confirmations; + final confirms = _transaction + .getConfirmations(currentHeight); + + if (widget.coin is Bitcoincash || + widget.coin is Ecash) { + height = + _transaction.height != null && + _transaction.height! > 0 + ? "${_transaction.height!}" + : "Pending"; + confirmations = confirms.toString(); + } else if (widget.coin is Epiccash && + _transaction.slateId == null) { + confirmations = "Unknown"; + height = "Unknown"; + } else { + final confirmed = _transaction.isConfirmed( + currentHeight, + minConfirms, + ); + if (widget.coin is! Epiccash && confirmed) { + height = + "${_transaction.height == 0 ? "Unknown" : _transaction.height}"; + } else { + height = + confirms > 0 + ? "${_transaction.height}" + : "Pending"; + } + + confirmations = confirms.toString(); + } + + return Column( + children: [ + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Block height", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + if (isDesktop) + const SizedBox(height: 2), + if (isDesktop) + SelectableText( + height, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + ], + ), + if (!isDesktop) + SelectableText( + height, style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, ) - : STextStyles.itemSubtitle( + : STextStyles.itemSubtitle12( context, ), ), - if (isDesktop) - const SizedBox(height: 2), - if (isDesktop) - SelectableText( - confirmations, + if (isDesktop) + IconCopyButton(data: height), + ], + ), + ), + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Confirmations", style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( context, - ).copyWith( - color: - Theme.of( - context, - ) - .extension< - StackColors - >()! - .textDark, ) - : STextStyles.itemSubtitle12( + : STextStyles.itemSubtitle( context, ), ), - ], - ), - if (!isDesktop) - SelectableText( - confirmations, - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), + if (isDesktop) + const SizedBox(height: 2), + if (isDesktop) + SelectableText( + confirmations, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + ], ), - if (isDesktop) - IconCopyButton(data: height), - ], - ), - ), - ], - ); - }, - ), - if (coin is Ethereum) - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - if (coin is Ethereum) - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - "Nonce", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - SelectableText( - _transaction.nonce.toString(), - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, + if (!isDesktop) + SelectableText( + confirmations, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), - ), - ], - ), + if (isDesktop) + IconCopyButton(data: height), + ], + ), + ), + ], + ); + }, ), - if (kDebugMode) + if (coin is Ethereum) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (coin is Ethereum) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Nonce", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + SelectableText( + _transaction.nonce.toString(), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + ], + ), + ), + if (kDebugMode) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (kDebugMode) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Tx sub type", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + SelectableText( + _transaction.subType.toString(), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + ], + ), + ), isDesktop ? const _Divider() : const SizedBox(height: 12), - if (kDebugMode) RoundedWhiteContainer( padding: isDesktop @@ -1430,318 +1494,278 @@ class _TransactionDetailsViewState mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Tx sub type", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - SelectableText( - _transaction.subType.toString(), - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), - ], - ), - ), - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Transaction ID", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - const SizedBox(height: 8), - // Flexible( - // child: FittedBox( - // fit: BoxFit.scaleDown, - // child: - SelectableText( - _transaction.txid, - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), - if (coin is! Epiccash) + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Transaction ID", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), const SizedBox(height: 8), - if (coin is! Epiccash) - CustomTextButton( - text: "Open in block explorer", - onTap: () async { - final uri = - getBlockExplorerTransactionUrlFor( - coin: coin, - txid: _transaction.txid, - ); - - if (ref - .read( - prefsChangeNotifierProvider, - ) - .hideBlockExplorerWarning == - false) { - final shouldContinue = - await showExplorerWarning( - "${uri.scheme}://${uri.host}", + // Flexible( + // child: FittedBox( + // fit: BoxFit.scaleDown, + // child: + SelectableText( + _transaction.txid, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + if (coin is! Epiccash) + const SizedBox(height: 8), + if (coin is! Epiccash) + CustomTextButton( + text: "Open in block explorer", + onTap: () async { + final uri = + getBlockExplorerTransactionUrlFor( + coin: coin, + txid: _transaction.txid, ); - if (!shouldContinue) { - return; + if (ref + .read( + prefsChangeNotifierProvider, + ) + .hideBlockExplorerWarning == + false) { + final shouldContinue = + await showExplorerWarning( + "${uri.scheme}://${uri.host}", + ); + + if (!shouldContinue) { + return; + } } - } - // ref - // .read( - // shouldShowLockscreenOnResumeStateProvider - // .state) - // .state = false; - try { - await launchUrl( - uri, - mode: - LaunchMode - .externalApplication, - ); - } catch (_) { - if (context.mounted) { - unawaited( - showDialog( - context: context, - builder: - (_) => StackOkDialog( - title: - "Could not open in block explorer", - message: - "Failed to open \"${uri.toString()}\"", - ), - ), + // ref + // .read( + // shouldShowLockscreenOnResumeStateProvider + // .state) + // .state = false; + try { + await launchUrl( + uri, + mode: + LaunchMode + .externalApplication, ); + } catch (_) { + if (context.mounted) { + unawaited( + showDialog( + context: context, + builder: + ( + _, + ) => StackOkDialog( + title: + "Could not open in block explorer", + message: + "Failed to open \"${uri.toString()}\"", + ), + ), + ); + } + } finally { + // Future.delayed( + // const Duration(seconds: 1), + // () => ref + // .read( + // shouldShowLockscreenOnResumeStateProvider + // .state) + // .state = true, + // ); } - } finally { - // Future.delayed( - // const Duration(seconds: 1), - // () => ref - // .read( - // shouldShowLockscreenOnResumeStateProvider - // .state) - // .state = true, - // ); - } - }, - ), - // ), - // ), - ], - ), - ), - if (isDesktop) const SizedBox(width: 12), - if (isDesktop) - IconCopyButton(data: _transaction.txid), - ], - ), - ), - // if ((coin is FiroTestNet || coin is Firo) && - // _transaction.subType == "mint") - // const SizedBox( - // height: 12, - // ), - // if ((coin is FiroTestNet || coin is Firo) && - // _transaction.subType == "mint") - // RoundedWhiteContainer( - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - // children: [ - // Text( - // "Mint Transaction ID", - // style: STextStyles.itemSubtitle(context), - // ), - // ], - // ), - // const SizedBox( - // height: 8, - // ), - // // Flexible( - // // child: FittedBox( - // // fit: BoxFit.scaleDown, - // // child: - // SelectableText( - // _transaction.otherData ?? "Unknown", - // style: STextStyles.itemSubtitle12(context), - // ), - // // ), - // // ), - // const SizedBox( - // height: 8, - // ), - // BlueTextButton( - // text: "Open in block explorer", - // onTap: () async { - // final uri = getBlockExplorerTransactionUrlFor( - // coin: coin, - // txid: _transaction.otherData ?? "Unknown", - // ); - // // ref - // // .read( - // // shouldShowLockscreenOnResumeStateProvider - // // .state) - // // .state = false; - // try { - // await launchUrl( - // uri, - // mode: LaunchMode.externalApplication, - // ); - // } catch (_) { - // unawaited(showDialog( - // context: context, - // builder: (_) => StackOkDialog( - // title: "Could not open in block explorer", - // message: - // "Failed to open \"${uri.toString()}\"", - // ), - // )); - // } finally { - // // Future.delayed( - // // const Duration(seconds: 1), - // // () => ref - // // .read( - // // shouldShowLockscreenOnResumeStateProvider - // // .state) - // // .state = true, - // // ); - // } - // }, - // ), - // ], - // ), - // ), - if (coin is Epiccash) - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - if (coin is Epiccash) - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Slate ID", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - // Flexible( - // child: FittedBox( - // fit: BoxFit.scaleDown, - // child: - SelectableText( - _transaction.slateId ?? "Unknown", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), - // ), - // ), - ], + }, + ), + // ), + // ), + ], + ), ), if (isDesktop) const SizedBox(width: 12), if (isDesktop) - IconCopyButton( - data: _transaction.slateId ?? "Unknown", - ), + IconCopyButton(data: _transaction.txid), ], ), ), - if (!isDesktop) const SizedBox(height: 12), - ], + // if ((coin is FiroTestNet || coin is Firo) && + // _transaction.subType == "mint") + // const SizedBox( + // height: 12, + // ), + // if ((coin is FiroTestNet || coin is Firo) && + // _transaction.subType == "mint") + // RoundedWhiteContainer( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // Text( + // "Mint Transaction ID", + // style: STextStyles.itemSubtitle(context), + // ), + // ], + // ), + // const SizedBox( + // height: 8, + // ), + // // Flexible( + // // child: FittedBox( + // // fit: BoxFit.scaleDown, + // // child: + // SelectableText( + // _transaction.otherData ?? "Unknown", + // style: STextStyles.itemSubtitle12(context), + // ), + // // ), + // // ), + // const SizedBox( + // height: 8, + // ), + // BlueTextButton( + // text: "Open in block explorer", + // onTap: () async { + // final uri = getBlockExplorerTransactionUrlFor( + // coin: coin, + // txid: _transaction.otherData ?? "Unknown", + // ); + // // ref + // // .read( + // // shouldShowLockscreenOnResumeStateProvider + // // .state) + // // .state = false; + // try { + // await launchUrl( + // uri, + // mode: LaunchMode.externalApplication, + // ); + // } catch (_) { + // unawaited(showDialog( + // context: context, + // builder: (_) => StackOkDialog( + // title: "Could not open in block explorer", + // message: + // "Failed to open \"${uri.toString()}\"", + // ), + // )); + // } finally { + // // Future.delayed( + // // const Duration(seconds: 1), + // // () => ref + // // .read( + // // shouldShowLockscreenOnResumeStateProvider + // // .state) + // // .state = true, + // // ); + // } + // }, + // ), + // ], + // ), + // ), + if (coin is Epiccash) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (coin is Epiccash) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Slate ID", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + // Flexible( + // child: FittedBox( + // fit: BoxFit.scaleDown, + // child: + SelectableText( + _transaction.slateId ?? "Unknown", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + // ), + // ), + ], + ), + if (isDesktop) const SizedBox(width: 12), + if (isDesktop) + IconCopyButton( + data: + _transaction.slateId ?? "Unknown", + ), + ], + ), + ), + if (!isDesktop) const SizedBox(height: 12), + ], + ), ), ), ), ), ), - ), - ], + ], + ), ), ), floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, diff --git a/lib/pages/wallet_view/transaction_views/transaction_search_filter_view.dart b/lib/pages/wallet_view/transaction_views/transaction_search_filter_view.dart index 2eebe5dbe..a337cd898 100644 --- a/lib/pages/wallet_view/transaction_views/transaction_search_filter_view.dart +++ b/lib/pages/wallet_view/transaction_views/transaction_search_filter_view.dart @@ -40,10 +40,7 @@ import '../../../widgets/stack_text_field.dart'; import '../../../widgets/textfield_icon_button.dart'; class TransactionSearchFilterView extends ConsumerStatefulWidget { - const TransactionSearchFilterView({ - super.key, - required this.coin, - }); + const TransactionSearchFilterView({super.key, required this.coin}); static const String routeName = "/transactionSearchFilter"; @@ -82,18 +79,19 @@ class _TransactionSearchViewState _selectedFromDate = filterState.from; _keywordTextEditingController.text = filterState.keyword; - _fromDateString = _selectedFromDate == null - ? "" - : Format.formatDate(_selectedFromDate!); + _fromDateString = + _selectedFromDate == null + ? "" + : Format.formatDate(_selectedFromDate!); _toDateString = _selectedToDate == null ? "" : Format.formatDate(_selectedToDate!); - final String amount = filterState.amount == null - ? "" - : ref.read(pAmountFormatter(widget.coin)).format( - filterState.amount!, - withUnitName: false, - ); + final String amount = + filterState.amount == null + ? "" + : ref + .read(pAmountFormatter(widget.coin)) + .format(filterState.amount!, withUnitName: false); _amountTextEditingController.text = amount; } @@ -118,9 +116,10 @@ class _TransactionSearchViewState return Text( isDateSelected ? "From..." : _fromDateString, style: STextStyles.fieldLabel(context).copyWith( - color: isDateSelected - ? Theme.of(context).extension()!.textSubtitle2 - : Theme.of(context).extension()!.accentColorDark, + color: + isDateSelected + ? Theme.of(context).extension()!.textSubtitle2 + : Theme.of(context).extension()!.accentColorDark, ), ); } @@ -130,9 +129,10 @@ class _TransactionSearchViewState return Text( isDateSelected ? "To..." : _toDateString, style: STextStyles.fieldLabel(context).copyWith( - color: isDateSelected - ? Theme.of(context).extension()!.textSubtitle2 - : Theme.of(context).extension()!.accentColorDark, + color: + isDateSelected + ? Theme.of(context).extension()!.textSubtitle2 + : Theme.of(context).extension()!.accentColorDark, ), ); } @@ -145,13 +145,14 @@ class _TransactionSearchViewState const middleSeparatorWidth = 12.0; final isDesktop = Util.isDesktop; - final width = isDesktop - ? null - : (MediaQuery.of(context).size.width - - (middleSeparatorWidth + - (2 * middleSeparatorPadding) + - (2 * Constants.size.standardPadding))) / - 2; + final width = + isDesktop + ? null + : (MediaQuery.of(context).size.width - + (middleSeparatorWidth + + (2 * middleSeparatorPadding) + + (2 * Constants.size.standardPadding))) / + 2; return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -172,7 +173,8 @@ class _TransactionSearchViewState _selectedFromDate = date; // flag to adjust date so from date is always before to date - final flag = _selectedToDate != null && + final flag = + _selectedToDate != null && !_selectedFromDate!.isBefore(_selectedToDate!); if (flag) { _selectedToDate = DateTime.fromMillisecondsSinceEpoch( @@ -182,13 +184,15 @@ class _TransactionSearchViewState setState(() { if (flag) { - _toDateString = _selectedToDate == null - ? "" - : Format.formatDate(_selectedToDate!); + _toDateString = + _selectedToDate == null + ? "" + : Format.formatDate(_selectedToDate!); } - _fromDateString = _selectedFromDate == null - ? "" - : Format.formatDate(_selectedFromDate!); + _fromDateString = + _selectedFromDate == null + ? "" + : Format.formatDate(_selectedFromDate!); }); } } @@ -196,15 +200,18 @@ class _TransactionSearchViewState child: Container( width: width, decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - borderRadius: - BorderRadius.circular(Constants.size.circularBorderRadius), + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), border: Border.all( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, width: 1, ), ), @@ -219,18 +226,15 @@ class _TransactionSearchViewState Assets.svg.calendar, height: 20, width: 20, - color: Theme.of(context) - .extension()! - .textSubtitle2, - ), - const SizedBox( - width: 10, + color: + Theme.of( + context, + ).extension()!.textSubtitle2, ), + const SizedBox(width: 10), Align( alignment: Alignment.centerLeft, - child: FittedBox( - child: _dateFromText, - ), + child: FittedBox(child: _dateFromText), ), ], ), @@ -239,8 +243,9 @@ class _TransactionSearchViewState ), ), Padding( - padding: - const EdgeInsets.symmetric(horizontal: middleSeparatorPadding), + padding: const EdgeInsets.symmetric( + horizontal: middleSeparatorPadding, + ), child: Container( width: middleSeparatorWidth, // height: 1, @@ -263,7 +268,8 @@ class _TransactionSearchViewState _selectedToDate = date; // flag to adjust date so from date is always before to date - final flag = _selectedFromDate != null && + final flag = + _selectedFromDate != null && !_selectedToDate!.isAfter(_selectedFromDate!); if (flag) { _selectedFromDate = DateTime.fromMillisecondsSinceEpoch( @@ -273,13 +279,15 @@ class _TransactionSearchViewState setState(() { if (flag) { - _fromDateString = _selectedFromDate == null - ? "" - : Format.formatDate(_selectedFromDate!); + _fromDateString = + _selectedFromDate == null + ? "" + : Format.formatDate(_selectedFromDate!); } - _toDateString = _selectedToDate == null - ? "" - : Format.formatDate(_selectedToDate!); + _toDateString = + _selectedToDate == null + ? "" + : Format.formatDate(_selectedToDate!); }); } } @@ -287,15 +295,18 @@ class _TransactionSearchViewState child: Container( width: width, decoration: BoxDecoration( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, - borderRadius: - BorderRadius.circular(Constants.size.circularBorderRadius), + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), border: Border.all( - color: Theme.of(context) - .extension()! - .textFieldDefaultBG, + color: + Theme.of( + context, + ).extension()!.textFieldDefaultBG, width: 1, ), ), @@ -310,18 +321,15 @@ class _TransactionSearchViewState Assets.svg.calendar, height: 20, width: 20, - color: Theme.of(context) - .extension()! - .textSubtitle2, - ), - const SizedBox( - width: 10, + color: + Theme.of( + context, + ).extension()!.textSubtitle2, ), + const SizedBox(width: 10), Align( alignment: Alignment.centerLeft, - child: FittedBox( - child: _dateToText, - ), + child: FittedBox(child: _dateToText), ), ], ), @@ -329,10 +337,7 @@ class _TransactionSearchViewState ), ), ), - if (isDesktop) - const SizedBox( - width: 24, - ), + if (isDesktop) const SizedBox(width: 24), ], ); } @@ -344,10 +349,7 @@ class _TransactionSearchViewState maxWidth: 576, maxHeight: double.infinity, child: Padding( - padding: const EdgeInsets.only( - left: 32, - bottom: 32, - ), + padding: const EdgeInsets.only(left: 32, bottom: 32), child: _buildContent(context), ), ); @@ -375,22 +377,23 @@ class _TransactionSearchViewState style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: EdgeInsets.symmetric( - horizontal: Constants.size.standardPadding, - ), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: - BoxConstraints(minHeight: constraints.maxHeight), - child: IntrinsicHeight( - child: _buildContent(context), + body: SafeArea( + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: Constants.size.standardPadding, + ), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight(child: _buildContent(context)), ), - ), - ); - }, + ); + }, + ), ), ), ), @@ -415,9 +418,7 @@ class _TransactionSearchViewState const DesktopDialogCloseButton(), ], ), - SizedBox( - height: isDesktop ? 14 : 10, - ), + SizedBox(height: isDesktop ? 14 : 10), if (!isDesktop) Align( alignment: Alignment.centerLeft, @@ -428,10 +429,7 @@ class _TransactionSearchViewState ), ), ), - if (!isDesktop) - const SizedBox( - height: 12, - ), + if (!isDesktop) const SizedBox(height: 12), RoundedWhiteContainer( padding: EdgeInsets.all(isDesktop ? 0 : 12), child: Column( @@ -466,9 +464,7 @@ class _TransactionSearchViewState }, ), ), - const SizedBox( - width: 14, - ), + const SizedBox(width: 14), Align( alignment: Alignment.centerLeft, child: FittedBox( @@ -476,14 +472,16 @@ class _TransactionSearchViewState children: [ Text( "Sent", - style: isDesktop - ? STextStyles.desktopTextSmall(context) - : STextStyles.itemSubtitle12(context), + style: + isDesktop + ? STextStyles.desktopTextSmall( + context, + ) + : STextStyles.itemSubtitle12( + context, + ), ), - if (isDesktop) - const SizedBox( - height: 4, - ), + if (isDesktop) const SizedBox(height: 4), ], ), ), @@ -494,9 +492,7 @@ class _TransactionSearchViewState ), ], ), - SizedBox( - height: isDesktop ? 4 : 10, - ), + SizedBox(height: isDesktop ? 4 : 10), Row( children: [ GestureDetector( @@ -526,9 +522,7 @@ class _TransactionSearchViewState }, ), ), - const SizedBox( - width: 14, - ), + const SizedBox(width: 14), Align( alignment: Alignment.centerLeft, child: FittedBox( @@ -536,14 +530,16 @@ class _TransactionSearchViewState children: [ Text( "Received", - style: isDesktop - ? STextStyles.desktopTextSmall(context) - : STextStyles.itemSubtitle12(context), + style: + isDesktop + ? STextStyles.desktopTextSmall( + context, + ) + : STextStyles.itemSubtitle12( + context, + ), ), - if (isDesktop) - const SizedBox( - height: 4, - ), + if (isDesktop) const SizedBox(height: 4), ], ), ), @@ -554,9 +550,7 @@ class _TransactionSearchViewState ), ], ), - SizedBox( - height: isDesktop ? 4 : 10, - ), + SizedBox(height: isDesktop ? 4 : 10), Row( children: [ GestureDetector( @@ -586,9 +580,7 @@ class _TransactionSearchViewState }, ), ), - const SizedBox( - width: 14, - ), + const SizedBox(width: 14), Align( alignment: Alignment.centerLeft, child: FittedBox( @@ -596,14 +588,16 @@ class _TransactionSearchViewState children: [ Text( "Trades", - style: isDesktop - ? STextStyles.desktopTextSmall(context) - : STextStyles.itemSubtitle12(context), + style: + isDesktop + ? STextStyles.desktopTextSmall( + context, + ) + : STextStyles.itemSubtitle12( + context, + ), ), - if (isDesktop) - const SizedBox( - height: 4, - ), + if (isDesktop) const SizedBox(height: 4), ], ), ), @@ -617,41 +611,35 @@ class _TransactionSearchViewState ], ), ), - SizedBox( - height: isDesktop ? 32 : 24, - ), + SizedBox(height: isDesktop ? 32 : 24), Align( alignment: Alignment.centerLeft, child: FittedBox( child: Text( "Date", - style: isDesktop - ? STextStyles.labelExtraExtraSmall(context) - : STextStyles.smallMed12(context), + style: + isDesktop + ? STextStyles.labelExtraExtraSmall(context) + : STextStyles.smallMed12(context), ), ), ), - SizedBox( - height: isDesktop ? 10 : 8, - ), + SizedBox(height: isDesktop ? 10 : 8), _buildDateRangePicker(), - SizedBox( - height: isDesktop ? 32 : 24, - ), + SizedBox(height: isDesktop ? 32 : 24), Align( alignment: Alignment.centerLeft, child: FittedBox( child: Text( "Amount", - style: isDesktop - ? STextStyles.labelExtraExtraSmall(context) - : STextStyles.smallMed12(context), + style: + isDesktop + ? STextStyles.labelExtraExtraSmall(context) + : STextStyles.smallMed12(context), ), ), ), - SizedBox( - height: isDesktop ? 10 : 8, - ), + SizedBox(height: isDesktop ? 10 : 8), Padding( padding: EdgeInsets.only(right: isDesktop ? 32 : 0), child: ClipRRect( @@ -665,19 +653,21 @@ class _TransactionSearchViewState controller: _amountTextEditingController, focusNode: amountTextFieldFocusNode, onChanged: (_) => setState(() {}), - keyboardType: Util.isDesktop - ? null - : const TextInputType.numberWithOptions( - signed: false, - decimal: true, - ), + keyboardType: + Util.isDesktop + ? null + : const TextInputType.numberWithOptions( + signed: false, + decimal: true, + ), inputFormatters: [ AmountInputFormatter( decimals: widget.coin.fractionDigits, unit: ref.watch(pAmountUnit(widget.coin)), locale: ref.watch( - localeServiceChangeNotifierProvider - .select((value) => value.locale), + localeServiceChangeNotifierProvider.select( + (value) => value.locale, + ), ), ), // // regex to validate a crypto amount with 8 decimal places @@ -687,65 +677,67 @@ class _TransactionSearchViewState // ? newValue // : oldValue), ], - style: isDesktop - ? STextStyles.desktopTextExtraSmall(context).copyWith( - color: - Theme.of(context).extension()!.textDark, - height: 1.8, - ) - : STextStyles.field(context), + style: + isDesktop + ? STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, + height: 1.8, + ) + : STextStyles.field(context), decoration: standardInputDecoration( "Enter ${widget.coin.ticker} amount...", keywordTextFieldFocusNode, context, desktopMed: isDesktop, ).copyWith( - contentPadding: isDesktop - ? const EdgeInsets.symmetric( - vertical: 10, - horizontal: 16, - ) - : null, - suffixIcon: _amountTextEditingController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _amountTextEditingController.text = ""; - }); - }, - ), - ], + contentPadding: + isDesktop + ? const EdgeInsets.symmetric( + vertical: 10, + horizontal: 16, + ) + : null, + suffixIcon: + _amountTextEditingController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _amountTextEditingController.text = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), ), - SizedBox( - height: isDesktop ? 32 : 24, - ), + SizedBox(height: isDesktop ? 32 : 24), Align( alignment: Alignment.centerLeft, child: FittedBox( child: Text( "Keyword", - style: isDesktop - ? STextStyles.labelExtraExtraSmall(context) - : STextStyles.smallMed12(context), + style: + isDesktop + ? STextStyles.labelExtraExtraSmall(context) + : STextStyles.smallMed12(context), ), ), ), - SizedBox( - height: isDesktop ? 10 : 8, - ), + SizedBox(height: isDesktop ? 10 : 8), Padding( padding: EdgeInsets.only(right: isDesktop ? 32 : 0), child: ClipRRect( @@ -758,13 +750,16 @@ class _TransactionSearchViewState key: const Key("transactionSearchViewKeywordFieldKey"), controller: _keywordTextEditingController, focusNode: keywordTextFieldFocusNode, - style: isDesktop - ? STextStyles.desktopTextExtraSmall(context).copyWith( - color: - Theme.of(context).extension()!.textDark, - height: 1.8, - ) - : STextStyles.field(context), + style: + isDesktop + ? STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, + height: 1.8, + ) + : STextStyles.field(context), onChanged: (_) => setState(() {}), decoration: standardInputDecoration( "Type keyword...", @@ -772,39 +767,39 @@ class _TransactionSearchViewState context, desktopMed: isDesktop, ).copyWith( - contentPadding: isDesktop - ? const EdgeInsets.symmetric( - vertical: 10, - horizontal: 16, - ) - : null, - suffixIcon: _keywordTextEditingController.text.isNotEmpty - ? Padding( - padding: const EdgeInsets.only(right: 0), - child: UnconstrainedBox( - child: Row( - children: [ - TextFieldIconButton( - child: const XIcon(), - onTap: () async { - setState(() { - _keywordTextEditingController.text = ""; - }); - }, - ), - ], + contentPadding: + isDesktop + ? const EdgeInsets.symmetric( + vertical: 10, + horizontal: 16, + ) + : null, + suffixIcon: + _keywordTextEditingController.text.isNotEmpty + ? Padding( + padding: const EdgeInsets.only(right: 0), + child: UnconstrainedBox( + child: Row( + children: [ + TextFieldIconButton( + child: const XIcon(), + onTap: () async { + setState(() { + _keywordTextEditingController.text = ""; + }); + }, + ), + ], + ), ), - ), - ) - : null, + ) + : null, ), ), ), ), if (!isDesktop) const Spacer(), - SizedBox( - height: isDesktop ? 32 : 20, - ), + SizedBox(height: isDesktop ? 32 : 20), Row( children: [ Expanded( @@ -816,9 +811,7 @@ class _TransactionSearchViewState if (FocusScope.of(context).hasFocus) { FocusScope.of(context).unfocus(); await Future.delayed( - const Duration( - milliseconds: 75, - ), + const Duration(milliseconds: 75), ); } } @@ -855,9 +848,7 @@ class _TransactionSearchViewState // ), // ), // ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: PrimaryButton( buttonHeight: isDesktop ? ButtonHeight.l : null, @@ -884,16 +875,10 @@ class _TransactionSearchViewState // ), // ), // ), - if (isDesktop) - const SizedBox( - width: 32, - ), + if (isDesktop) const SizedBox(width: 32), ], ), - if (!isDesktop) - const SizedBox( - height: 20, - ), + if (!isDesktop) const SizedBox(height: 20), ], ); } @@ -902,11 +887,14 @@ class _TransactionSearchViewState final amountText = _amountTextEditingController.text; Amount? amount; if (amountText.isNotEmpty && !(amountText == "," || amountText == ".")) { - amount = amountText.contains(",") - ? Decimal.parse(amountText.replaceFirst(",", ".")) - .toAmount(fractionDigits: widget.coin.fractionDigits) - : Decimal.parse(amountText) - .toAmount(fractionDigits: widget.coin.fractionDigits); + amount = + amountText.contains(",") + ? Decimal.parse( + amountText.replaceFirst(",", "."), + ).toAmount(fractionDigits: widget.coin.fractionDigits) + : Decimal.parse( + amountText, + ).toAmount(fractionDigits: widget.coin.fractionDigits); } final TransactionFilter filter = TransactionFilter( diff --git a/lib/pages/wallet_view/transaction_views/tx_v2/boost_transaction_view.dart b/lib/pages/wallet_view/transaction_views/tx_v2/boost_transaction_view.dart index 5219b3f26..308210124 100644 --- a/lib/pages/wallet_view/transaction_views/tx_v2/boost_transaction_view.dart +++ b/lib/pages/wallet_view/transaction_views/tx_v2/boost_transaction_view.dart @@ -198,7 +198,7 @@ class _BoostTransactionViewState extends ConsumerState { style: STextStyles.navBarTitle(context), ), ), - body: child, + body: SafeArea(child: child), ), ), child: Padding( diff --git a/lib/pages/wallet_view/transaction_views/tx_v2/fusion_group_details_view.dart b/lib/pages/wallet_view/transaction_views/tx_v2/fusion_group_details_view.dart index ef473b3bf..c861bbff6 100644 --- a/lib/pages/wallet_view/transaction_views/tx_v2/fusion_group_details_view.dart +++ b/lib/pages/wallet_view/transaction_views/tx_v2/fusion_group_details_view.dart @@ -10,8 +10,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; + import '../../../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; -import 'transaction_v2_list_item.dart'; import '../../../../themes/stack_colors.dart'; import '../../../../utilities/constants.dart'; import '../../../../utilities/text_styles.dart'; @@ -21,6 +21,7 @@ import '../../../../widgets/background.dart'; import '../../../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../../../widgets/desktop/desktop_dialog_close_button.dart'; import '../../../../widgets/rounded_white_container.dart'; +import 'transaction_v2_list_item.dart'; class FusionGroupDetailsView extends ConsumerStatefulWidget { const FusionGroupDetailsView({ @@ -48,23 +49,15 @@ class _FusionGroupDetailsViewState BorderRadius get _borderRadiusFirst { return BorderRadius.only( - topLeft: Radius.circular( - Constants.size.circularBorderRadius, - ), - topRight: Radius.circular( - Constants.size.circularBorderRadius, - ), + topLeft: Radius.circular(Constants.size.circularBorderRadius), + topRight: Radius.circular(Constants.size.circularBorderRadius), ); } BorderRadius get _borderRadiusLast { return BorderRadius.only( - bottomLeft: Radius.circular( - Constants.size.circularBorderRadius, - ), - bottomRight: Radius.circular( - Constants.size.circularBorderRadius, - ), + bottomLeft: Radius.circular(Constants.size.circularBorderRadius), + bottomRight: Radius.circular(Constants.size.circularBorderRadius), ); } @@ -97,16 +90,14 @@ class _FusionGroupDetailsViewState ), Flexible( child: Padding( - padding: const EdgeInsets.only( - right: 32, - bottom: 32, - ), + padding: const EdgeInsets.only(right: 32, bottom: 32), child: RoundedWhiteContainer( - borderColor: isDesktop - ? Theme.of(context) - .extension()! - .backgroundAppBar - : null, + borderColor: + isDesktop + ? Theme.of( + context, + ).extension()!.backgroundAppBar + : null, padding: const EdgeInsets.all(0), child: ListView.separated( shrinkWrap: true, @@ -132,9 +123,10 @@ class _FusionGroupDetailsViewState return Container( width: double.infinity, height: 1.2, - color: Theme.of(context) - .extension()! - .background, + color: + Theme.of( + context, + ).extension()!.background, ); }, itemCount: widget.transactions.length, @@ -164,29 +156,27 @@ class _FusionGroupDetailsViewState style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: ListView.builder( - itemCount: widget.transactions.length, - itemBuilder: (context, index) { - BorderRadius? radius; - if (widget.transactions.length == 1) { - radius = BorderRadius.circular( - Constants.size.circularBorderRadius, - ); - } else if (index == widget.transactions.length - 1) { - radius = _borderRadiusLast; - } else if (index == 0) { - radius = _borderRadiusFirst; - } - final tx = widget.transactions[index]; + body: SafeArea( + child: Padding( + padding: const EdgeInsets.all(16), + child: ListView.builder( + itemCount: widget.transactions.length, + itemBuilder: (context, index) { + BorderRadius? radius; + if (widget.transactions.length == 1) { + radius = BorderRadius.circular( + Constants.size.circularBorderRadius, + ); + } else if (index == widget.transactions.length - 1) { + radius = _borderRadiusLast; + } else if (index == 0) { + radius = _borderRadiusFirst; + } + final tx = widget.transactions[index]; - return TxListItem( - tx: tx, - coin: widget.coin, - radius: radius, - ); - }, + return TxListItem(tx: tx, coin: widget.coin, radius: radius); + }, + ), ), ), ), diff --git a/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart b/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart index 06469c92b..a2e8e4453 100644 --- a/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart +++ b/lib/pages/wallet_view/transaction_views/tx_v2/transaction_v2_details_view.dart @@ -24,7 +24,6 @@ import '../../../../models/isar/models/blockchain_data/transaction.dart'; import '../../../../models/isar/models/blockchain_data/v2/transaction_v2.dart'; import '../../../../models/isar/models/ethereum/eth_contract.dart'; import '../../../../notifications/show_flush_bar.dart'; -import '../../../../providers/db/main_db_provider.dart'; import '../../../../providers/global/address_book_service_provider.dart'; import '../../../../providers/providers.dart'; import '../../../../themes/stack_colors.dart'; @@ -634,259 +633,192 @@ class _TransactionV2DetailsViewState style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: - isDesktop - ? const EdgeInsets.only(left: 32) - : const EdgeInsets.all(12), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - if (isDesktop) - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Transaction details", - style: STextStyles.desktopH3(context), - ), - const DesktopDialogCloseButton(), - ], - ), - Flexible( - child: Padding( - padding: - isDesktop - ? const EdgeInsets.only(right: 32, bottom: 32) - : const EdgeInsets.all(0), - child: ConditionalParent( - condition: isDesktop, - builder: (child) { - return RoundedWhiteContainer( - borderColor: - isDesktop - ? Theme.of( - context, - ).extension()!.backgroundAppBar - : null, - padding: const EdgeInsets.all(0), - child: child, - ); - }, - child: SingleChildScrollView( - primary: isDesktop ? false : null, - child: Padding( - padding: - isDesktop - ? const EdgeInsets.all(0) - : const EdgeInsets.all(4), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(0) - : const EdgeInsets.all(12), - child: Container( - decoration: + body: ConditionalParent( + condition: !isDesktop, + builder: (child) => SafeArea(child: child), + child: Padding( + padding: + isDesktop + ? const EdgeInsets.only(left: 32) + : const EdgeInsets.all(12), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + if (isDesktop) + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Transaction details", + style: STextStyles.desktopH3(context), + ), + const DesktopDialogCloseButton(), + ], + ), + Flexible( + child: Padding( + padding: + isDesktop + ? const EdgeInsets.only(right: 32, bottom: 32) + : const EdgeInsets.all(0), + child: ConditionalParent( + condition: isDesktop, + builder: (child) { + return RoundedWhiteContainer( + borderColor: + isDesktop + ? Theme.of( + context, + ).extension()!.backgroundAppBar + : null, + padding: const EdgeInsets.all(0), + child: child, + ); + }, + child: SingleChildScrollView( + primary: isDesktop ? false : null, + child: Padding( + padding: + isDesktop + ? const EdgeInsets.all(0) + : const EdgeInsets.all(4), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedWhiteContainer( + padding: isDesktop - ? BoxDecoration( - color: - Theme.of(context) - .extension()! - .backgroundAppBar, - borderRadius: BorderRadius.vertical( - top: Radius.circular( - Constants - .size - .circularBorderRadius, - ), - ), - ) - : null, - child: Padding( - padding: + ? const EdgeInsets.all(0) + : const EdgeInsets.all(12), + child: Container( + decoration: isDesktop - ? const EdgeInsets.all(12) - : const EdgeInsets.all(0), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - if (isDesktop) - Row( - children: [ - TxIcon( - transaction: _transaction, - currentHeight: currentHeight, - coin: coin, - ), - const SizedBox(width: 16), - SelectableText( - whatIsIt( - _transaction, - currentHeight, + ? BoxDecoration( + color: + Theme.of(context) + .extension()! + .backgroundAppBar, + borderRadius: BorderRadius.vertical( + top: Radius.circular( + Constants + .size + .circularBorderRadius, ), - style: - STextStyles.desktopTextMedium( - context, - ), ), - ], - ), - Column( - crossAxisAlignment: - isDesktop - ? CrossAxisAlignment.end - : CrossAxisAlignment.start, - children: [ - SelectableText( - "$amountPrefix${ref.watch(pAmountFormatter(coin)).format(amount, ethContract: ethContract)}", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.titleBold12( + ) + : null, + child: Padding( + padding: + isDesktop + ? const EdgeInsets.all(12) + : const EdgeInsets.all(0), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + if (isDesktop) + Row( + children: [ + TxIcon( + transaction: _transaction, + currentHeight: currentHeight, + coin: coin, + ), + const SizedBox(width: 16), + SelectableText( + whatIsIt( + _transaction, + currentHeight, + ), + style: + STextStyles.desktopTextMedium( context, ), + ), + ], ), - const SizedBox(height: 2), - if (price != null) - Builder( - builder: (context) { - final total = (amount.decimal * - price!) - .toAmount( - fractionDigits: 2, - ); - final formatted = total.fiatString( - locale: ref.watch( - localeServiceChangeNotifierProvider + Column( + crossAxisAlignment: + isDesktop + ? CrossAxisAlignment.end + : CrossAxisAlignment.start, + children: [ + SelectableText( + "$amountPrefix${ref.watch(pAmountFormatter(coin)).format(amount, ethContract: ethContract)}", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.titleBold12( + context, + ), + ), + const SizedBox(height: 2), + if (price != null) + Builder( + builder: (context) { + final total = + (amount.decimal * price!) + .toAmount( + fractionDigits: 2, + ); + final formatted = total + .fiatString( + locale: ref.watch( + localeServiceChangeNotifierProvider + .select( + (value) => + value + .locale, + ), + ), + ); + final ticker = ref.watch( + prefsChangeNotifierProvider .select( (value) => - value.locale, + value.currency, ), - ), - ); - final ticker = ref.watch( - prefsChangeNotifierProvider - .select( - (value) => - value.currency, - ), - ); - return SelectableText( - "$amountPrefix$formatted $ticker", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ); - }, - ), - ], - ), - if (!isDesktop) - TxIcon( - transaction: _transaction, - currentHeight: currentHeight, - coin: coin, + ); + return SelectableText( + "$amountPrefix$formatted $ticker", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ); + }, + ), + ], ), - ], + if (!isDesktop) + TxIcon( + transaction: _transaction, + currentHeight: currentHeight, + coin: coin, + ), + ], + ), ), ), ), - ), - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - "Status", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle(context), - ), - // Flexible( - // child: FittedBox( - // fit: BoxFit.scaleDown, - // child: - SelectableText( - whatIsIt(_transaction, currentHeight), - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - _transaction.type == - TransactionType - .outgoing && - _transaction - .subType != - TransactionSubType - .cashFusion - ? Theme.of(context) - .extension< - StackColors - >()! - .accentColorOrange - : Theme.of(context) - .extension< - StackColors - >()! - .accentColorGreen, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), - // ), - // ), - ], - ), - ), - if (!((coin is Monero || coin is Wownero) && - _transaction.type == - TransactionType.outgoing) && - !((coin is Firo) && - _transaction.subType == - TransactionSubType.mint)) isDesktop ? const _Divider() : const SizedBox(height: 12), - if (!((coin is Monero || coin is Wownero) && - _transaction.type == - TransactionType.outgoing) && - !((coin is Firo) && - _transaction.subType == - TransactionSubType.mint)) RoundedWhiteContainer( padding: isDesktop @@ -895,393 +827,360 @@ class _TransactionV2DetailsViewState child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - ConditionalParent( - condition: kDebugMode, - builder: (child) { - return Row( - mainAxisAlignment: - MainAxisAlignment - .spaceBetween, - children: [ - child, - // CustomTextButton( - // text: "Info", - // onTap: () async { - // final adr = await ref - // .read(mainDBProvider) - // .getAddress(walletId, - // addresses.first); - // if (adr != null && - // mounted) { - // if (isDesktop) { - // await showDialog< - // void>( - // context: context, - // builder: (_) => - // DesktopDialog( - // maxHeight: double - // .infinity, - // child: - // AddressDetailsView( - // addressId: - // adr.id, - // walletId: widget - // .walletId, - // ), - // ), - // ); - // } else { - // await Navigator.of( - // context) - // .pushNamed( - // AddressDetailsView - // .routeName, - // arguments: Tuple2( - // adr.id, - // widget.walletId, - // ), - // ); - // } - // } - // }, - // ) - ], - ); - }, - child: Text( - outputLabel, - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), + Text( + "Status", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + // Flexible( + // child: FittedBox( + // fit: BoxFit.scaleDown, + // child: + SelectableText( + whatIsIt(_transaction, currentHeight), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + _transaction.type == + TransactionType + .outgoing && + _transaction + .subType != + TransactionSubType + .cashFusion + ? Theme.of(context) + .extension< + StackColors + >()! + .accentColorOrange + : Theme.of(context) + .extension< + StackColors + >()! + .accentColorGreen, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + // ), + // ), + ], + ), + ), + if (!((coin is Monero || coin is Wownero) && + _transaction.type == + TransactionType.outgoing) && + !((coin is Firo) && + _transaction.subType == + TransactionSubType.mint)) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (!((coin is Monero || coin is Wownero) && + _transaction.type == + TransactionType.outgoing) && + !((coin is Firo) && + _transaction.subType == + TransactionSubType.mint)) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + ConditionalParent( + condition: kDebugMode, + builder: (child) { + return Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + child, + // CustomTextButton( + // text: "Info", + // onTap: () async { + // final adr = await ref + // .read(mainDBProvider) + // .getAddress(walletId, + // addresses.first); + // if (adr != null && + // mounted) { + // if (isDesktop) { + // await showDialog< + // void>( + // context: context, + // builder: (_) => + // DesktopDialog( + // maxHeight: double + // .infinity, + // child: + // AddressDetailsView( + // addressId: + // adr.id, + // walletId: widget + // .walletId, + // ), + // ), + // ); + // } else { + // await Navigator.of( + // context) + // .pushNamed( + // AddressDetailsView + // .routeName, + // arguments: Tuple2( + // adr.id, + // widget.walletId, + // ), + // ); + // } + // } + // }, + // ) + ], + ); + }, + child: Text( + outputLabel, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), ), - ), - const SizedBox(height: 8), - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - if (data.length == 1 && - data.first.addresses.length == - 1) - FutureBuilder( - future: fetchContactNameFor( - data.first.addresses.first, - ), - builder: ( - builderContext, - AsyncSnapshot - snapshot, - ) { - String - addressOrContactName = - data + const SizedBox(height: 8), + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + if (data.length == 1 && + data .first .addresses - .first; - if (snapshot.connectionState == - ConnectionState - .done && - snapshot.hasData) { + .length == + 1) + FutureBuilder( + future: fetchContactNameFor( + data + .first + .addresses + .first, + ), + builder: ( + builderContext, + AsyncSnapshot + snapshot, + ) { + String addressOrContactName = - snapshot.data!; - } - return SelectableText( - addressOrContactName, - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of( - context, - ) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ); - }, - ) - else - for ( - int i = 0; - i < data.length; - i++ - ) - ConditionalParent( - condition: i > 0, - builder: - (child) => Column( + data + .first + .addresses + .first; + if (snapshot.connectionState == + ConnectionState + .done && + snapshot.hasData) { + addressOrContactName = + snapshot.data!; + } + return SelectableText( + addressOrContactName, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ); + }, + ) + else + for ( + int i = 0; + i < data.length; + i++ + ) + ConditionalParent( + condition: i > 0, + builder: + (child) => Column( + crossAxisAlignment: + CrossAxisAlignment + .stretch, + children: [ + const _Divider(), + child, + ], + ), + child: Padding( + padding: + const EdgeInsets.all( + 8.0, + ), + child: Column( crossAxisAlignment: CrossAxisAlignment - .stretch, + .start, children: [ - const _Divider(), - child, + ...data[i].addresses.map(( + e, + ) { + return FutureBuilder( + future: + fetchContactNameFor( + e, + ), + builder: ( + builderContext, + AsyncSnapshot< + String + > + snapshot, + ) { + final String + addressOrContactName; + if (snapshot.connectionState == + ConnectionState + .done && + snapshot + .hasData) { + addressOrContactName = + snapshot + .data!; + } else { + addressOrContactName = + e; + } + + return OutputCard( + address: + addressOrContactName, + amount: + data[i] + .amount, + coin: coin, + ); + }, + ); + }), ], ), - child: Padding( - padding: - const EdgeInsets.all( - 8.0, - ), - child: Column( - crossAxisAlignment: - CrossAxisAlignment - .start, - children: [ - ...data[i].addresses.map(( - e, - ) { - return FutureBuilder( - future: - fetchContactNameFor( - e, - ), - builder: ( - builderContext, - AsyncSnapshot< - String - > - snapshot, - ) { - final String - addressOrContactName; - if (snapshot.connectionState == - ConnectionState - .done && - snapshot - .hasData) { - addressOrContactName = - snapshot - .data!; - } else { - addressOrContactName = - e; - } - - return OutputCard( - address: - addressOrContactName, - amount: - data[i] - .amount, - coin: coin, - ); - }, - ); - }), - ], ), ), - ), - ], - ), - ], + ], + ), + ], + ), ), - ), - // if (isDesktop) - // IconCopyButton( - // data: addresses.first, - // ), - ], + // if (isDesktop) + // IconCopyButton( + // data: addresses.first, + // ), + ], + ), ), - ), - if (coin is Epiccash) - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - if (coin is Epiccash) - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "On chain note", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - const SizedBox(height: 8), - SelectableText( - _transaction.onChainNote ?? "", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), - ], - ), - ), - if (isDesktop) - IconCopyButton( - data: _transaction.onChainNote ?? "", - ), - ], - ), - ), - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( + if (coin is Epiccash) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (coin is Epiccash) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ - Text( - (coin is Epiccash) - ? "Local Note" - : "Note ", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - isDesktop - ? IconPencilButton( - onPressed: () { - showDialog( - context: context, - builder: (context) { - return DesktopDialog( - maxWidth: 580, - maxHeight: 360, - child: EditNoteView( - txid: _transaction.txid, - walletId: walletId, - ), - ); - }, - ); - }, - ) - : GestureDetector( - onTap: () { - Navigator.of(context).pushNamed( - EditNoteView.routeName, - arguments: Tuple2( - _transaction.txid, - walletId, - ), - ); - }, - child: Row( - children: [ - SvgPicture.asset( - Assets.svg.pencil, - width: 10, - height: 10, - color: - Theme.of(context) - .extension< - StackColors - >()! - .infoItemIcons, - ), - const SizedBox(width: 4), - Text( - "Edit", - style: STextStyles.link2( - context, - ), - ), - ], + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "On chain note", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), ), - ), - ], - ), - const SizedBox(height: 8), - SelectableText( - ref - .watch( - pTransactionNote(( - txid: - (coin is Epiccash) - ? _transaction.slateId - .toString() - : _transaction.txid, - walletId: walletId, - )), - ) - ?.value ?? - "", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, + const SizedBox(height: 8), + SelectableText( + _transaction.onChainNote ?? "", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), + ], + ), + ), + if (isDesktop) + IconCopyButton( + data: _transaction.onChainNote ?? "", + ), + ], ), - ], - ), - ), - if (_sparkMemo != null) + ), isDesktop ? const _Divider() : const SizedBox(height: 12), - if (_sparkMemo != null) RoundedWhiteContainer( padding: isDesktop @@ -1291,9 +1190,13 @@ class _TransactionV2DetailsViewState crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, children: [ Text( - "Memo", + (coin is Epiccash) + ? "Local Note" + : "Note ", style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( @@ -1303,11 +1206,74 @@ class _TransactionV2DetailsViewState context, ), ), + isDesktop + ? IconPencilButton( + onPressed: () { + showDialog( + context: context, + builder: (context) { + return DesktopDialog( + maxWidth: 580, + maxHeight: 360, + child: EditNoteView( + txid: _transaction.txid, + walletId: walletId, + ), + ); + }, + ); + }, + ) + : GestureDetector( + onTap: () { + Navigator.of(context).pushNamed( + EditNoteView.routeName, + arguments: Tuple2( + _transaction.txid, + walletId, + ), + ); + }, + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.pencil, + width: 10, + height: 10, + color: + Theme.of(context) + .extension< + StackColors + >()! + .infoItemIcons, + ), + const SizedBox(width: 4), + Text( + "Edit", + style: STextStyles.link2( + context, + ), + ), + ], + ), + ), ], ), const SizedBox(height: 8), SelectableText( - _sparkMemo!, + ref + .watch( + pTransactionNote(( + txid: + (coin is Epiccash) + ? _transaction.slateId + .toString() + : _transaction.txid, + walletId: walletId, + )), + ) + ?.value ?? + "", style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( @@ -1327,177 +1293,92 @@ class _TransactionV2DetailsViewState ], ), ), - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Column( + if (_sparkMemo != null) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (_sparkMemo != null) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - "Date", + Row( + children: [ + Text( + "Memo", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + ], + ), + const SizedBox(height: 8), + SelectableText( + _sparkMemo!, style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, ) - : STextStyles.itemSubtitle( + : STextStyles.itemSubtitle12( context, ), ), - if (isDesktop) const SizedBox(height: 2), - if (isDesktop) - SelectableText( - Format.extractDateFrom( - _transaction.timestamp, - ), - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), ], ), - if (!isDesktop) - SelectableText( - Format.extractDateFrom( - _transaction.timestamp, - ), - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), - if (isDesktop) - IconCopyButton( - data: Format.extractDateFrom( - _transaction.timestamp, - ), - ), - ], - ), - ), - if (coin is! NanoCurrency && - !(coin is Xelis && - _transaction.type == - TransactionType.incoming)) + ), isDesktop ? const _Divider() : const SizedBox(height: 12), - if (coin is! NanoCurrency && - !(coin is Xelis && - _transaction.type == - TransactionType.incoming)) RoundedWhiteContainer( padding: isDesktop ? const EdgeInsets.all(16) : const EdgeInsets.all(12), - child: Builder( - builder: (context) { - final String feeString = - showFeePending - ? _transaction.isConfirmed( - currentHeight, - minConfirms, - coin.minCoinbaseConfirms, - ) - ? ref - .watch( - pAmountFormatter(coin), - ) - .format(fee) - : "Pending" - : ref - .watch(pAmountFormatter(coin)) - .format(fee); - - return Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Transaction fee", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), + Text( + "Date", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + if (isDesktop) + const SizedBox(height: 2), + if (isDesktop) + SelectableText( + Format.extractDateFrom( + _transaction.timestamp, ), - if (isDesktop) - const SizedBox(height: 2), - if (isDesktop) - SelectableText( - feeString, - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), - if (supportsRbf && !confirmedTxn) - const SizedBox(height: 8), - if (supportsRbf && !confirmedTxn) - CustomTextButton( - text: "Boost transaction", - onTap: _boostPressed, - ), - ], - ), - if (!isDesktop) - SelectableText( - feeString, style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( @@ -1514,63 +1395,74 @@ class _TransactionV2DetailsViewState context, ), ), - if (isDesktop) - IconCopyButton(data: feeString), ], - ); - }, + ), + if (!isDesktop) + SelectableText( + Format.extractDateFrom( + _transaction.timestamp, + ), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + if (isDesktop) + IconCopyButton( + data: Format.extractDateFrom( + _transaction.timestamp, + ), + ), + ], ), ), - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - Builder( - builder: (context) { - final String height; - final String confirmations; - final confirms = _transaction.getConfirmations( - currentHeight, - ); - - if (widget.coin is Bitcoincash || - widget.coin is Ecash) { - height = - _transaction.height != null && - _transaction.height! > 0 - ? "${_transaction.height!}" - : "Pending"; - confirmations = confirms.toString(); - } else if (widget.coin is Epiccash && - _transaction.slateId == null) { - confirmations = "Unknown"; - height = "Unknown"; - } else { - final confirmed = _transaction.isConfirmed( - currentHeight, - minConfirms, - coin.minCoinbaseConfirms, - ); - if (widget.coin is! Epiccash && confirmed) { - height = - "${_transaction.height == 0 ? "Unknown" : _transaction.height}"; - } else { - height = - confirms > 0 - ? "${_transaction.height}" - : "Pending"; - } - - confirmations = confirms.toString(); - } + if (coin is! NanoCurrency && + !(coin is Xelis && + _transaction.type == + TransactionType.incoming)) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (coin is! NanoCurrency && + !(coin is Xelis && + _transaction.type == + TransactionType.incoming)) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Builder( + builder: (context) { + final String feeString = + showFeePending + ? _transaction.isConfirmed( + currentHeight, + minConfirms, + coin.minCoinbaseConfirms, + ) + ? ref + .watch( + pAmountFormatter(coin), + ) + .format(fee) + : "Pending" + : ref + .watch(pAmountFormatter(coin)) + .format(fee); - return Column( - children: [ - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( + return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: @@ -1581,7 +1473,7 @@ class _TransactionV2DetailsViewState CrossAxisAlignment.start, children: [ Text( - "Block height", + "Transaction fee", style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( @@ -1595,7 +1487,7 @@ class _TransactionV2DetailsViewState const SizedBox(height: 2), if (isDesktop) SelectableText( - height, + feeString, style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( @@ -1614,11 +1506,18 @@ class _TransactionV2DetailsViewState context, ), ), + if (supportsRbf && !confirmedTxn) + const SizedBox(height: 8), + if (supportsRbf && !confirmedTxn) + CustomTextButton( + text: "Boost transaction", + onTap: _boostPressed, + ), ], ), if (!isDesktop) SelectableText( - height, + feeString, style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( @@ -1636,146 +1535,322 @@ class _TransactionV2DetailsViewState ), ), if (isDesktop) - IconCopyButton(data: height), + IconCopyButton(data: feeString), ], - ), - ), - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Confirmations", + ); + }, + ), + ), + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + Builder( + builder: (context) { + final String height; + final String confirmations; + final confirms = _transaction + .getConfirmations(currentHeight); + + if (widget.coin is Bitcoincash || + widget.coin is Ecash) { + height = + _transaction.height != null && + _transaction.height! > 0 + ? "${_transaction.height!}" + : "Pending"; + confirmations = confirms.toString(); + } else if (widget.coin is Epiccash && + _transaction.slateId == null) { + confirmations = "Unknown"; + height = "Unknown"; + } else { + final confirmed = _transaction.isConfirmed( + currentHeight, + minConfirms, + coin.minCoinbaseConfirms, + ); + if (widget.coin is! Epiccash && confirmed) { + height = + "${_transaction.height == 0 ? "Unknown" : _transaction.height}"; + } else { + height = + confirms > 0 + ? "${_transaction.height}" + : "Pending"; + } + + confirmations = confirms.toString(); + } + + return Column( + children: [ + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Block height", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + if (isDesktop) + const SizedBox(height: 2), + if (isDesktop) + SelectableText( + height, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + ], + ), + if (!isDesktop) + SelectableText( + height, style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, ) - : STextStyles.itemSubtitle( + : STextStyles.itemSubtitle12( context, ), ), - if (isDesktop) - const SizedBox(height: 2), - if (isDesktop) - SelectableText( - confirmations, + if (isDesktop) + IconCopyButton(data: height), + ], + ), + ), + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Confirmations", style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( context, - ).copyWith( - color: - Theme.of( - context, - ) - .extension< - StackColors - >()! - .textDark, ) - : STextStyles.itemSubtitle12( + : STextStyles.itemSubtitle( context, ), ), - ], - ), - if (!isDesktop) - SelectableText( - confirmations, - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), + if (isDesktop) + const SizedBox(height: 2), + if (isDesktop) + SelectableText( + confirmations, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + ], ), - if (isDesktop) - IconCopyButton(data: height), - ], - ), - ), - ], - ); - }, - ), - if (coin is Ethereum && - _transaction.type != TransactionType.incoming) - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - if (coin is Ethereum && - _transaction.type != TransactionType.incoming) - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - "Nonce", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - SelectableText( - _transaction.nonce.toString(), - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, + if (!isDesktop) + SelectableText( + confirmations, + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), ), - ), - ], - ), + if (isDesktop) + IconCopyButton(data: height), + ], + ), + ), + ], + ); + }, ), - if (kDebugMode) + if (coin is Ethereum && + _transaction.type != TransactionType.incoming) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (coin is Ethereum && + _transaction.type != TransactionType.incoming) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Nonce", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + SelectableText( + _transaction.nonce.toString(), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + ], + ), + ), + if (kDebugMode) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (kDebugMode) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + "Tx sub type", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + SelectableText( + _transaction.subType.toString(), + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + ], + ), + ), + if (hasTxKeyProbably) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (hasTxKeyProbably) + TxKeyWidget( + walletId: walletId, + txid: _transaction.txid, + ), isDesktop ? const _Divider() : const SizedBox(height: 12), - if (kDebugMode) RoundedWhiteContainer( padding: isDesktop @@ -1786,349 +1861,300 @@ class _TransactionV2DetailsViewState mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Tx sub type", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - SelectableText( - _transaction.subType.toString(), - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), - ], - ), - ), - if (hasTxKeyProbably) - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - if (hasTxKeyProbably) - TxKeyWidget( - walletId: walletId, - txid: _transaction.txid, - ), - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - ConditionalParent( - condition: !isDesktop, - builder: - (child) => Row( - children: [ - Expanded(child: child), - SimpleCopyButton( - data: _transaction.txid, - ), - ], - ), - child: Text( - "Transaction ID", + Expanded( + child: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + ConditionalParent( + condition: !isDesktop, + builder: + (child) => Row( + children: [ + Expanded(child: child), + SimpleCopyButton( + data: _transaction.txid, + ), + ], + ), + child: Text( + "Transaction ID", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + ), + const SizedBox(height: 8), + // Flexible( + // child: FittedBox( + // fit: BoxFit.scaleDown, + // child: + SelectableText( + _transaction.txid, style: isDesktop ? STextStyles.desktopTextExtraExtraSmall( context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, ) - : STextStyles.itemSubtitle( + : STextStyles.itemSubtitle12( context, ), ), - ), - const SizedBox(height: 8), - // Flexible( - // child: FittedBox( - // fit: BoxFit.scaleDown, - // child: - SelectableText( - _transaction.txid, - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), - if (coin is! Epiccash) - const SizedBox(height: 8), - if (coin is! Epiccash) - CustomTextButton( - text: "Open in block explorer", - onTap: () async { - final uri = - getBlockExplorerTransactionUrlFor( - coin: coin, - txid: _transaction.txid, - ); - - if (ref - .read( - prefsChangeNotifierProvider, - ) - .hideBlockExplorerWarning == - false) { - final shouldContinue = - await showExplorerWarning( - "${uri.scheme}://${uri.host}", + if (coin is! Epiccash) + const SizedBox(height: 8), + if (coin is! Epiccash) + CustomTextButton( + text: "Open in block explorer", + onTap: () async { + final uri = + getBlockExplorerTransactionUrlFor( + coin: coin, + txid: _transaction.txid, ); - if (!shouldContinue) { - return; + if (ref + .read( + prefsChangeNotifierProvider, + ) + .hideBlockExplorerWarning == + false) { + final shouldContinue = + await showExplorerWarning( + "${uri.scheme}://${uri.host}", + ); + + if (!shouldContinue) { + return; + } } - } - - // ref - // .read( - // shouldShowLockscreenOnResumeStateProvider - // .state) - // .state = false; - try { - await launchUrl( - uri, - mode: - LaunchMode - .externalApplication, - ); - } catch (_) { - if (context.mounted) { - unawaited( - showDialog( - context: context, - builder: - (_) => StackOkDialog( - title: - "Could not open in block explorer", - message: - "Failed to open \"${uri.toString()}\"", - ), - ), + + // ref + // .read( + // shouldShowLockscreenOnResumeStateProvider + // .state) + // .state = false; + try { + await launchUrl( + uri, + mode: + LaunchMode + .externalApplication, ); + } catch (_) { + if (context.mounted) { + unawaited( + showDialog( + context: context, + builder: + ( + _, + ) => StackOkDialog( + title: + "Could not open in block explorer", + message: + "Failed to open \"${uri.toString()}\"", + ), + ), + ); + } + } finally { + // Future.delayed( + // const Duration(seconds: 1), + // () => ref + // .read( + // shouldShowLockscreenOnResumeStateProvider + // .state) + // .state = true, + // ); } - } finally { - // Future.delayed( - // const Duration(seconds: 1), - // () => ref - // .read( - // shouldShowLockscreenOnResumeStateProvider - // .state) - // .state = true, - // ); - } - }, - ), - // ), - // ), - ], - ), - ), - if (isDesktop) const SizedBox(width: 12), - if (isDesktop) - IconCopyButton(data: _transaction.txid), - ], - ), - ), - // if ((coin is FiroTestNet || coin is Firo) && - // _transaction.subType == "mint") - // const SizedBox( - // height: 12, - // ), - // if ((coin is FiroTestNet || coin is Firo) && - // _transaction.subType == "mint") - // RoundedWhiteContainer( - // child: Column( - // crossAxisAlignment: CrossAxisAlignment.start, - // children: [ - // Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, - // children: [ - // Text( - // "Mint Transaction ID", - // style: STextStyles.itemSubtitle(context), - // ), - // ], - // ), - // const SizedBox( - // height: 8, - // ), - // // Flexible( - // // child: FittedBox( - // // fit: BoxFit.scaleDown, - // // child: - // SelectableText( - // _transaction.otherData ?? "Unknown", - // style: STextStyles.itemSubtitle12(context), - // ), - // // ), - // // ), - // const SizedBox( - // height: 8, - // ), - // BlueTextButton( - // text: "Open in block explorer", - // onTap: () async { - // final uri = getBlockExplorerTransactionUrlFor( - // coin: coin, - // txid: _transaction.otherData ?? "Unknown", - // ); - // // ref - // // .read( - // // shouldShowLockscreenOnResumeStateProvider - // // .state) - // // .state = false; - // try { - // await launchUrl( - // uri, - // mode: LaunchMode.externalApplication, - // ); - // } catch (_) { - // unawaited(showDialog( - // context: context, - // builder: (_) => StackOkDialog( - // title: "Could not open in block explorer", - // message: - // "Failed to open \"${uri.toString()}\"", - // ), - // )); - // } finally { - // // Future.delayed( - // // const Duration(seconds: 1), - // // () => ref - // // .read( - // // shouldShowLockscreenOnResumeStateProvider - // // .state) - // // .state = true, - // // ); - // } - // }, - // ), - // ], - // ), - // ), - if (coin is Epiccash) - isDesktop - ? const _Divider() - : const SizedBox(height: 12), - if (coin is Epiccash) - RoundedWhiteContainer( - padding: - isDesktop - ? const EdgeInsets.all(16) - : const EdgeInsets.all(12), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Slate ID", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ) - : STextStyles.itemSubtitle( - context, - ), - ), - // Flexible( - // child: FittedBox( - // fit: BoxFit.scaleDown, - // child: - SelectableText( - _transaction.slateId ?? "Unknown", - style: - isDesktop - ? STextStyles.desktopTextExtraExtraSmall( - context, - ).copyWith( - color: - Theme.of(context) - .extension< - StackColors - >()! - .textDark, - ) - : STextStyles.itemSubtitle12( - context, - ), - ), - // ), - // ), - ], + }, + ), + // ), + // ), + ], + ), ), if (isDesktop) const SizedBox(width: 12), if (isDesktop) - IconCopyButton( - data: _transaction.slateId ?? "Unknown", - ), + IconCopyButton(data: _transaction.txid), ], ), ), - if (!isDesktop) const SizedBox(height: 12), - // if (whatIsIt( - // _transaction, - // currentHeight, - // ) != - // "Sending") - // isDesktop - // ? const _Divider() - // : const SizedBox( - // height: 12, - // ), - ], + // if ((coin is FiroTestNet || coin is Firo) && + // _transaction.subType == "mint") + // const SizedBox( + // height: 12, + // ), + // if ((coin is FiroTestNet || coin is Firo) && + // _transaction.subType == "mint") + // RoundedWhiteContainer( + // child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // Text( + // "Mint Transaction ID", + // style: STextStyles.itemSubtitle(context), + // ), + // ], + // ), + // const SizedBox( + // height: 8, + // ), + // // Flexible( + // // child: FittedBox( + // // fit: BoxFit.scaleDown, + // // child: + // SelectableText( + // _transaction.otherData ?? "Unknown", + // style: STextStyles.itemSubtitle12(context), + // ), + // // ), + // // ), + // const SizedBox( + // height: 8, + // ), + // BlueTextButton( + // text: "Open in block explorer", + // onTap: () async { + // final uri = getBlockExplorerTransactionUrlFor( + // coin: coin, + // txid: _transaction.otherData ?? "Unknown", + // ); + // // ref + // // .read( + // // shouldShowLockscreenOnResumeStateProvider + // // .state) + // // .state = false; + // try { + // await launchUrl( + // uri, + // mode: LaunchMode.externalApplication, + // ); + // } catch (_) { + // unawaited(showDialog( + // context: context, + // builder: (_) => StackOkDialog( + // title: "Could not open in block explorer", + // message: + // "Failed to open \"${uri.toString()}\"", + // ), + // )); + // } finally { + // // Future.delayed( + // // const Duration(seconds: 1), + // // () => ref + // // .read( + // // shouldShowLockscreenOnResumeStateProvider + // // .state) + // // .state = true, + // // ); + // } + // }, + // ), + // ], + // ), + // ), + if (coin is Epiccash) + isDesktop + ? const _Divider() + : const SizedBox(height: 12), + if (coin is Epiccash) + RoundedWhiteContainer( + padding: + isDesktop + ? const EdgeInsets.all(16) + : const EdgeInsets.all(12), + child: Row( + crossAxisAlignment: + CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Slate ID", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ) + : STextStyles.itemSubtitle( + context, + ), + ), + // Flexible( + // child: FittedBox( + // fit: BoxFit.scaleDown, + // child: + SelectableText( + _transaction.slateId ?? "Unknown", + style: + isDesktop + ? STextStyles.desktopTextExtraExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension< + StackColors + >()! + .textDark, + ) + : STextStyles.itemSubtitle12( + context, + ), + ), + // ), + // ), + ], + ), + if (isDesktop) const SizedBox(width: 12), + if (isDesktop) + IconCopyButton( + data: + _transaction.slateId ?? "Unknown", + ), + ], + ), + ), + if (!isDesktop) const SizedBox(height: 12), + // if (whatIsIt( + // _transaction, + // currentHeight, + // ) != + // "Sending") + // isDesktop + // ? const _Divider() + // : const SizedBox( + // height: 12, + // ), + ], + ), ), ), ), ), ), - ), - ], + ], + ), ), ), floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, diff --git a/lib/widgets/desktop/desktop_scaffold.dart b/lib/widgets/desktop/desktop_scaffold.dart index 920c66306..805fc56a7 100644 --- a/lib/widgets/desktop/desktop_scaffold.dart +++ b/lib/widgets/desktop/desktop_scaffold.dart @@ -14,12 +14,7 @@ import '../../themes/stack_colors.dart'; import '../background.dart'; class DesktopScaffold extends StatelessWidget { - const DesktopScaffold({ - super.key, - this.background, - this.appBar, - this.body, - }); + const DesktopScaffold({super.key, this.background, this.appBar, this.body}); final Color? background; final Widget? appBar; @@ -35,10 +30,7 @@ class DesktopScaffold extends StatelessWidget { // crossAxisAlignment: CrossAxisAlignment.stretch, children: [ if (appBar != null) appBar!, - if (body != null) - Expanded( - child: body!, - ), + if (body != null) Expanded(child: body!), ], ), ), @@ -73,7 +65,7 @@ class MasterScaffold extends StatelessWidget { child: Scaffold( backgroundColor: background ?? Colors.transparent, appBar: appBar as PreferredSizeWidget?, - body: body, + body: SafeArea(child: body), ), ); } From f67940acefa0ba7452be308eae19fd8697a80c4f Mon Sep 17 00:00:00 2001 From: julian Date: Mon, 26 May 2025 15:08:23 -0600 Subject: [PATCH 2/6] auto format --- lib/app_config.dart | 6 +- .../exchange_data_loading_service.dart | 119 +++++++++--------- 2 files changed, 57 insertions(+), 68 deletions(-) diff --git a/lib/app_config.dart b/lib/app_config.dart index 62ce560c3..9f862f4c7 100644 --- a/lib/app_config.dart +++ b/lib/app_config.dart @@ -3,11 +3,7 @@ import 'wallets/crypto_currency/intermediate/frost_currency.dart'; part 'app_config.g.dart'; -enum AppFeature { - themeSelection, - buy, - swap; -} +enum AppFeature { themeSelection, buy, swap } abstract class AppConfig { static const appName = _prefix + _separator + suffix; diff --git a/lib/services/exchange/exchange_data_loading_service.dart b/lib/services/exchange/exchange_data_loading_service.dart index 1cfaee23b..80b7c53af 100644 --- a/lib/services/exchange/exchange_data_loading_service.dart +++ b/lib/services/exchange/exchange_data_loading_service.dart @@ -43,9 +43,10 @@ class ExchangeDataLoadingService { static int get currentCacheVersion => DB.instance.get( - boxName: DB.boxNameDBInfo, - key: "exchange_data_cache_version", - ) as int? ?? + boxName: DB.boxNameDBInfo, + key: "exchange_data_cache_version", + ) + as int? ?? 0; Future _updateCurrentCacheVersion(int version) async { @@ -88,11 +89,7 @@ class ExchangeDataLoadingService { ); pair?.setReceive( - await getAggregateCurrency( - AppConfig.swapDefaults.to, - rateType, - null, - ), + await getAggregateCurrency(AppConfig.swapDefaults.to, rateType, null), notifyListeners: false, ); } @@ -104,27 +101,26 @@ class ExchangeDataLoadingService { ExchangeRateType rateType, String? contract, ) async { - final currencies = await ExchangeDataLoadingService.instance.isar.currencies - .filter() - .group( - (q) => rateType == ExchangeRateType.fixed - ? q - .rateTypeEqualTo(SupportedRateType.both) - .or() - .rateTypeEqualTo(SupportedRateType.fixed) - : q - .rateTypeEqualTo(SupportedRateType.both) - .or() - .rateTypeEqualTo(SupportedRateType.estimated), - ) - .and() - .tickerEqualTo( - ticker, - caseSensitive: false, - ) - .and() - .tokenContractEqualTo(contract) - .findAll(); + final currencies = + await ExchangeDataLoadingService.instance.isar.currencies + .filter() + .group( + (q) => + rateType == ExchangeRateType.fixed + ? q + .rateTypeEqualTo(SupportedRateType.both) + .or() + .rateTypeEqualTo(SupportedRateType.fixed) + : q + .rateTypeEqualTo(SupportedRateType.both) + .or() + .rateTypeEqualTo(SupportedRateType.estimated), + ) + .and() + .tickerEqualTo(ticker, caseSensitive: false) + .and() + .tokenContractEqualTo(contract) + .findAll(); final items = currencies .map((e) => Tuple2(e.exchangeName, e)) @@ -145,9 +141,7 @@ class ExchangeDataLoadingService { if (_isar == null) { await initDB(); } - Logging.instance.d( - "ExchangeDataLoadingService.loadAll starting...", - ); + Logging.instance.d("ExchangeDataLoadingService.loadAll starting..."); final start = DateTime.now(); try { /* @@ -209,11 +203,12 @@ class ExchangeDataLoadingService { final responseCurrencies = await exchange.getAllCurrencies(false); if (responseCurrencies.value != null) { await isar.writeTxn(() async { - final idsToDelete = await isar.currencies - .where() - .exchangeNameEqualTo(ChangeNowExchange.exchangeName) - .idProperty() - .findAll(); + final idsToDelete = + await isar.currencies + .where() + .exchangeNameEqualTo(ChangeNowExchange.exchangeName) + .idProperty() + .findAll(); await isar.currencies.deleteAll(idsToDelete); await isar.currencies.putAll(responseCurrencies.value!); }); @@ -342,18 +337,17 @@ class ExchangeDataLoadingService { if (responseCurrencies.value != null) { await isar.writeTxn(() async { - final idsToDelete = await isar.currencies - .where() - .exchangeNameEqualTo(MajesticBankExchange.exchangeName) - .idProperty() - .findAll(); + final idsToDelete = + await isar.currencies + .where() + .exchangeNameEqualTo(MajesticBankExchange.exchangeName) + .idProperty() + .findAll(); await isar.currencies.deleteAll(idsToDelete); await isar.currencies.putAll(responseCurrencies.value!); }); } else { - Logging.instance.w( - "loadMajesticBankCurrencies: $responseCurrencies", - ); + Logging.instance.w("loadMajesticBankCurrencies: $responseCurrencies"); } } @@ -366,18 +360,17 @@ class ExchangeDataLoadingService { if (responseCurrencies.value != null) { await isar.writeTxn(() async { - final idsToDelete = await isar.currencies - .where() - .exchangeNameEqualTo(TrocadorExchange.exchangeName) - .idProperty() - .findAll(); + final idsToDelete = + await isar.currencies + .where() + .exchangeNameEqualTo(TrocadorExchange.exchangeName) + .idProperty() + .findAll(); await isar.currencies.deleteAll(idsToDelete); await isar.currencies.putAll(responseCurrencies.value!); }); } else { - Logging.instance.w( - "loadTrocadorCurrencies: $responseCurrencies", - ); + Logging.instance.w("loadTrocadorCurrencies: $responseCurrencies"); } } @@ -385,23 +378,23 @@ class ExchangeDataLoadingService { if (_isar == null) { await initDB(); } - final responseCurrencies = - await NanswapExchange.instance.getAllCurrencies(false); + final responseCurrencies = await NanswapExchange.instance.getAllCurrencies( + false, + ); if (responseCurrencies.value != null) { await isar.writeTxn(() async { - final idsToDelete = await isar.currencies - .where() - .exchangeNameEqualTo(NanswapExchange.exchangeName) - .idProperty() - .findAll(); + final idsToDelete = + await isar.currencies + .where() + .exchangeNameEqualTo(NanswapExchange.exchangeName) + .idProperty() + .findAll(); await isar.currencies.deleteAll(idsToDelete); await isar.currencies.putAll(responseCurrencies.value!); }); } else { - Logging.instance.w( - "loadNanswapCurrencies: $responseCurrencies", - ); + Logging.instance.w("loadNanswapCurrencies: $responseCurrencies"); } } From b6b63bca3e690b8f96a368de73f5353921edc59a Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 27 May 2025 08:17:33 -0600 Subject: [PATCH 3/6] fix: swap issues --- lib/app_config.dart | 3 +- lib/models/exchange/aggregate_currency.dart | 20 ++- .../change_now/estimated_exchange_amount.dart | 6 +- lib/models/isar/exchange_cache/currency.dart | 39 +++- .../exchange_currency_selection_view.dart | 168 ++++++++---------- lib/pages/exchange_view/exchange_form.dart | 77 ++------ .../exchange_data_loading_service.dart | 73 +++++--- .../exchange/trocador/trocador_api.dart | 58 +++--- scripts/app_config/configure_campfire.sh | 8 +- scripts/app_config/configure_stack_duo.sh | 8 +- scripts/app_config/configure_stack_wallet.sh | 8 +- 11 files changed, 236 insertions(+), 232 deletions(-) diff --git a/lib/app_config.dart b/lib/app_config.dart index 9f862f4c7..96b07b2c9 100644 --- a/lib/app_config.dart +++ b/lib/app_config.dart @@ -23,7 +23,8 @@ abstract class AppConfig { static List get coins => _supportedCoins; - static ({String from, String to}) get swapDefaults => _swapDefaults; + static ({String from, String fromFuzzyNet, String to, String toFuzzyNet}) + get swapDefaults => _swapDefaults; static bool get isSingleCoinApp => coins.length == 1; diff --git a/lib/models/exchange/aggregate_currency.dart b/lib/models/exchange/aggregate_currency.dart index ffaccd3c0..580e1b3bf 100644 --- a/lib/models/exchange/aggregate_currency.dart +++ b/lib/models/exchange/aggregate_currency.dart @@ -42,13 +42,29 @@ class AggregateCurrency { bool get isStackCoin => _map.values.first!.isStackCoin; + String get fuzzyNet => _map.values.first!.getFuzzyNet(); + @override String toString() { String str = "AggregateCurrency: {"; for (final key in _map.keys) { - str += " $key: ${_map[key]},"; + str += "\n $key: ${_map[key]},"; } - str += " }"; + str += "\n}"; return str; } + + @override + bool operator ==(Object other) { + return other is AggregateCurrency && + other.ticker == ticker && + other._map.isNotEmpty && + other._map.length == _map.length && + other._map.values.first!.getFuzzyNet() == + _map.values.first!.getFuzzyNet(); + } + + @override + int get hashCode => + Object.hash(ticker, _map.values.first!.getFuzzyNet(), _map.length); } diff --git a/lib/models/exchange/change_now/estimated_exchange_amount.dart b/lib/models/exchange/change_now/estimated_exchange_amount.dart index 7648cdacb..b36efe480 100644 --- a/lib/models/exchange/change_now/estimated_exchange_amount.dart +++ b/lib/models/exchange/change_now/estimated_exchange_amount.dart @@ -29,7 +29,7 @@ class EstimatedExchangeAmount { final String? rateId; /// Date and time before which the estimated amount is valid if using `rateId`. - final DateTime validUntil; + final DateTime? validUntil; /// Dash-separated min and max estimated time in minutes. final String? transactionSpeedForecast; @@ -87,7 +87,7 @@ class EstimatedExchangeAmount { flow: _parseFlow(json["flow"] as String), type: _parseType(json["type"] as String), rateId: json["rateId"] as String?, - validUntil: DateTime.parse(json["validUntil"] as String), + validUntil: DateTime.tryParse(json["validUntil"] as String? ?? ""), transactionSpeedForecast: json["transactionSpeedForecast"] as String?, warningMessage: json["warningMessage"] as String?, depositFee: Decimal.parse(json["depositFee"].toString()), @@ -108,7 +108,7 @@ class EstimatedExchangeAmount { "flow": flow.name.replaceAll("fixedRate", "fixed-rate"), "type": type.name, "rateId": rateId, - "validUntil": validUntil.toIso8601String(), + "validUntil": validUntil?.toIso8601String(), "transactionSpeedForecast": transactionSpeedForecast, "warningMessage": warningMessage, "depositFee": depositFee.toString(), diff --git a/lib/models/isar/exchange_cache/currency.dart b/lib/models/isar/exchange_cache/currency.dart index 29fed140d..04c510186 100644 --- a/lib/models/isar/exchange_cache/currency.dart +++ b/lib/models/isar/exchange_cache/currency.dart @@ -11,6 +11,11 @@ import 'package:isar/isar.dart'; import '../../../app_config.dart'; +import '../../../services/exchange/change_now/change_now_exchange.dart'; +import '../../../services/exchange/exchange.dart'; +import '../../../services/exchange/majestic_bank/majestic_bank_exchange.dart'; +import '../../../services/exchange/nanswap/nanswap_exchange.dart'; +import '../../../services/exchange/trocador/trocador_exchange.dart'; import 'pair.dart'; part 'currency.g.dart'; @@ -23,12 +28,7 @@ class Currency { final String exchangeName; /// Currency ticker - @Index( - composite: [ - CompositeIndex("exchangeName"), - CompositeIndex("name"), - ], - ) + @Index(composite: [CompositeIndex("exchangeName"), CompositeIndex("name")]) final String ticker; /// Currency name @@ -68,6 +68,33 @@ class Currency { rateType == SupportedRateType.estimated || rateType == SupportedRateType.both; + // used to group coins across providers + @ignore + String? _fuzzyCache; + String getFuzzyNet() { + return _fuzzyCache ??= switch (Exchange.fromName( + exchangeName, + ).runtimeType) { + // already lower case ticker basically + const (ChangeNowExchange) => network, + + // not used at the time being + // case const (SimpleSwapExchange): + + // currently a hardcoded of coins so we can just + const (MajesticBankExchange) => ticker.toLowerCase(), + + const (TrocadorExchange) => + (network == "Mainnet" ? ticker.toLowerCase() : network), + + // only a few coins and `network` is the ticker + const (NanswapExchange) => + network.isNotEmpty ? network.toLowerCase() : ticker.toLowerCase(), + + _ => throw Exception("Unknown exchange: $exchangeName"), + }; + } + Currency({ required this.exchangeName, required this.ticker, diff --git a/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart b/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart index 5c51ac134..291a61781 100644 --- a/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart +++ b/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart @@ -13,18 +13,18 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:isar/isar.dart'; +import 'package:tuple/tuple.dart'; import '../../../app_config.dart'; +import '../../../models/exchange/aggregate_currency.dart'; import '../../../models/isar/exchange_cache/currency.dart'; import '../../../models/isar/exchange_cache/pair.dart'; import '../../../services/exchange/exchange.dart'; import '../../../services/exchange/exchange_data_loading_service.dart'; -import '../../../services/exchange/majestic_bank/majestic_bank_exchange.dart'; -import '../../../services/exchange/nanswap/nanswap_exchange.dart'; -import '../../../services/exchange/trocador/trocador_exchange.dart'; import '../../../themes/stack_colors.dart'; import '../../../utilities/assets.dart'; import '../../../utilities/constants.dart'; +import '../../../utilities/logger.dart'; import '../../../utilities/prefs.dart'; import '../../../utilities/text_styles.dart'; import '../../../utilities/util.dart'; @@ -42,14 +42,12 @@ import '../../buy_view/sub_widgets/crypto_selection_view.dart'; class ExchangeCurrencySelectionView extends StatefulWidget { const ExchangeCurrencySelectionView({ super.key, - required this.willChangeTicker, - required this.pairedTicker, + required this.pairedCurrency, required this.isFixedRate, required this.willChangeIsSend, }); - final String? willChangeTicker; - final String? pairedTicker; + final AggregateCurrency? pairedCurrency; final bool isFixedRate; final bool willChangeIsSend; @@ -64,7 +62,7 @@ class _ExchangeCurrencySelectionViewState final _searchFocusNode = FocusNode(); final isDesktop = Util.isDesktop; - List _currencies = []; + List _currencies = []; bool _loaded = false; String _searchString = ""; @@ -99,26 +97,7 @@ class _ExchangeCurrencySelectionViewState return result; } - Future> _loadCurrencies() async { - if (widget.pairedTicker == null) { - return await _getCurrencies(); - } - await ExchangeDataLoadingService.instance.initDB(); - final List currencies = - await ExchangeDataLoadingService.instance.isar.currencies - .where() - .filter() - .exchangeNameEqualTo(MajesticBankExchange.exchangeName) - .or() - .exchangeNameStartsWith(TrocadorExchange.exchangeName) - .or() - .exchangeNameStartsWith(NanswapExchange.exchangeName) - .findAll(); - - return _getDistinctCurrenciesFrom(currencies); - } - - Future> _getCurrencies() async { + Future> _loadCurrencies() async { await ExchangeDataLoadingService.instance.initDB(); final currencies = await ExchangeDataLoadingService.instance.isar.currencies @@ -154,53 +133,78 @@ class _ExchangeCurrencySelectionViewState } } - return _getDistinctCurrenciesFrom(currencies); + return await _getDistinctCurrenciesFrom(currencies); } - List _getDistinctCurrenciesFrom(List currencies) { - final List distinctCurrencies = []; + Future> _getDistinctCurrenciesFrom( + List currencies, + ) async { + final Map> groups = {}; + for (final currency in currencies) { - if (!distinctCurrencies.any( - (e) => e.ticker.toLowerCase() == currency.ticker.toLowerCase(), - )) { - distinctCurrencies.add(currency); - } + final key = '${currency.ticker.toLowerCase()}|${currency.getFuzzyNet()}'; + + groups.putIfAbsent(key, () => []).add(currency); } - return distinctCurrencies; - } - List filter(String text) { - if (widget.pairedTicker == null) { - if (text.isEmpty) { - return _currencies; - } + final Set results = {}; + + for (final group in groups.values) { + final items = group + .map((e) => Tuple2(e.exchangeName, e)) + .toList(growable: false); + + results.add(AggregateCurrency(exchangeCurrencyPairs: items)); + } + + if (widget.pairedCurrency != null) { + results.remove(widget.pairedCurrency); + } - return _currencies - .where( - (e) => - e.name.toLowerCase().contains(text.toLowerCase()) || - e.ticker.toLowerCase().contains(text.toLowerCase()), - ) - .toList(); - } else { - if (text.isEmpty) { - return _currencies + final walletCoins = + results .where( - (e) => - e.ticker.toLowerCase() != widget.pairedTicker!.toLowerCase(), + (currency) => + AppConfig.coins + .where( + (coin) => + coin.ticker.toLowerCase() == + currency.ticker.toLowerCase() && + currency.fuzzyNet == coin.ticker.toLowerCase(), + ) + .isNotEmpty, ) .toList(); - } - return _currencies - .where( - (e) => - e.ticker.toLowerCase() != widget.pairedTicker!.toLowerCase() && - (e.name.toLowerCase().contains(text.toLowerCase()) || - e.ticker.toLowerCase().contains(text.toLowerCase())), - ) - .toList(); + final list = results.toList(); + + // sort alphabetically by name + list.sort((a, b) => a.name.compareTo(b.name)); + + // reverse sort walletCoins to prepare for next step + walletCoins.sort((a, b) => b.name.compareTo(a.name)); + + // insert wallet coins at beginning + for (final c in walletCoins) { + list.remove(c); + list.insert(0, c); + } + + return list; + } + + List filter(String text) { + if (text.isEmpty) { + return _currencies.toList(); } + + return _currencies + .where( + (e) => + e.name.toLowerCase().contains(text.toLowerCase()) || + e.ticker.toLowerCase().contains(text.toLowerCase()), + ) + .toList(); } @override @@ -325,40 +329,8 @@ class _ExchangeCurrencySelectionViewState Flexible( child: Builder( builder: (context) { - final coins = AppConfig.coins.where( - (e) => - e.ticker.toLowerCase() != - widget.pairedTicker?.toLowerCase(), - ); - final items = filter(_searchString); - final walletCoins = - items - .where( - (currency) => - coins - .where( - (coin) => - coin.ticker.toLowerCase() == - currency.ticker.toLowerCase(), - ) - .isNotEmpty, - ) - .toList(); - - // sort alphabetically by name - items.sort((a, b) => a.name.compareTo(b.name)); - - // reverse sort walletCoins to prepare for next step - walletCoins.sort((a, b) => b.name.compareTo(a.name)); - - // insert wallet coins at beginning - for (final c in walletCoins) { - items.remove(c); - items.insert(0, c); - } - return RoundedWhiteContainer( padding: const EdgeInsets.all(0), child: ListView.builder( @@ -373,7 +345,9 @@ class _ExchangeCurrencySelectionViewState padding: const EdgeInsets.symmetric(vertical: 4), child: GestureDetector( onTap: () { - Navigator.of(context).pop(items[index]); + final selected = items[index]; + Logging.instance.d("swap selected: $selected"); + Navigator.of(context).pop(selected); }, child: RoundedWhiteContainer( child: Row( diff --git a/lib/pages/exchange_view/exchange_form.dart b/lib/pages/exchange_view/exchange_form.dart index 6976d557b..70671cb5c 100644 --- a/lib/pages/exchange_view/exchange_form.dart +++ b/lib/pages/exchange_view/exchange_form.dart @@ -15,7 +15,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/svg.dart'; -import 'package:isar/isar.dart'; import 'package:tuple/tuple.dart'; import 'package:uuid/uuid.dart'; @@ -23,8 +22,6 @@ import '../../models/exchange/aggregate_currency.dart'; import '../../models/exchange/incomplete_exchange.dart'; import '../../models/exchange/response_objects/estimate.dart'; import '../../models/exchange/response_objects/range.dart'; -import '../../models/isar/exchange_cache/currency.dart'; -import '../../models/isar/exchange_cache/pair.dart'; import '../../models/isar/models/ethereum/eth_contract.dart'; import '../../pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart'; import '../../providers/providers.dart'; @@ -179,38 +176,6 @@ class _ExchangeFormState extends ConsumerState { ?.decimal; } - Future _getAggregateCurrency(Currency currency) async { - final rateType = ref.read(efRateTypeProvider); - final currencies = - await ExchangeDataLoadingService.instance.isar.currencies - .filter() - .group( - (q) => - rateType == ExchangeRateType.fixed - ? q - .rateTypeEqualTo(SupportedRateType.both) - .or() - .rateTypeEqualTo(SupportedRateType.fixed) - : q - .rateTypeEqualTo(SupportedRateType.both) - .or() - .rateTypeEqualTo(SupportedRateType.estimated), - ) - .and() - .tickerEqualTo(currency.ticker, caseSensitive: false) - .and() - .tokenContractEqualTo(currency.tokenContract) - .findAll(); - - final items = [Tuple2(currency.exchangeName, currency)]; - - for (final currency in currencies) { - items.add(Tuple2(currency.exchangeName, currency)); - } - - return AggregateCurrency(exchangeCurrencyPairs: items); - } - void selectSendCurrency() async { final type = ref.read(efRateTypeProvider); final fromTicker = ref.read(efCurrencyPairProvider).send?.ticker ?? ""; @@ -228,20 +193,15 @@ class _ExchangeFormState extends ConsumerState { } final selectedCurrency = await _showCurrencySelectionSheet( - willChange: ref.read(efCurrencyPairProvider).send?.ticker, willChangeIsSend: true, - paired: ref.read(efCurrencyPairProvider).receive?.ticker, + paired: ref.read(efCurrencyPairProvider).receive, isFixedRate: type == ExchangeRateType.fixed, ); if (selectedCurrency != null) { - await showUpdatingExchangeRate( - whileFuture: _getAggregateCurrency(selectedCurrency).then( - (aggregateSelected) => ref - .read(efCurrencyPairProvider) - .setSend(aggregateSelected, notifyListeners: true), - ), - ); + ref + .read(efCurrencyPairProvider) + .setSend(selectedCurrency, notifyListeners: true); } } @@ -254,20 +214,15 @@ class _ExchangeFormState extends ConsumerState { } final selectedCurrency = await _showCurrencySelectionSheet( - willChange: ref.read(efCurrencyPairProvider).receive?.ticker, willChangeIsSend: false, - paired: ref.read(efCurrencyPairProvider).send?.ticker, + paired: ref.read(efCurrencyPairProvider).send, isFixedRate: ref.read(efRateTypeProvider) == ExchangeRateType.fixed, ); if (selectedCurrency != null) { - await showUpdatingExchangeRate( - whileFuture: _getAggregateCurrency(selectedCurrency).then( - (aggregateSelected) => ref - .read(efCurrencyPairProvider) - .setReceive(aggregateSelected, notifyListeners: true), - ), - ); + ref + .read(efCurrencyPairProvider) + .setReceive(selectedCurrency, notifyListeners: true); } } @@ -299,9 +254,8 @@ class _ExchangeFormState extends ConsumerState { _swapLock = false; } - Future _showCurrencySelectionSheet({ - required String? willChange, - required String? paired, + Future _showCurrencySelectionSheet({ + required AggregateCurrency? paired, required bool isFixedRate, required bool willChangeIsSend, }) async { @@ -310,7 +264,7 @@ class _ExchangeFormState extends ConsumerState { final result = isDesktop - ? await showDialog( + ? await showDialog( context: context, builder: (context) { return DesktopDialog( @@ -348,8 +302,7 @@ class _ExchangeFormState extends ConsumerState { context, ).extension()!.background, child: ExchangeCurrencySelectionView( - willChangeTicker: willChange, - pairedTicker: paired, + pairedCurrency: paired, isFixedRate: isFixedRate, willChangeIsSend: willChangeIsSend, ), @@ -368,15 +321,14 @@ class _ExchangeFormState extends ConsumerState { MaterialPageRoute( builder: (_) => ExchangeCurrencySelectionView( - willChangeTicker: willChange, - pairedTicker: paired, + pairedCurrency: paired, isFixedRate: isFixedRate, willChangeIsSend: willChangeIsSend, ), ), ); - if (mounted && result is Currency) { + if (mounted && result is AggregateCurrency) { return result; } else { return null; @@ -769,6 +721,7 @@ class _ExchangeFormState extends ConsumerState { ExchangeDataLoadingService.instance .getAggregateCurrency( widget.contract == null ? coin!.ticker : widget.contract!.symbol, + coin!.ticker.toLowerCase(), ExchangeRateType.estimated, widget.contract?.address, ) diff --git a/lib/services/exchange/exchange_data_loading_service.dart b/lib/services/exchange/exchange_data_loading_service.dart index 80b7c53af..f1a181104 100644 --- a/lib/services/exchange/exchange_data_loading_service.dart +++ b/lib/services/exchange/exchange_data_loading_service.dart @@ -82,6 +82,7 @@ class ExchangeDataLoadingService { pair?.setSend( await getAggregateCurrency( AppConfig.swapDefaults.from, + AppConfig.swapDefaults.fromFuzzyNet, rateType, null, ), @@ -89,7 +90,12 @@ class ExchangeDataLoadingService { ); pair?.setReceive( - await getAggregateCurrency(AppConfig.swapDefaults.to, rateType, null), + await getAggregateCurrency( + AppConfig.swapDefaults.to, + AppConfig.swapDefaults.toFuzzyNet, + rateType, + null, + ), notifyListeners: false, ); } @@ -98,29 +104,54 @@ class ExchangeDataLoadingService { Future getAggregateCurrency( String ticker, + String fuzzyNet, ExchangeRateType rateType, String? contract, ) async { - final currencies = - await ExchangeDataLoadingService.instance.isar.currencies - .filter() - .group( - (q) => - rateType == ExchangeRateType.fixed - ? q - .rateTypeEqualTo(SupportedRateType.both) - .or() - .rateTypeEqualTo(SupportedRateType.fixed) - : q - .rateTypeEqualTo(SupportedRateType.both) - .or() - .rateTypeEqualTo(SupportedRateType.estimated), - ) - .and() - .tickerEqualTo(ticker, caseSensitive: false) - .and() - .tokenContractEqualTo(contract) - .findAll(); + final List currencies; + if (contract != null) { + currencies = + await ExchangeDataLoadingService.instance.isar.currencies + .filter() + .tokenContractEqualTo(contract) + .and() + .group( + (q) => + rateType == ExchangeRateType.fixed + ? q + .rateTypeEqualTo(SupportedRateType.both) + .or() + .rateTypeEqualTo(SupportedRateType.fixed) + : q + .rateTypeEqualTo(SupportedRateType.both) + .or() + .rateTypeEqualTo(SupportedRateType.estimated), + ) + .findAll(); + } else { + currencies = + await ExchangeDataLoadingService.instance.isar.currencies + .filter() + .group( + (q) => + rateType == ExchangeRateType.fixed + ? q + .rateTypeEqualTo(SupportedRateType.both) + .or() + .rateTypeEqualTo(SupportedRateType.fixed) + : q + .rateTypeEqualTo(SupportedRateType.both) + .or() + .rateTypeEqualTo(SupportedRateType.estimated), + ) + .and() + .tickerEqualTo(ticker, caseSensitive: false) + .and() + .tokenContractIsNull() + .findAll(); + } + + currencies.retainWhere((e) => e.getFuzzyNet() == fuzzyNet); final items = currencies .map((e) => Tuple2(e.exchangeName, e)) diff --git a/lib/services/exchange/trocador/trocador_api.dart b/lib/services/exchange/trocador/trocador_api.dart index 9aff6d872..917fee3f3 100644 --- a/lib/services/exchange/trocador/trocador_api.dart +++ b/lib/services/exchange/trocador/trocador_api.dart @@ -56,9 +56,10 @@ abstract class TrocadorAPI { "Content-Type": "application/json", "API-KEY": kTrocadorApiKey, }, - proxyInfo: Prefs.instance.useTor - ? TorService.sharedInstance.getProxyInfo() - : null, + proxyInfo: + Prefs.instance.useTor + ? TorService.sharedInstance.getProxyInfo() + : null, ); code = response.code; @@ -68,10 +69,17 @@ abstract class TrocadorAPI { final json = jsonDecode(response.body); + if (code != 200) { + throw Exception(json["error"] as String? ?? json); + } + return json; } catch (e, s) { - Logging.instance - .e("_makeRequest($uri) HTTP:$code threw: ", error: e, stackTrace: s); + Logging.instance.e( + "_makeRequest($uri) HTTP:$code threw: ", + error: e, + stackTrace: s, + ); rethrow; } } @@ -83,9 +91,7 @@ abstract class TrocadorAPI { final uri = _buildUri( isOnion: isOnion, method: "coins", - params: { - "ref": kTrocadorRefCode, - }, + params: {"ref": kTrocadorRefCode}, ); try { @@ -93,22 +99,15 @@ abstract class TrocadorAPI { if (json is List) { final list = List>.from(json); - final List coins = list - .map( - (e) => TrocadorCoin.fromMap(e), - ) - .toList(); + final List coins = + list.map((e) => TrocadorCoin.fromMap(e)).toList(); return ExchangeResponse(value: coins); } else { throw Exception("unexpected json: $json"); } } catch (e, s) { - Logging.instance.e( - "getCoins exception", - error: e, - stackTrace: s, - ); + Logging.instance.e("getCoins exception", error: e, stackTrace: s); return ExchangeResponse( exception: ExchangeException( e.toString(), @@ -126,10 +125,7 @@ abstract class TrocadorAPI { final uri = _buildUri( isOnion: isOnion, method: "trade", - params: { - "ref": kTrocadorRefCode, - "id": tradeId, - }, + params: {"ref": kTrocadorRefCode, "id": tradeId}, ); try { @@ -138,11 +134,7 @@ abstract class TrocadorAPI { return ExchangeResponse(value: TrocadorTrade.fromMap(map)); } catch (e, s) { - Logging.instance.e( - "getTrade exception", - error: e, - stackTrace: s, - ); + Logging.instance.e("getTrade exception", error: e, stackTrace: s); return ExchangeResponse( exception: ExchangeException( e.toString(), @@ -204,11 +196,7 @@ abstract class TrocadorAPI { required bool isOnion, required Map params, }) async { - final uri = _buildUri( - isOnion: isOnion, - method: "new_rate", - params: params, - ); + final uri = _buildUri(isOnion: isOnion, method: "new_rate", params: params); try { final json = await _makeGetRequest(uri); @@ -216,11 +204,7 @@ abstract class TrocadorAPI { return ExchangeResponse(value: TrocadorRate.fromMap(map)); } catch (e, s) { - Logging.instance.e( - "getNewRate exception", - error: e, - stackTrace: s, - ); + Logging.instance.e("getNewRate exception", error: e, stackTrace: s); return ExchangeResponse( exception: ExchangeException( e.toString(), diff --git a/scripts/app_config/configure_campfire.sh b/scripts/app_config/configure_campfire.sh index 883d67fa0..258058aae 100755 --- a/scripts/app_config/configure_campfire.sh +++ b/scripts/app_config/configure_campfire.sh @@ -62,6 +62,12 @@ final List _supportedCoins = List.unmodifiable([ Firo(CryptoCurrencyNetwork.main), ]); -final ({String from, String to}) _swapDefaults = (from: "BTC", to: "FIRO"); +final ({String from, String fromFuzzyNet, String to, String toFuzzyNet}) +_swapDefaults = ( + from: "BTC", + fromFuzzyNet: "btc", + to: "FIRO", + toFuzzyNet: "firo", +); EOF \ No newline at end of file diff --git a/scripts/app_config/configure_stack_duo.sh b/scripts/app_config/configure_stack_duo.sh index 7d1a7665a..4c871fff3 100755 --- a/scripts/app_config/configure_stack_duo.sh +++ b/scripts/app_config/configure_stack_duo.sh @@ -64,6 +64,12 @@ final List _supportedCoins = List.unmodifiable([ BitcoinFrost(CryptoCurrencyNetwork.test4), ]); -final ({String from, String to}) _swapDefaults = (from: "BTC", to: "XMR"); +final ({String from, String fromFuzzyNet, String to, String toFuzzyNet}) +_swapDefaults = ( + from: "BTC", + fromFuzzyNet: "btc", + to: "XMR", + toFuzzyNet: "xmr", +); EOF \ No newline at end of file diff --git a/scripts/app_config/configure_stack_wallet.sh b/scripts/app_config/configure_stack_wallet.sh index e46420fa0..3268eca0d 100755 --- a/scripts/app_config/configure_stack_wallet.sh +++ b/scripts/app_config/configure_stack_wallet.sh @@ -87,6 +87,12 @@ final List _supportedCoins = List.unmodifiable([ Xelis(CryptoCurrencyNetwork.test), ]); -final ({String from, String to}) _swapDefaults = (from: "BTC", to: "XMR"); +final ({String from, String fromFuzzyNet, String to, String toFuzzyNet}) +_swapDefaults = ( + from: "BTC", + fromFuzzyNet: "btc", + to: "XMR", + toFuzzyNet: "xmr", +); EOF \ No newline at end of file From 397f496e7b37abd7b1cff3f4bce9a69b57143134 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 27 May 2025 13:05:25 -0600 Subject: [PATCH 4/6] clean up swap currency selection list items and add trocador warnings for ltc and firo --- .gitignore | 1 + lib/models/exchange/aggregate_currency.dart | 30 +- .../exchange_currency_selection_view.dart | 71 +++- lib/pages/exchange_view/exchange_form.dart | 93 ++++- .../sub_widgets/exchange_provider_option.dart | 332 +++++++++++------- .../token_view/sub_widgets/token_summary.dart | 28 +- .../wallet_view/desktop_token_view.dart | 116 +++--- .../exchange/trocador/trocador_exchange.dart | 38 ++ lib/widgets/coin_ticker_tag.dart | 26 ++ .../wallet_info_row/wallet_info_row.dart | 107 +++--- 10 files changed, 534 insertions(+), 308 deletions(-) create mode 100644 lib/widgets/coin_ticker_tag.dart diff --git a/.gitignore b/.gitignore index b61c79144..7b550e43e 100644 --- a/.gitignore +++ b/.gitignore @@ -112,3 +112,4 @@ scripts/linux/build/libsecret/subprojects/gi-docgen/.meson-subproject-wrap-hash. crypto_plugins/cs_monero/built_outputs crypto_plugins/cs_monero/build crypto_plugins/*.diff +/devtools_options.yaml diff --git a/lib/models/exchange/aggregate_currency.dart b/lib/models/exchange/aggregate_currency.dart index 580e1b3bf..b2fa09f30 100644 --- a/lib/models/exchange/aggregate_currency.dart +++ b/lib/models/exchange/aggregate_currency.dart @@ -10,11 +10,12 @@ import 'package:tuple/tuple.dart'; +import '../../services/exchange/trocador/trocador_exchange.dart'; import '../isar/exchange_cache/currency.dart'; import '../isar/exchange_cache/pair.dart'; class AggregateCurrency { - final Map _map = {}; + final Map _map = {}; AggregateCurrency({ required List> exchangeCurrencyPairs, @@ -32,17 +33,26 @@ class AggregateCurrency { String? networkFor(String exchangeName) => forExchange(exchangeName)?.network; - String get ticker => _map.values.first!.ticker; + String get ticker => _map.values.first.ticker; - String get name => _map.values.first!.name; + String get name { + if (_map.values.length > 2) { + return _map.values + .firstWhere((e) => e.exchangeName != TrocadorExchange.exchangeName) + .name; + } + + // trocador hack + return _map.values.first.name.split(" (Mainnet").first; + } - String get image => _map.values.first!.image; + String get image => _map.values.first.image; - SupportedRateType get rateType => _map.values.first!.rateType; + SupportedRateType get rateType => _map.values.first.rateType; - bool get isStackCoin => _map.values.first!.isStackCoin; + bool get isStackCoin => _map.values.first.isStackCoin; - String get fuzzyNet => _map.values.first!.getFuzzyNet(); + String get fuzzyNet => _map.values.first.getFuzzyNet(); @override String toString() { @@ -60,11 +70,11 @@ class AggregateCurrency { other.ticker == ticker && other._map.isNotEmpty && other._map.length == _map.length && - other._map.values.first!.getFuzzyNet() == - _map.values.first!.getFuzzyNet(); + other._map.values.first.getFuzzyNet() == + _map.values.first.getFuzzyNet(); } @override int get hashCode => - Object.hash(ticker, _map.values.first!.getFuzzyNet(), _map.length); + Object.hash(ticker, _map.values.first.getFuzzyNet(), _map.length); } diff --git a/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart b/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart index 291a61781..ce861d560 100644 --- a/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart +++ b/lib/pages/exchange_view/exchange_coin_selection/exchange_currency_selection_view.dart @@ -29,6 +29,7 @@ import '../../../utilities/prefs.dart'; import '../../../utilities/text_styles.dart'; import '../../../utilities/util.dart'; import '../../../widgets/background.dart'; +import '../../../widgets/coin_ticker_tag.dart'; import '../../../widgets/conditional_parent.dart'; import '../../../widgets/custom_buttons/app_bar_icon_button.dart'; import '../../../widgets/custom_loading_overlay.dart'; @@ -338,9 +339,8 @@ class _ExchangeCurrencySelectionViewState primary: isDesktop ? false : null, itemCount: items.length, itemBuilder: (builderContext, index) { - final bool hasImageUrl = items[index].image.startsWith( - "http", - ); + final image = items[index].image; + final hasImageUrl = image.startsWith("http"); return Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: GestureDetector( @@ -363,18 +363,12 @@ class _ExchangeCurrencySelectionViewState ticker: items[index].ticker, size: 24, ) - // ? getIconForTicker( - // items[index].ticker, - // size: 24, - // ) : hasImageUrl - ? SvgPicture.network( - items[index].image, - width: 24, - height: 24, - placeholderBuilder: - (_) => - const LoadingIndicator(), + ? _NetImage( + url: image, + key: ValueKey( + image + items[index].fuzzyNet, + ), ) : const SizedBox( width: 24, @@ -387,11 +381,29 @@ class _ExchangeCurrencySelectionViewState crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - items[index].name, - style: STextStyles.largeMedium14( - context, - ), + Row( + children: [ + Text( + items[index].name, + style: STextStyles.largeMedium14( + context, + ), + ), + if (items[index].ticker + .toLowerCase() != + items[index].fuzzyNet + .toLowerCase()) + Padding( + padding: const EdgeInsets.only( + left: 12, + ), + child: CoinTickerTag( + ticker: + items[index].fuzzyNet + .toUpperCase(), + ), + ), + ], ), const SizedBox(height: 2), Text( @@ -425,3 +437,24 @@ class _ExchangeCurrencySelectionViewState ); } } + +class _NetImage extends StatelessWidget { + const _NetImage({super.key, required this.url}); + + final String url; + + @override + Widget build(BuildContext context) { + if (url.endsWith(".svg")) { + return SvgPicture.network( + key: key, + url, + width: 24, + height: 24, + placeholderBuilder: (_) => const LoadingIndicator(), + ); + } else { + return Image.network(url, width: 24, height: 24, key: key); + } + } +} diff --git a/lib/pages/exchange_view/exchange_form.dart b/lib/pages/exchange_view/exchange_form.dart index 70671cb5c..488a74674 100644 --- a/lib/pages/exchange_view/exchange_form.dart +++ b/lib/pages/exchange_view/exchange_form.dart @@ -22,6 +22,7 @@ import '../../models/exchange/aggregate_currency.dart'; import '../../models/exchange/incomplete_exchange.dart'; import '../../models/exchange/response_objects/estimate.dart'; import '../../models/exchange/response_objects/range.dart'; +import '../../models/isar/exchange_cache/currency.dart'; import '../../models/isar/models/ethereum/eth_contract.dart'; import '../../pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart'; import '../../providers/providers.dart'; @@ -47,6 +48,7 @@ import '../../widgets/desktop/desktop_dialog.dart'; import '../../widgets/desktop/desktop_dialog_close_button.dart'; import '../../widgets/desktop/primary_button.dart'; import '../../widgets/desktop/secondary_button.dart'; +import '../../widgets/dialogs/basic_dialog.dart'; import '../../widgets/rounded_container.dart'; import '../../widgets/rounded_white_container.dart'; import '../../widgets/stack_dialog.dart'; @@ -343,9 +345,80 @@ class _ExchangeFormState extends ConsumerState { update(); } + Future _checkTrocadorWarning(Currency from, Currency to) async { + final Set warnings = {}; + + final firoWarning = + TrocadorExchange.checkFiro(from) ?? TrocadorExchange.checkFiro(to); + final ltcWarning = + TrocadorExchange.checkLtc(from) ?? TrocadorExchange.checkLtc(to); + + if (firoWarning != null) warnings.add(firoWarning); + if (ltcWarning != null) warnings.add(ltcWarning); + + if (warnings.isNotEmpty) { + final title = warnings.map((e) => e.message).join(" and "); + final message = warnings.map((e) => e.messageDetail).join(" "); + + final result = await showDialog( + context: context, + builder: (context) { + return BasicDialog( + title: title, + message: message, + canPopWithBackButton: true, + flex: true, + desktopHeight: 400, + leftButton: SecondaryButton( + label: "Cancel", + buttonHeight: isDesktop ? ButtonHeight.l : null, + onPressed: () => Navigator.of(context).pop(false), + ), + rightButton: PrimaryButton( + label: "Continue", + buttonHeight: isDesktop ? ButtonHeight.l : null, + onPressed: () => Navigator.of(context).pop(true), + ), + ); + }, + ); + + return result == true; + } else { + return true; + } + } + void onExchangePressed() async { final exchangeName = ref.read(efExchangeProvider).name; + final fromCurrency = ref + .read(efCurrencyPairProvider) + .send + ?.forExchange(exchangeName); + final toCurrency = ref + .read(efCurrencyPairProvider) + .receive + ?.forExchange(exchangeName); + + if (fromCurrency == null || toCurrency == null) { + await showDialog( + context: context, + builder: + (context) => const StackOkDialog( + title: "Missing currency!", + message: "This should not happen. Please contact support", + ), + ); + + return; + } + + if (exchangeName == TrocadorExchange.exchangeName) { + final canContinue = await _checkTrocadorWarning(fromCurrency, toCurrency); + if (!canContinue) return; + } + final rateType = ref.read(efRateTypeProvider); final fromTicker = ref.read(efCurrencyPairProvider).send?.ticker ?? ""; final fromNetwork = ref @@ -361,15 +434,17 @@ class _ExchangeFormState extends ConsumerState { final sendAmount = ref.read(efSendAmountProvider)!; if (rateType == ExchangeRateType.fixed && toTicker.toUpperCase() == "WOW") { - await showDialog( - context: context, - builder: - (context) => const StackOkDialog( - title: "WOW error", - message: - "Wownero is temporarily disabled as a receiving currency for fixed rate trades due to network issues", - ), - ); + if (mounted) { + await showDialog( + context: context, + builder: + (context) => const StackOkDialog( + title: "WOW error", + message: + "Wownero is temporarily disabled as a receiving currency for fixed rate trades due to network issues", + ), + ); + } return; } diff --git a/lib/pages/exchange_view/sub_widgets/exchange_provider_option.dart b/lib/pages/exchange_view/sub_widgets/exchange_provider_option.dart index 5b11876e8..8b56ae213 100644 --- a/lib/pages/exchange_view/sub_widgets/exchange_provider_option.dart +++ b/lib/pages/exchange_view/sub_widgets/exchange_provider_option.dart @@ -14,10 +14,12 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import '../../../app_config.dart'; +import '../../../models/exchange/aggregate_currency.dart'; import '../../../models/exchange/response_objects/estimate.dart'; import '../../../providers/exchange/exchange_form_state_provider.dart'; import '../../../providers/global/locale_provider.dart'; import '../../../services/exchange/exchange.dart'; +import '../../../services/exchange/trocador/trocador_exchange.dart'; import '../../../themes/stack_colors.dart'; import '../../../utilities/amount/amount.dart'; import '../../../utilities/amount/amount_formatter.dart'; @@ -30,6 +32,9 @@ import '../../../utilities/util.dart'; import '../../../wallets/crypto_currency/crypto_currency.dart'; import '../../../widgets/animated_text.dart'; import '../../../widgets/conditional_parent.dart'; +import '../../../widgets/custom_buttons/blue_text_button.dart'; +import '../../../widgets/desktop/primary_button.dart'; +import '../../../widgets/dialogs/basic_dialog.dart'; import '../../../widgets/exchange/trocador/trocador_kyc_info_button.dart'; import '../../../widgets/exchange/trocador/trocador_rating_type_enum.dart'; @@ -54,18 +59,26 @@ class _ExchangeOptionState extends ConsumerState { @override Widget build(BuildContext context) { - final sendCurrency = - ref.watch(efCurrencyPairProvider.select((value) => value.send)); - final receivingCurrency = - ref.watch(efCurrencyPairProvider.select((value) => value.receive)); + final sendCurrency = ref.watch( + efCurrencyPairProvider.select((value) => value.send), + ); + final receivingCurrency = ref.watch( + efCurrencyPairProvider.select((value) => value.receive), + ); final reversed = ref.watch(efReversedProvider); - final amount = reversed - ? ref.watch(efReceiveAmountProvider) - : ref.watch(efSendAmountProvider); + final amount = + reversed + ? ref.watch(efReceiveAmountProvider) + : ref.watch(efSendAmountProvider); final data = ref.watch(efEstimatesListProvider(widget.exchange.name)); final estimates = data?.item1.value; + final pair = + sendCurrency != null && receivingCurrency != null + ? (from: sendCurrency, to: receivingCurrency) + : null; + return AnimatedSize( duration: const Duration(milliseconds: 500), curve: Curves.easeInOutCubicEmphasized, @@ -76,6 +89,7 @@ class _ExchangeOptionState extends ConsumerState { return _ProviderOption( exchange: widget.exchange, estimate: null, + pair: pair, rateString: "", loadingString: true, ); @@ -94,10 +108,10 @@ class _ExchangeOptionState extends ConsumerState { int decimals; try { - decimals = AppConfig.getCryptoCurrencyForTicker( - receivingCurrency.ticker, - )! - .fractionDigits; + decimals = + AppConfig.getCryptoCurrencyForTicker( + receivingCurrency.ticker, + )!.fractionDigits; } catch (_) { decimals = 8; // some reasonable alternative } @@ -123,46 +137,50 @@ class _ExchangeOptionState extends ConsumerState { final String rateString; if (coin != null) { - rateString = "1 ${sendCurrency.ticker.toUpperCase()} " + rateString = + "1 ${sendCurrency.ticker.toUpperCase()} " "~ ${ref.watch(pAmountFormatter(coin)).format(rate)}"; } else { final formatter = AmountFormatter( unit: AmountUnit.normal, locale: ref.watch( - localeServiceChangeNotifierProvider - .select((value) => value.locale), + localeServiceChangeNotifierProvider.select( + (value) => value.locale, + ), ), coin: Bitcoin( CryptoCurrencyNetwork.main, ), // some sane default maxDecimals: 8, // some sane default ); - rateString = "1 ${sendCurrency.ticker.toUpperCase()} " + rateString = + "1 ${sendCurrency.ticker.toUpperCase()} " "~ ${formatter.format(rate, withUnitName: false)}" " ${receivingCurrency.ticker.toUpperCase()}"; } return ConditionalParent( condition: i > 0, - builder: (child) => Column( - mainAxisSize: MainAxisSize.min, - children: [ - isDesktop - ? Container( - height: 1, - color: Theme.of(context) - .extension()! - .background, - ) - : const SizedBox( - height: 16, - ), - child, - ], - ), + builder: + (child) => Column( + mainAxisSize: MainAxisSize.min, + children: [ + isDesktop + ? Container( + height: 1, + color: + Theme.of(context) + .extension()! + .background, + ) + : const SizedBox(height: 16), + child, + ], + ), child: _ProviderOption( key: Key(widget.exchange.name + e.exchangeProvider), exchange: widget.exchange, + pair: pair, estimate: e, rateString: rateString, kycRating: e.kycRating, @@ -189,16 +207,18 @@ class _ExchangeOptionState extends ConsumerState { message ??= "Amount too large"; } } else if (data?.item1.value == null) { - final rateType = ref.watch(efRateTypeProvider) == - ExchangeRateType.estimated - ? "estimated" - : "fixed"; + final rateType = + ref.watch(efRateTypeProvider) == + ExchangeRateType.estimated + ? "estimated" + : "fixed"; message ??= "Pair unavailable on $rateType rate flow"; } return _ProviderOption( exchange: widget.exchange, estimate: null, + pair: pair, rateString: message ?? "Failed to fetch rate", rateColor: Theme.of(context).extension()!.textError, @@ -211,6 +231,7 @@ class _ExchangeOptionState extends ConsumerState { return _ProviderOption( exchange: widget.exchange, estimate: null, + pair: pair, rateString: "n/a", ); } @@ -225,6 +246,7 @@ class _ProviderOption extends ConsumerStatefulWidget { super.key, required this.exchange, required this.estimate, + required this.pair, required this.rateString, this.kycRating, this.loadingString = false, @@ -233,6 +255,7 @@ class _ProviderOption extends ConsumerStatefulWidget { final Exchange exchange; final Estimate? estimate; + final ({AggregateCurrency from, AggregateCurrency to})? pair; final String rateString; final String? kycRating; final bool loadingString; @@ -246,12 +269,59 @@ class _ProviderOptionState extends ConsumerState<_ProviderOption> { final isDesktop = Util.isDesktop; late final String _id; + final Set _warnings = {}; + + bool _warningLock = false; + void _showNoSparkWarning() async { + if (_warningLock) return; + _warningLock = true; + try { + await showDialog( + context: context, + builder: (context) { + return BasicDialog( + title: _warnings.map((e) => e.message).join(" and "), + message: _warnings.map((e) => e.messageDetail).join(" "), + canPopWithBackButton: true, + flex: true, + desktopHeight: 400, + rightButton: PrimaryButton( + label: "OK", + buttonHeight: isDesktop ? ButtonHeight.l : null, + onPressed: Navigator.of(context).pop, + ), + ); + }, + ); + } finally { + _warningLock = false; + } + } @override void initState() { + super.initState(); _id = "${widget.exchange.name} (${widget.estimate?.exchangeProvider ?? widget.exchange.name})"; - super.initState(); + + if (widget.exchange.name == TrocadorExchange.exchangeName && + widget.pair != null) { + final from = widget.pair!.from.forExchange(widget.exchange.name); + final to = widget.pair!.to.forExchange(widget.exchange.name); + + if (from != null) { + final firoWarning = TrocadorExchange.checkFiro(from); + if (firoWarning != null) _warnings.add(firoWarning); + final ltcWarning = TrocadorExchange.checkLtc(from); + if (ltcWarning != null) _warnings.add(ltcWarning); + } + if (to != null) { + final firoWarning = TrocadorExchange.checkFiro(to); + if (firoWarning != null) _warnings.add(firoWarning); + final ltcWarning = TrocadorExchange.checkLtc(to); + if (ltcWarning != null) _warnings.add(ltcWarning); + } + } } @override @@ -265,10 +335,9 @@ class _ProviderOptionState extends ConsumerState<_ProviderOption> { return ConditionalParent( condition: isDesktop, - builder: (child) => MouseRegion( - cursor: SystemMouseCursors.click, - child: child, - ), + builder: + (child) => + MouseRegion(cursor: SystemMouseCursors.click, child: child), child: GestureDetector( onTap: () { ref.read(efExchangeProvider.notifier).state = widget.exchange; @@ -289,127 +358,138 @@ class _ProviderOptionState extends ConsumerState<_ProviderOption> { child: Padding( padding: EdgeInsets.only(top: isDesktop ? 20.0 : 15.0), child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, + activeColor: + Theme.of( + context, + ).extension()!.radioButtonIconEnabled, value: _id, groupValue: groupValue, onChanged: (_) { ref.read(efExchangeProvider.notifier).state = widget.exchange; ref - .read(efExchangeProviderNameProvider.notifier) - .state = - widget.estimate?.exchangeProvider ?? - widget.exchange.name; + .read(efExchangeProviderNameProvider.notifier) + .state = widget.estimate?.exchangeProvider ?? + widget.exchange.name; }, ), ), ), - const SizedBox( - width: 14, - ), + const SizedBox(width: 14), Padding( padding: const EdgeInsets.only(top: 5.0), child: SizedBox( width: isDesktop ? 32 : 24, height: isDesktop ? 32 : 24, - child: widget.estimate?.exchangeProviderLogo != null && - widget - .estimate! - .exchangeProviderLogo! - .isNotEmpty - ? ClipRRect( - borderRadius: BorderRadius.circular(5), - child: Image.network( - widget.estimate!.exchangeProviderLogo!, - loadingBuilder: ( - context, - child, - loadingProgress, - ) { - if (loadingProgress == null) { - return child; - } else { - return const Center( - child: - CircularProgressIndicator(), - ); - } - }, - errorBuilder: (context, error, stackTrace) { - return SvgPicture.asset( - Assets.exchange.getIconFor( - exchangeName: widget.exchange.name, + child: + widget.estimate?.exchangeProviderLogo != null && + widget + .estimate! + .exchangeProviderLogo! + .isNotEmpty + ? ClipRRect( + borderRadius: BorderRadius.circular(5), + child: Image.network( + widget.estimate!.exchangeProviderLogo!, + loadingBuilder: ( + context, + child, + loadingProgress, + ) { + if (loadingProgress == null) { + return child; + } else { + return const Center( + child: CircularProgressIndicator(), + ); + } + }, + errorBuilder: (context, error, stackTrace) { + return SvgPicture.asset( + Assets.exchange.getIconFor( + exchangeName: widget.exchange.name, + ), + width: isDesktop ? 32 : 24, + height: isDesktop ? 32 : 24, + ); + }, + width: isDesktop ? 32 : 24, + height: isDesktop ? 32 : 24, + ), + ) + : SvgPicture.asset( + Assets.exchange.getIconFor( + exchangeName: widget.exchange.name, + ), + width: isDesktop ? 32 : 24, + height: isDesktop ? 32 : 24, ), - width: isDesktop ? 32 : 24, - height: isDesktop ? 32 : 24, - ); - }, - width: isDesktop ? 32 : 24, - height: isDesktop ? 32 : 24, - ), - ) - : SvgPicture.asset( - Assets.exchange.getIconFor( - exchangeName: widget.exchange.name, - ), - width: isDesktop ? 32 : 24, - height: isDesktop ? 32 : 24, - ), ), ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), Expanded( child: Column( mainAxisAlignment: MainAxisAlignment.start, mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - widget.estimate?.exchangeProvider ?? - widget.exchange.name, - style: STextStyles.titleBold12(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark2, + ConditionalParent( + condition: _warnings.isNotEmpty, + builder: + (child) => Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + child, + CustomTextButton( + text: _warnings.first.value, + onTap: () { + _showNoSparkWarning(); + }, + ), + ], + ), + child: Text( + widget.estimate?.exchangeProvider ?? + widget.exchange.name, + style: STextStyles.titleBold12(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark2, + ), ), ), widget.loadingString ? AnimatedText( - stringsToLoopThrough: const [ - "Loading", - "Loading.", - "Loading..", - "Loading...", - ], - style: - STextStyles.itemSubtitle12(context).copyWith( - color: Theme.of(context) - .extension()! - .textSubtitle1, - ), - ) + stringsToLoopThrough: const [ + "Loading", + "Loading.", + "Loading..", + "Loading...", + ], + style: STextStyles.itemSubtitle12(context).copyWith( + color: + Theme.of( + context, + ).extension()!.textSubtitle1, + ), + ) : Text( - widget.rateString, - style: - STextStyles.itemSubtitle12(context).copyWith( - color: widget.rateColor ?? - Theme.of(context) - .extension()! - .textSubtitle1, - ), + widget.rateString, + style: STextStyles.itemSubtitle12(context).copyWith( + color: + widget.rateColor ?? + Theme.of( + context, + ).extension()!.textSubtitle1, ), + ), ], ), ), if (widget.kycRating != null) TrocadorKYCInfoButton( - kycType: TrocadorKYCType.fromString( - widget.kycRating!, - ), + kycType: TrocadorKYCType.fromString(widget.kycRating!), ), ], ), diff --git a/lib/pages/token_view/sub_widgets/token_summary.dart b/lib/pages/token_view/sub_widgets/token_summary.dart index 9bebfda49..2c09077cb 100644 --- a/lib/pages/token_view/sub_widgets/token_summary.dart +++ b/lib/pages/token_view/sub_widgets/token_summary.dart @@ -34,6 +34,7 @@ import '../../../wallets/crypto_currency/crypto_currency.dart'; import '../../../wallets/isar/providers/eth/current_token_wallet_provider.dart'; import '../../../wallets/isar/providers/eth/token_balance_provider.dart'; import '../../../wallets/isar/providers/wallet_info_provider.dart'; +import '../../../widgets/coin_ticker_tag.dart'; import '../../../widgets/conditional_parent.dart'; import '../../../widgets/rounded_container.dart'; import '../../buy_view/buy_in_wallet_view.dart'; @@ -121,7 +122,11 @@ class TokenSummary extends ConsumerWidget { ), ), const SizedBox(width: 10), - CoinTickerTag(walletId: walletId), + CoinTickerTag( + ticker: ref.watch( + pWalletCoin(walletId).select((s) => s.ticker), + ), + ), ], ), if (price != null) const SizedBox(height: 6), @@ -325,24 +330,3 @@ class TokenOptionsButton extends StatelessWidget { ); } } - -class CoinTickerTag extends ConsumerWidget { - const CoinTickerTag({super.key, required this.walletId}); - - final String walletId; - - @override - Widget build(BuildContext context, WidgetRef ref) { - return RoundedContainer( - padding: const EdgeInsets.symmetric(vertical: 2, horizontal: 4), - radiusMultiplier: 0.25, - color: Theme.of(context).extension()!.ethTagBG, - child: Text( - ref.watch(pWalletCoin(walletId)).ticker, - style: STextStyles.w600_12(context).copyWith( - color: Theme.of(context).extension()!.ethTagText, - ), - ), - ); - } -} diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_token_view.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_token_view.dart index e30245c4d..577d4e322 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_token_view.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/desktop_token_view.dart @@ -12,13 +12,10 @@ import 'package:event_bus/event_bus.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; + import '../../../pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart'; -import '../../../pages/token_view/sub_widgets/token_summary.dart'; import '../../../pages/token_view/sub_widgets/token_transaction_list_widget.dart'; import '../../../pages/wallet_view/transaction_views/tx_v2/all_transactions_v2_view.dart'; -import 'sub_widgets/desktop_wallet_features.dart'; -import 'sub_widgets/desktop_wallet_summary.dart'; -import 'sub_widgets/my_wallet.dart'; import '../../../providers/providers.dart'; import '../../../services/event_bus/events/global/wallet_sync_status_changed_event.dart'; import '../../../themes/stack_colors.dart'; @@ -26,20 +23,20 @@ import '../../../utilities/assets.dart'; import '../../../utilities/text_styles.dart'; import '../../../wallets/isar/providers/eth/current_token_wallet_provider.dart'; import '../../../wallets/isar/providers/wallet_info_provider.dart'; +import '../../../widgets/coin_ticker_tag.dart'; import '../../../widgets/custom_buttons/blue_text_button.dart'; import '../../../widgets/desktop/desktop_app_bar.dart'; import '../../../widgets/desktop/desktop_scaffold.dart'; import '../../../widgets/desktop/secondary_button.dart'; import '../../../widgets/icon_widgets/eth_token_icon.dart'; import '../../../widgets/rounded_white_container.dart'; +import 'sub_widgets/desktop_wallet_features.dart'; +import 'sub_widgets/desktop_wallet_summary.dart'; +import 'sub_widgets/my_wallet.dart'; /// [eventBus] should only be set during testing class DesktopTokenView extends ConsumerStatefulWidget { - const DesktopTokenView({ - super.key, - required this.walletId, - this.eventBus, - }); + const DesktopTokenView({super.key, required this.walletId, this.eventBus}); static const String routeName = "/desktopTokenView"; @@ -57,9 +54,10 @@ class _DesktopTokenViewState extends ConsumerState { @override void initState() { - initialSyncStatus = ref.read(pCurrentTokenWallet)!.refreshMutex.isLocked - ? WalletSyncStatus.syncing - : WalletSyncStatus.synced; + initialSyncStatus = + ref.read(pCurrentTokenWallet)!.refreshMutex.isLocked + ? WalletSyncStatus.syncing + : WalletSyncStatus.synced; super.initState(); } @@ -79,32 +77,26 @@ class _DesktopTokenViewState extends ConsumerState { flex: 3, child: Row( children: [ - const SizedBox( - width: 32, - ), + const SizedBox(width: 32), SecondaryButton( - padding: const EdgeInsets.only( - left: 12, - right: 18, - ), + padding: const EdgeInsets.only(left: 12, right: 18), buttonHeight: ButtonHeight.s, label: ref.watch(pWalletName(widget.walletId)), icon: SvgPicture.asset( Assets.svg.arrowLeft, width: 18, height: 18, - color: Theme.of(context) - .extension()! - .topNavIconPrimary, + color: + Theme.of( + context, + ).extension()!.topNavIconPrimary, ), onPressed: () { ref.refresh(feeSheetSessionCacheProvider); Navigator.of(context).pop(); }, ), - const SizedBox( - width: 15, - ), + const SizedBox(width: 15), ], ), ), @@ -120,9 +112,7 @@ class _DesktopTokenViewState extends ConsumerState { ), size: 32, ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Text( ref.watch( pCurrentTokenWallet.select( @@ -131,11 +121,11 @@ class _DesktopTokenViewState extends ConsumerState { ), style: STextStyles.desktopH3(context), ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), CoinTickerTag( - walletId: widget.walletId, + ticker: ref.watch( + pWalletCoin(widget.walletId).select((s) => s.ticker), + ), ), ], ), @@ -159,30 +149,25 @@ class _DesktopTokenViewState extends ConsumerState { ), size: 40, ), - const SizedBox( - width: 10, - ), + const SizedBox(width: 10), DesktopWalletSummary( walletId: widget.walletId, isToken: true, - initialSyncStatus: ref - .watch(pWallets) - .getWallet(widget.walletId) - .refreshMutex - .isLocked - ? WalletSyncStatus.syncing - : WalletSyncStatus.synced, + initialSyncStatus: + ref + .watch(pWallets) + .getWallet(widget.walletId) + .refreshMutex + .isLocked + ? WalletSyncStatus.syncing + : WalletSyncStatus.synced, ), const Spacer(), - DesktopWalletFeatures( - walletId: widget.walletId, - ), + DesktopWalletFeatures(walletId: widget.walletId), ], ), ), - const SizedBox( - height: 24, - ), + const SizedBox(height: 24), Row( children: [ SizedBox( @@ -190,26 +175,27 @@ class _DesktopTokenViewState extends ConsumerState { child: Text( "My wallet", style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconLeft, + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconLeft, ), ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Recent transactions", - style: - STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textFieldActiveSearchIconLeft, + style: STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of(context) + .extension()! + .textFieldActiveSearchIconLeft, ), ), CustomTextButton( @@ -233,9 +219,7 @@ class _DesktopTokenViewState extends ConsumerState { ), ], ), - const SizedBox( - height: 14, - ), + const SizedBox(height: 14), Expanded( child: Row( crossAxisAlignment: CrossAxisAlignment.start, @@ -251,13 +235,9 @@ class _DesktopTokenViewState extends ConsumerState { ), ), ), - const SizedBox( - width: 16, - ), + const SizedBox(width: 16), Expanded( - child: TokenTransactionsList( - walletId: widget.walletId, - ), + child: TokenTransactionsList(walletId: widget.walletId), ), ], ), diff --git a/lib/services/exchange/trocador/trocador_exchange.dart b/lib/services/exchange/trocador/trocador_exchange.dart index 3bae214b6..ffb217a9f 100644 --- a/lib/services/exchange/trocador/trocador_exchange.dart +++ b/lib/services/exchange/trocador/trocador_exchange.dart @@ -36,6 +36,22 @@ class TrocadorExchange extends Exchange { static const onlySupportedNetwork = "Mainnet"; + static ProviderWarning? checkFiro(Currency currency) { + if (currency.ticker.toLowerCase() == "firo" && + currency.name.contains("No Spark")) { + return ProviderWarning.noSpark; + } + return null; + } + + static ProviderWarning? checkLtc(Currency currency) { + if (currency.ticker.toLowerCase() == "ltc" && + currency.name.contains("not MW")) { + return ProviderWarning.noMWEB; + } + return null; + } + @override Future> createTrade({ required String from, @@ -421,3 +437,25 @@ class TrocadorExchange extends Exchange { @override bool get supportsTor => true; } + +enum ProviderWarning { + noSpark("NO SPARK"), + noMWEB("NO MW"); + + final String value; + const ProviderWarning(this.value); + + String get message => switch (this) { + ProviderWarning.noSpark => "No Spark", + ProviderWarning.noMWEB => "No MimbleWimble", + }; + + String get messageDetail => switch (this) { + ProviderWarning.noSpark => + "Trocador does not support Firo transactions involving Spark addresses," + " including both sending to and receiving from them.", + ProviderWarning.noMWEB => + "Trocador does not support Litecoin transactions involving MWEB " + "(MimbleWimble Extension Block) addresses.", + }; +} diff --git a/lib/widgets/coin_ticker_tag.dart b/lib/widgets/coin_ticker_tag.dart new file mode 100644 index 000000000..f15e6548d --- /dev/null +++ b/lib/widgets/coin_ticker_tag.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; + +import '../themes/stack_colors.dart'; +import '../utilities/text_styles.dart'; +import 'rounded_container.dart'; + +class CoinTickerTag extends StatelessWidget { + const CoinTickerTag({super.key, required this.ticker}); + + final String ticker; + + @override + Widget build(BuildContext context) { + return RoundedContainer( + padding: const EdgeInsets.symmetric(vertical: 2, horizontal: 4), + radiusMultiplier: 0.25, + color: Theme.of(context).extension()!.ethTagBG, + child: Text( + ticker, + style: STextStyles.w600_12(context).copyWith( + color: Theme.of(context).extension()!.ethTagText, + ), + ), + ); + } +} diff --git a/lib/widgets/wallet_info_row/wallet_info_row.dart b/lib/widgets/wallet_info_row/wallet_info_row.dart index 2cc35b7aa..381d0e0d5 100644 --- a/lib/widgets/wallet_info_row/wallet_info_row.dart +++ b/lib/widgets/wallet_info_row/wallet_info_row.dart @@ -12,12 +12,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../models/isar/models/ethereum/eth_contract.dart'; -import '../../pages/token_view/sub_widgets/token_summary.dart'; -import '../../providers/db/main_db_provider.dart'; import '../../providers/providers.dart'; import '../../themes/stack_colors.dart'; import '../../utilities/text_styles.dart'; import '../../utilities/util.dart'; +import '../../wallets/isar/providers/wallet_info_provider.dart'; +import '../coin_ticker_tag.dart'; import '../custom_buttons/blue_text_button.dart'; import 'sub_widgets/wallet_info_row_balance.dart'; import 'sub_widgets/wallet_info_row_coin_icon.dart'; @@ -43,8 +43,9 @@ class WalletInfoRow extends ConsumerWidget { EthContract? contract; if (contractAddress != null) { contract = ref.watch( - mainDBProvider - .select((value) => value.getEthContractSync(contractAddress!)), + mainDBProvider.select( + (value) => value.getEthContractSync(contractAddress!), + ), ); } @@ -63,39 +64,40 @@ class WalletInfoRow extends ConsumerWidget { coin: wallet.info.coin, contractAddress: contractAddress, ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), contract != null ? Row( - children: [ - Text( - contract.name, - style: - STextStyles.desktopTextExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textDark, - ), - ), - const SizedBox( - width: 4, + children: [ + Text( + contract.name, + style: STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, ), - CoinTickerTag( - walletId: walletId, + ), + const SizedBox(width: 4), + CoinTickerTag( + ticker: ref.watch( + pWalletCoin(walletId).select((s) => s.ticker), ), - ], - ) - : Text( - wallet.info.name, - style: STextStyles.desktopTextExtraSmall(context) - .copyWith( - color: Theme.of(context) - .extension()! - .textDark, ), + ], + ) + : Text( + wallet.info.name, + style: STextStyles.desktopTextExtraSmall( + context, + ).copyWith( + color: + Theme.of( + context, + ).extension()!.textDark, ), + ), ], ), ), @@ -129,36 +131,33 @@ class WalletInfoRow extends ConsumerWidget { coin: wallet.info.coin, contractAddress: contractAddress, ), - const SizedBox( - width: 12, - ), + const SizedBox(width: 12), Expanded( child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ - contract != null - ? Row( - children: [ - Text( - contract.name, - style: STextStyles.titleBold12(context), - ), - const SizedBox( - width: 4, - ), - CoinTickerTag( - walletId: walletId, - ), - ], - ) - : Text( - wallet.info.name, + if (contract != null) + Row( + children: [ + Text( + contract.name, style: STextStyles.titleBold12(context), ), - const SizedBox( - height: 2, - ), + const SizedBox(width: 4), + CoinTickerTag( + ticker: ref.watch( + pWalletCoin(walletId).select((s) => s.ticker), + ), + ), + ], + ) + else + Text( + wallet.info.name, + style: STextStyles.titleBold12(context), + ), + const SizedBox(height: 2), WalletInfoRowBalance( walletId: walletId, contractAddress: contractAddress, From 24c022aaab601ec6896d27b72651fc3cc06facb0 Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 27 May 2025 13:26:12 -0600 Subject: [PATCH 5/6] pass full currency into incomplete exchange model --- lib/models/exchange/incomplete_exchange.dart | 19 ++++--- lib/pages/exchange_view/exchange_form.dart | 23 ++------ .../exchange_step_views/step_3_view.dart | 57 ++++++++++--------- .../exchange_steps/step_scaffold.dart | 6 +- 4 files changed, 49 insertions(+), 56 deletions(-) diff --git a/lib/models/exchange/incomplete_exchange.dart b/lib/models/exchange/incomplete_exchange.dart index 3608b8b05..86441bc90 100644 --- a/lib/models/exchange/incomplete_exchange.dart +++ b/lib/models/exchange/incomplete_exchange.dart @@ -12,14 +12,16 @@ import 'package:decimal/decimal.dart'; import 'package:flutter/foundation.dart'; import '../../utilities/enums/exchange_rate_type_enum.dart'; +import '../isar/exchange_cache/currency.dart'; import 'response_objects/estimate.dart'; import 'response_objects/trade.dart'; class IncompleteExchangeModel extends ChangeNotifier { - final String sendTicker; - final String? sendNetwork; - final String receiveTicker; - final String? receiveNetwork; + final Currency sendCurrency; + final Currency receiveCurrency; + + String get sendTicker => sendCurrency.ticker; + String get receiveTicker => receiveCurrency.ticker; final String rateInfo; @@ -76,10 +78,8 @@ class IncompleteExchangeModel extends ChangeNotifier { } IncompleteExchangeModel({ - required this.sendTicker, - required this.sendNetwork, - required this.receiveTicker, - required this.receiveNetwork, + required this.sendCurrency, + required this.receiveCurrency, required this.rateInfo, required this.sendAmount, required this.receiveAmount, @@ -87,5 +87,6 @@ class IncompleteExchangeModel extends ChangeNotifier { required this.reversed, required this.walletInitiated, Estimate? estimate, - }) : _estimate = estimate; + }) : _estimate = estimate, + assert(sendCurrency.exchangeName == receiveCurrency.exchangeName); } diff --git a/lib/pages/exchange_view/exchange_form.dart b/lib/pages/exchange_view/exchange_form.dart index 488a74674..93e15c4bb 100644 --- a/lib/pages/exchange_view/exchange_form.dart +++ b/lib/pages/exchange_view/exchange_form.dart @@ -420,20 +420,11 @@ class _ExchangeFormState extends ConsumerState { } final rateType = ref.read(efRateTypeProvider); - final fromTicker = ref.read(efCurrencyPairProvider).send?.ticker ?? ""; - final fromNetwork = ref - .read(efCurrencyPairProvider) - .send - ?.networkFor(exchangeName); - final toTicker = ref.read(efCurrencyPairProvider).receive?.ticker ?? ""; - final toNetwork = ref - .read(efCurrencyPairProvider) - .receive - ?.networkFor(exchangeName); final estimate = ref.read(efEstimateProvider)!; final sendAmount = ref.read(efSendAmountProvider)!; - if (rateType == ExchangeRateType.fixed && toTicker.toUpperCase() == "WOW") { + if (rateType == ExchangeRateType.fixed && + toCurrency.ticker.toUpperCase() == "WOW") { if (mounted) { await showDialog( context: context, @@ -461,7 +452,7 @@ class _ExchangeFormState extends ConsumerState { switch (rateType) { case ExchangeRateType.estimated: rate = - "1 ${fromTicker.toUpperCase()} ~${(amountToReceive / sendAmount).toDecimal(scaleOnInfinitePrecision: 8).toStringAsFixed(8)} ${toTicker.toUpperCase()}"; + "1 ${fromCurrency.ticker.toUpperCase()} ~${(amountToReceive / sendAmount).toDecimal(scaleOnInfinitePrecision: 8).toStringAsFixed(8)} ${toCurrency.ticker.toUpperCase()}"; break; case ExchangeRateType.fixed: bool? shouldCancel; @@ -568,15 +559,13 @@ class _ExchangeFormState extends ConsumerState { return; } rate = - "1 ${fromTicker.toUpperCase()} ~${(amountToReceive / amountToSend).toDecimal(scaleOnInfinitePrecision: 12).toStringAsFixed(8)} ${toTicker.toUpperCase()}"; + "1 ${fromCurrency.ticker.toUpperCase()} ~${(amountToReceive / amountToSend).toDecimal(scaleOnInfinitePrecision: 12).toStringAsFixed(8)} ${toCurrency.ticker.toUpperCase()}"; break; } final model = IncompleteExchangeModel( - sendTicker: fromTicker.toUpperCase(), - sendNetwork: fromNetwork, - receiveTicker: toTicker.toUpperCase(), - receiveNetwork: toNetwork, + sendCurrency: fromCurrency, + receiveCurrency: toCurrency, rateInfo: rate, sendAmount: amountToSend, receiveAmount: amountToReceive, diff --git a/lib/pages/exchange_view/exchange_step_views/step_3_view.dart b/lib/pages/exchange_view/exchange_step_views/step_3_view.dart index 46457ae2a..4f0b352c3 100644 --- a/lib/pages/exchange_view/exchange_step_views/step_3_view.dart +++ b/lib/pages/exchange_view/exchange_step_views/step_3_view.dart @@ -74,7 +74,7 @@ class _Step3ViewState extends ConsumerState { FocusScope.of(context).unfocus(); await Future.delayed(const Duration(milliseconds: 75)); } - if (mounted) { + if (context.mounted) { Navigator.of(context).pop(); } }, @@ -243,32 +243,33 @@ class _Step3ViewState extends ConsumerState { ), ); - final ExchangeResponse response = - await ref - .read(efExchangeProvider) - .createTrade( - from: model.sendTicker, - fromNetwork: model.sendNetwork, - to: model.receiveTicker, - toNetwork: model.receiveNetwork, - fixedRate: - model.rateType != - ExchangeRateType.estimated, - amount: - model.reversed - ? model.receiveAmount - : model.sendAmount, - addressTo: - model.recipientAddress!, - extraId: null, - addressRefund: - supportsRefund - ? model.refundAddress! - : "", - refundExtraId: "", - estimate: model.estimate, - reversed: model.reversed, - ); + final ExchangeResponse + response = await ref + .read(efExchangeProvider) + .createTrade( + from: model.sendTicker, + fromNetwork: + model.sendCurrency.network, + to: model.receiveTicker, + toNetwork: + model.receiveCurrency.network, + fixedRate: + model.rateType != + ExchangeRateType.estimated, + amount: + model.reversed + ? model.receiveAmount + : model.sendAmount, + addressTo: model.recipientAddress!, + extraId: null, + addressRefund: + supportsRefund + ? model.refundAddress! + : "", + refundExtraId: "", + estimate: model.estimate, + reversed: model.reversed, + ); if (response.value == null) { if (context.mounted) { @@ -339,7 +340,7 @@ class _Step3ViewState extends ConsumerState { ), ); - if (mounted) { + if (context.mounted) { unawaited( Navigator.of(context).pushNamed( Step4View.routeName, diff --git a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart index 3fe2b20d7..606d9fa68 100644 --- a/lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart +++ b/lib/pages_desktop_specific/desktop_exchange/exchange_steps/step_scaffold.dart @@ -96,9 +96,11 @@ class _StepScaffoldState extends ConsumerState { .read(efExchangeProvider) .createTrade( from: ref.read(desktopExchangeModelProvider)!.sendTicker, - fromNetwork: ref.read(desktopExchangeModelProvider)!.sendNetwork, + fromNetwork: + ref.read(desktopExchangeModelProvider)!.sendCurrency.network, to: ref.read(desktopExchangeModelProvider)!.receiveTicker, - toNetwork: ref.read(desktopExchangeModelProvider)!.receiveNetwork, + toNetwork: + ref.read(desktopExchangeModelProvider)!.receiveCurrency.network, fixedRate: ref.read(desktopExchangeModelProvider)!.rateType != ExchangeRateType.estimated, From daf112e0f3527b4072999091a2c5de608228ac8d Mon Sep 17 00:00:00 2001 From: julian Date: Tue, 27 May 2025 13:58:14 -0600 Subject: [PATCH 6/6] hack in prevention of spark sends to trocador swaps --- lib/app_config.dart | 8 +- lib/pages/exchange_view/send_from_view.dart | 132 ++++++++++---------- 2 files changed, 74 insertions(+), 66 deletions(-) diff --git a/lib/app_config.dart b/lib/app_config.dart index 96b07b2c9..09eeae26f 100644 --- a/lib/app_config.dart +++ b/lib/app_config.dart @@ -72,7 +72,13 @@ abstract class AppConfig { /// Fuzzy logic. Use with caution!! @Deprecated("dangerous") static CryptoCurrency getCryptoCurrencyByPrettyName(final String prettyName) { - final name = prettyName.replaceAll(" ", "").toLowerCase(); + // trocador hack + const hackSplitter = " (Mainnet"; + final name = + prettyName.contains(hackSplitter) + ? prettyName.split(hackSplitter).first.toLowerCase() + : prettyName.replaceAll(" ", "").toLowerCase(); + try { return coins.firstWhere( (e) => e.identifier.toLowerCase() == name || e.prettyName == prettyName, diff --git a/lib/pages/exchange_view/send_from_view.dart b/lib/pages/exchange_view/send_from_view.dart index bad0a3aac..8f397e79e 100644 --- a/lib/pages/exchange_view/send_from_view.dart +++ b/lib/pages/exchange_view/send_from_view.dart @@ -20,6 +20,7 @@ import '../../models/exchange/response_objects/trade.dart'; import '../../pages_desktop_specific/desktop_exchange/desktop_exchange_view.dart'; import '../../providers/providers.dart'; import '../../route_generator.dart'; +import '../../services/exchange/trocador/trocador_exchange.dart'; import '../../themes/coin_icon_provider.dart'; import '../../themes/stack_colors.dart'; import '../../themes/theme_providers.dart'; @@ -406,12 +407,6 @@ class _SendFromCardState extends ConsumerState { @override Widget build(BuildContext context) { - final wallet = ref.watch(pWallets).getWallet(walletId); - - final locale = ref.watch( - localeServiceChangeNotifierProvider.select((value) => value.locale), - ); - final coin = ref.watch(pWalletCoin(walletId)); final isFiro = coin is Firo; @@ -430,70 +425,77 @@ class _SendFromCardState extends ConsumerState { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ - MaterialButton( - splashColor: - Theme.of(context).extension()!.highlight, - key: Key("walletsSheetItemButtonFiroPrivateKey_$walletId"), - padding: const EdgeInsets.all(0), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, + if (!trade.exchangeName.startsWith( + TrocadorExchange.exchangeName, + )) + MaterialButton( + splashColor: + Theme.of(context).extension()!.highlight, + key: Key( + "walletsSheetItemButtonFiroPrivateKey_$walletId", ), - ), - onPressed: () async { - if (mounted) { - unawaited(_send(shouldSendPublicFiroFunds: false)); - } - }, - child: Container( - color: Colors.transparent, - child: Padding( - padding: const EdgeInsets.only( - top: 6, - left: 16, - right: 16, - bottom: 6, + padding: const EdgeInsets.all(0), + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Use private balance", - style: STextStyles.itemSubtitle(context), - ), - Text( - ref - .watch(pAmountFormatter(coin)) - .format( - ref - .watch( - pWalletBalanceTertiary(walletId), - ) - .spendable, - ), - style: STextStyles.itemSubtitle(context), - ), - ], - ), - SvgPicture.asset( - Assets.svg.chevronRight, - height: 14, - width: 7, - color: - Theme.of( - context, - ).extension()!.infoItemLabel, - ), - ], + ), + onPressed: () async { + if (mounted) { + unawaited(_send(shouldSendPublicFiroFunds: false)); + } + }, + child: Container( + color: Colors.transparent, + child: Padding( + padding: const EdgeInsets.only( + top: 6, + left: 16, + right: 16, + bottom: 6, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Use private balance", + style: STextStyles.itemSubtitle(context), + ), + Text( + ref + .watch(pAmountFormatter(coin)) + .format( + ref + .watch( + pWalletBalanceTertiary( + walletId, + ), + ) + .spendable, + ), + style: STextStyles.itemSubtitle(context), + ), + ], + ), + SvgPicture.asset( + Assets.svg.chevronRight, + height: 14, + width: 7, + color: + Theme.of( + context, + ).extension()!.infoItemLabel, + ), + ], + ), ), ), ), - ), MaterialButton( splashColor: Theme.of(context).extension()!.highlight,