diff --git a/assets/svg/Button.svg b/assets/svg/Button.svg new file mode 100644 index 000000000..37e0d359b --- /dev/null +++ b/assets/svg/Button.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/svg/about-desktop.svg b/assets/svg/about-desktop.svg new file mode 100644 index 000000000..a80067d9c --- /dev/null +++ b/assets/svg/about-desktop.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/svg/address-book-desktop.svg b/assets/svg/address-book-desktop.svg new file mode 100644 index 000000000..fb85e3e11 --- /dev/null +++ b/assets/svg/address-book-desktop.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/svg/dark/dark-theme.svg b/assets/svg/dark/dark-theme.svg new file mode 100644 index 000000000..47b5e2d5e --- /dev/null +++ b/assets/svg/dark/dark-theme.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svg/dollar-sign-circle.svg b/assets/svg/dollar-sign-circle.svg new file mode 100644 index 000000000..03aacffea --- /dev/null +++ b/assets/svg/dollar-sign-circle.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/svg/exchange-desktop.svg b/assets/svg/exchange-desktop.svg new file mode 100644 index 000000000..8eacfa84e --- /dev/null +++ b/assets/svg/exchange-desktop.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/svg/exit-desktop.svg b/assets/svg/exit-desktop.svg new file mode 100644 index 000000000..abba264cd --- /dev/null +++ b/assets/svg/exit-desktop.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/svg/language-circle.svg b/assets/svg/language-circle.svg new file mode 100644 index 000000000..700ffede4 --- /dev/null +++ b/assets/svg/language-circle.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/assets/svg/light/light-mode.svg b/assets/svg/light/light-mode.svg new file mode 100644 index 000000000..4ff9e2696 --- /dev/null +++ b/assets/svg/light/light-mode.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/svg/lock-circle.svg b/assets/svg/lock-circle.svg new file mode 100644 index 000000000..f8fd71831 --- /dev/null +++ b/assets/svg/lock-circle.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/assets/svg/node-circle.svg b/assets/svg/node-circle.svg new file mode 100644 index 000000000..bd9353a2b --- /dev/null +++ b/assets/svg/node-circle.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/svg/rotate-circle.svg b/assets/svg/rotate-circle.svg new file mode 100644 index 000000000..1940da5f5 --- /dev/null +++ b/assets/svg/rotate-circle.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/svg/sun-circle.svg b/assets/svg/sun-circle.svg new file mode 100644 index 000000000..eba7d031d --- /dev/null +++ b/assets/svg/sun-circle.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/assets/svg/wallet-desktop.svg b/assets/svg/wallet-desktop.svg new file mode 100644 index 000000000..0b0acdae3 --- /dev/null +++ b/assets/svg/wallet-desktop.svg @@ -0,0 +1,3 @@ + + + diff --git a/lib/main.dart b/lib/main.dart index eb7cd8e64..aa2155478 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -68,6 +68,9 @@ final openedFromSWBFileStringStateProvider = void main() async { WidgetsBinding widgetsBinding = WidgetsFlutterBinding.ensureInitialized(); GoogleFonts.config.allowRuntimeFetching = false; + if(Platform.isIOS){ + Util.libraryPath = await getLibraryDirectory(); + } if (Util.isDesktop) { setWindowTitle('Stack Wallet'); 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 ae72e1846..df5c44d18 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 @@ -90,6 +90,8 @@ class _AddWalletViewState extends State { Constants.size.circularBorderRadius, ), child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, controller: _searchFieldController, focusNode: _searchFocusNode, onChanged: (value) { 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 f7dbe3d33..8bc01b124 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 @@ -194,6 +194,8 @@ class _NameYourWalletViewState extends ConsumerState { Constants.size.circularBorderRadius, ), child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, onChanged: (string) { if (string.isEmpty) { if (_nextEnabled) { diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/sub_widgets/mobile_mnemonic_length_selector.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/sub_widgets/mobile_mnemonic_length_selector.dart index 49896e107..4f5b76fab 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/sub_widgets/mobile_mnemonic_length_selector.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/sub_widgets/mobile_mnemonic_length_selector.dart @@ -7,6 +7,8 @@ import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/utilities/util.dart'; + class MobileMnemonicLengthSelector extends ConsumerWidget { const MobileMnemonicLengthSelector({ Key? key, @@ -19,7 +21,9 @@ class MobileMnemonicLengthSelector extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { return Stack( children: [ - const TextField( + TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, // controller: _lengthController, readOnly: true, textInputAction: TextInputAction.none, diff --git a/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/sub_widgets/restore_from_date_picker.dart b/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/sub_widgets/restore_from_date_picker.dart index e5637cfc6..803e9b03b 100644 --- a/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/sub_widgets/restore_from_date_picker.dart +++ b/lib/pages/add_wallet_views/restore_wallet_view/restore_options_view/sub_widgets/restore_from_date_picker.dart @@ -4,6 +4,8 @@ import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/utilities/util.dart'; + class RestoreFromDatePicker extends StatefulWidget { const RestoreFromDatePicker({ Key? key, @@ -35,6 +37,8 @@ class _RestoreFromDatePickerState extends State { return Container( color: Colors.transparent, child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, onTap: onTap, controller: _dateController, style: STextStyles.field(context), diff --git a/lib/pages/address_book_views/address_book_view.dart b/lib/pages/address_book_views/address_book_view.dart index b70ef19ed..c9dd72d72 100644 --- a/lib/pages/address_book_views/address_book_view.dart +++ b/lib/pages/address_book_views/address_book_view.dart @@ -21,6 +21,8 @@ import 'package:stackwallet/widgets/rounded_white_container.dart'; import 'package:stackwallet/widgets/stack_text_field.dart'; import 'package:stackwallet/widgets/textfield_icon_button.dart'; +import 'package:stackwallet/utilities/util.dart'; + class AddressBookView extends ConsumerStatefulWidget { const AddressBookView({Key? key, this.coin}) : super(key: key); @@ -198,6 +200,8 @@ class _AddressBookViewState extends ConsumerState { Constants.size.circularBorderRadius, ), child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, controller: _searchController, focusNode: _searchFocusNode, onChanged: (value) { 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 4fa89908c..74f3dfde8 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 @@ -22,6 +22,8 @@ import 'package:stackwallet/widgets/icon_widgets/x_icon.dart'; import 'package:stackwallet/widgets/stack_text_field.dart'; import 'package:stackwallet/widgets/textfield_icon_button.dart'; +import 'package:stackwallet/utilities/util.dart'; + class AddAddressBookEntryView extends ConsumerStatefulWidget { const AddAddressBookEntryView({ Key? key, @@ -279,6 +281,8 @@ class _AddAddressBookEntryViewState Constants.size.circularBorderRadius, ), child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, controller: nameController, focusNode: nameFocusNode, style: STextStyles.field(context), 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 45c23b13c..fff01eee3 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 @@ -13,6 +13,8 @@ import 'package:stackwallet/widgets/icon_widgets/x_icon.dart'; import 'package:stackwallet/widgets/stack_text_field.dart'; import 'package:stackwallet/widgets/textfield_icon_button.dart'; +import 'package:stackwallet/utilities/util.dart'; + class EditContactNameEmojiView extends ConsumerStatefulWidget { const EditContactNameEmojiView({ Key? key, @@ -200,6 +202,8 @@ class _EditContactNameEmojiViewState Constants.size.circularBorderRadius, ), child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, controller: nameController, focusNode: nameFocusNode, style: STextStyles.field(context), diff --git a/lib/pages/address_book_views/subviews/new_contact_address_entry_form.dart b/lib/pages/address_book_views/subviews/new_contact_address_entry_form.dart index 73de8b0aa..ce98cee10 100644 --- a/lib/pages/address_book_views/subviews/new_contact_address_entry_form.dart +++ b/lib/pages/address_book_views/subviews/new_contact_address_entry_form.dart @@ -20,6 +20,8 @@ import 'package:stackwallet/widgets/icon_widgets/x_icon.dart'; import 'package:stackwallet/widgets/stack_text_field.dart'; import 'package:stackwallet/widgets/textfield_icon_button.dart'; +import 'package:stackwallet/utilities/util.dart'; + class NewContactAddressEntryForm extends ConsumerStatefulWidget { const NewContactAddressEntryForm({ Key? key, @@ -71,6 +73,8 @@ class _NewContactAddressEntryFormState return Column( children: [ TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, readOnly: true, style: STextStyles.field(context), decoration: InputDecoration( @@ -154,6 +158,8 @@ class _NewContactAddressEntryFormState Constants.size.circularBorderRadius, ), child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, focusNode: addressLabelFocusNode, controller: addressLabelController, style: STextStyles.field(context), @@ -197,6 +203,7 @@ class _NewContactAddressEntryFormState Constants.size.circularBorderRadius, ), child: TextField( + enableSuggestions: Util.isDesktop ? false : true, focusNode: addressFocusNode, controller: addressController, style: STextStyles.field(context), @@ -324,7 +331,6 @@ class _NewContactAddressEntryFormState key: const Key("addAddressBookEntryViewAddressField"), readOnly: false, autocorrect: false, - enableSuggestions: false, // inputFormatters: [ // FilteringTextInputFormatter.allow(RegExp("[a-zA-Z0-9]{34}")), // ], diff --git a/lib/pages/exchange_view/edit_trade_note_view.dart b/lib/pages/exchange_view/edit_trade_note_view.dart index 5e1571b73..e2a72d1b4 100644 --- a/lib/pages/exchange_view/edit_trade_note_view.dart +++ b/lib/pages/exchange_view/edit_trade_note_view.dart @@ -9,6 +9,8 @@ import 'package:stackwallet/widgets/icon_widgets/x_icon.dart'; import 'package:stackwallet/widgets/stack_text_field.dart'; import 'package:stackwallet/widgets/textfield_icon_button.dart'; +import 'package:stackwallet/utilities/util.dart'; + class EditTradeNoteView extends ConsumerStatefulWidget { const EditTradeNoteView({ Key? key, @@ -85,6 +87,8 @@ class _EditNoteViewState extends ConsumerState { Constants.size.circularBorderRadius, ), child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, controller: _noteController, style: STextStyles.field(context), focusNode: noteFieldFocusNode, diff --git a/lib/pages/exchange_view/exchange_coin_selection/fixed_rate_pair_coin_selection_view.dart b/lib/pages/exchange_view/exchange_coin_selection/fixed_rate_pair_coin_selection_view.dart index d7577e960..80bdcda62 100644 --- a/lib/pages/exchange_view/exchange_coin_selection/fixed_rate_pair_coin_selection_view.dart +++ b/lib/pages/exchange_view/exchange_coin_selection/fixed_rate_pair_coin_selection_view.dart @@ -16,6 +16,8 @@ import 'package:stackwallet/widgets/stack_text_field.dart'; import 'package:stackwallet/widgets/textfield_icon_button.dart'; import 'package:tuple/tuple.dart'; +import 'package:stackwallet/utilities/util.dart'; + class FixedRateMarketPairCoinSelectionView extends ConsumerStatefulWidget { const FixedRateMarketPairCoinSelectionView({ Key? key, @@ -152,6 +154,8 @@ class _FixedRateMarketPairCoinSelectionViewState Constants.size.circularBorderRadius, ), child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, controller: _searchController, focusNode: _searchFocusNode, onChanged: filter, diff --git a/lib/pages/exchange_view/exchange_coin_selection/floating_rate_currency_selection_view.dart b/lib/pages/exchange_view/exchange_coin_selection/floating_rate_currency_selection_view.dart index 7c3b935b7..e1c1addd2 100644 --- a/lib/pages/exchange_view/exchange_coin_selection/floating_rate_currency_selection_view.dart +++ b/lib/pages/exchange_view/exchange_coin_selection/floating_rate_currency_selection_view.dart @@ -13,6 +13,8 @@ import 'package:stackwallet/widgets/rounded_white_container.dart'; import 'package:stackwallet/widgets/stack_text_field.dart'; import 'package:stackwallet/widgets/textfield_icon_button.dart'; +import 'package:stackwallet/utilities/util.dart'; + class FloatingRateCurrencySelectionView extends StatefulWidget { const FloatingRateCurrencySelectionView({ Key? key, @@ -108,6 +110,8 @@ class _FloatingRateCurrencySelectionViewState Constants.size.circularBorderRadius, ), child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, controller: _searchController, focusNode: _searchFocusNode, onChanged: filter, 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 744d8b53c..3e29612d1 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 @@ -19,6 +19,7 @@ import 'package:stackwallet/utilities/enums/flush_bar_type.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; import 'package:stackwallet/widgets/icon_widgets/x_icon.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; @@ -160,6 +161,8 @@ class _GenerateUriQrCodeViewState extends State { Constants.size.circularBorderRadius, ), child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, controller: amountController, focusNode: _amountFocusNode, style: STextStyles.field(context), @@ -209,6 +212,8 @@ class _GenerateUriQrCodeViewState extends State { Constants.size.circularBorderRadius, ), child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, controller: noteController, focusNode: _noteFocusNode, style: STextStyles.field(context), diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart index 5e689a580..d91b7a3ea 100644 --- a/lib/pages/send_view/send_view.dart +++ b/lib/pages/send_view/send_view.dart @@ -41,6 +41,8 @@ import 'package:stackwallet/widgets/stack_dialog.dart'; import 'package:stackwallet/widgets/stack_text_field.dart'; import 'package:stackwallet/widgets/textfield_icon_button.dart'; +import 'package:stackwallet/utilities/util.dart'; + class SendView extends ConsumerStatefulWidget { const SendView({ Key? key, @@ -885,7 +887,10 @@ class _SendViewState extends ConsumerState { if (coin == Coin.firo) Stack( children: [ - const TextField( + TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: + Util.isDesktop ? false : true, readOnly: true, textInputAction: TextInputAction.none, ), @@ -1061,6 +1066,8 @@ class _SendViewState extends ConsumerState { height: 8, ), TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, style: STextStyles.smallMed14(context).copyWith( color: Theme.of(context) .extension()! @@ -1114,6 +1121,8 @@ class _SendViewState extends ConsumerState { ), 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()! @@ -1238,6 +1247,8 @@ class _SendViewState extends ConsumerState { Constants.size.circularBorderRadius, ), child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, controller: noteController, focusNode: _noteFocusNode, style: STextStyles.field(context), @@ -1283,6 +1294,8 @@ class _SendViewState extends ConsumerState { Stack( children: [ TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, controller: feeController, readOnly: true, textInputAction: TextInputAction.none, diff --git a/lib/pages/settings_views/global_settings_view/advanced_views/debug_view.dart b/lib/pages/settings_views/global_settings_view/advanced_views/debug_view.dart index 06815bd41..a3aa925a0 100644 --- a/lib/pages/settings_views/global_settings_view/advanced_views/debug_view.dart +++ b/lib/pages/settings_views/global_settings_view/advanced_views/debug_view.dart @@ -36,6 +36,8 @@ import 'package:stackwallet/pages/settings_views/global_settings_view/stack_back import 'package:stackwallet/utilities/clipboard_interface.dart'; +import 'package:stackwallet/utilities/util.dart'; + class DebugView extends ConsumerStatefulWidget { const DebugView({Key? key}) : super(key: key); @@ -228,6 +230,8 @@ class _DebugViewState extends ConsumerState { Constants.size.circularBorderRadius, ), child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, controller: _searchController, focusNode: _searchFocusNode, onChanged: (newString) { 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 cae947caa..e884393bd 100644 --- a/lib/pages/settings_views/global_settings_view/currency_view.dart +++ b/lib/pages/settings_views/global_settings_view/currency_view.dart @@ -13,6 +13,8 @@ import 'package:stackwallet/widgets/rounded_container.dart'; import 'package:stackwallet/widgets/stack_text_field.dart'; import 'package:stackwallet/widgets/textfield_icon_button.dart'; +import 'package:stackwallet/utilities/util.dart'; + class BaseCurrencySettingsView extends ConsumerStatefulWidget { const BaseCurrencySettingsView({Key? key}) : super(key: key); @@ -140,6 +142,8 @@ class _CurrencyViewState extends ConsumerState { Constants.size.circularBorderRadius, ), child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, controller: _searchController, focusNode: _searchFocusNode, onChanged: (newString) { 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 75a2751a2..b617546e4 100644 --- a/lib/pages/settings_views/global_settings_view/language_view.dart +++ b/lib/pages/settings_views/global_settings_view/language_view.dart @@ -13,6 +13,8 @@ import 'package:stackwallet/widgets/rounded_container.dart'; import 'package:stackwallet/widgets/stack_text_field.dart'; import 'package:stackwallet/widgets/textfield_icon_button.dart'; +import 'package:stackwallet/utilities/util.dart'; + class LanguageSettingsView extends ConsumerStatefulWidget { const LanguageSettingsView({Key? key}) : super(key: key); @@ -138,6 +140,8 @@ class _LanguageViewState extends ConsumerState { Constants.size.circularBorderRadius, ), child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, controller: _searchController, focusNode: _searchFocusNode, onChanged: (newString) { 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 143b1e84d..100c03e1b 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 @@ -27,6 +27,8 @@ import 'package:stackwallet/widgets/stack_text_field.dart'; import 'package:stackwallet/widgets/textfield_icon_button.dart'; import 'package:uuid/uuid.dart'; +import 'package:stackwallet/utilities/util.dart'; + enum AddEditNodeViewType { add, edit } class AddEditNodeView extends ConsumerStatefulWidget { @@ -648,6 +650,8 @@ class _NodeFormState extends ConsumerState { Constants.size.circularBorderRadius, ), child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, key: const Key("addCustomNodeNodeNameFieldKey"), readOnly: widget.readOnly, enabled: enableField(_nameController), @@ -695,6 +699,8 @@ class _NodeFormState extends ConsumerState { Constants.size.circularBorderRadius, ), child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, key: const Key("addCustomNodeNodeAddressFieldKey"), readOnly: widget.readOnly, enabled: enableField(_hostController), @@ -746,6 +752,8 @@ class _NodeFormState extends ConsumerState { Constants.size.circularBorderRadius, ), child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, key: const Key("addCustomNodeNodePortFieldKey"), readOnly: widget.readOnly, enabled: enableField(_portController), @@ -797,6 +805,8 @@ class _NodeFormState extends ConsumerState { Constants.size.circularBorderRadius, ), child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, controller: _usernameController, readOnly: widget.readOnly, enabled: enableField(_usernameController), @@ -844,6 +854,8 @@ class _NodeFormState extends ConsumerState { Constants.size.circularBorderRadius, ), child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, controller: _passwordController, readOnly: widget.readOnly, enabled: enableField(_passwordController), diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/coin_nodes_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/coin_nodes_view.dart index 12573042e..e3743d54e 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/coin_nodes_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/coin_nodes_view.dart @@ -7,7 +7,10 @@ import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart'; import 'package:tuple/tuple.dart'; class CoinNodesView extends ConsumerStatefulWidget { @@ -37,69 +40,139 @@ class _CoinNodesViewState extends ConsumerState { @override Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () { - Navigator.of(context).pop(); - }, - ), - title: Text( - "${widget.coin.prettyName} nodes", - style: STextStyles.navBarTitle(context), - ), - actions: [ - Padding( - padding: const EdgeInsets.only( - top: 10, - bottom: 10, - right: 10, - ), - child: AspectRatio( - aspectRatio: 1, - child: AppBarIconButton( - key: const Key("manageNodesAddNewNodeButtonKey"), - size: 36, - shadows: const [], - color: Theme.of(context).extension()!.background, - icon: SvgPicture.asset( - Assets.svg.plus, - color: Theme.of(context) - .extension()! - .accentColorDark, - width: 20, - height: 20, + if (Util.isDesktop) { + return DesktopDialog( + child: Column( + children: [ + Row( + children: [ + const SizedBox( + width: 32, ), - onPressed: () { - Navigator.of(context).pushNamed( - AddEditNodeView.routeName, - arguments: Tuple4( - AddEditNodeViewType.add, - widget.coin, - null, - CoinNodesView.routeName, + SvgPicture.asset( + Assets.svg.iconFor(coin: widget.coin), + width: 24, + height: 24, + ), + const SizedBox( + width: 12, + ), + Text( + "${widget.coin.prettyName} nodes", + style: STextStyles.desktopH3(context), + textAlign: TextAlign.center, + ), + Expanded( + child: const DesktopDialogCloseButton(), + ), + ], + ), + Padding( + padding: EdgeInsets.only( + left: 32, + right: 32, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "${widget.coin.prettyName} nodes", + style: STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of(context).extension()!.textDark3, ), - ); - }, + textAlign: TextAlign.left, + ), + RichText( + text: TextSpan( + text: 'Add new nodes', + style: + STextStyles.desktopTextExtraSmall(context).copyWith( + color: Colors.blueAccent, + ), + ), + ), + ], ), ), - ), - ], - ), - body: Padding( - padding: const EdgeInsets.only( - top: 12, - left: 12, - right: 12, + const SizedBox( + width: 12, + ), + Padding( + padding: const EdgeInsets.all(20), + child: NodesList( + coin: widget.coin, + popBackToRoute: CoinNodesView.routeName, + ), + ), + ], ), - child: SingleChildScrollView( - child: NodesList( - coin: widget.coin, - popBackToRoute: CoinNodesView.routeName, + ); + } else { + return Scaffold( + backgroundColor: Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () { + Navigator.of(context).pop(); + }, + ), + title: Text( + "${widget.coin.prettyName} nodes", + style: STextStyles.navBarTitle(context), + ), + actions: [ + Padding( + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + right: 10, + ), + child: AspectRatio( + aspectRatio: 1, + child: AppBarIconButton( + key: const Key("manageNodesAddNewNodeButtonKey"), + size: 36, + shadows: const [], + color: Theme.of(context).extension()!.background, + icon: SvgPicture.asset( + Assets.svg.plus, + color: Theme.of(context) + .extension()! + .accentColorDark, + width: 20, + height: 20, + ), + onPressed: () { + Navigator.of(context).pushNamed( + AddEditNodeView.routeName, + arguments: Tuple4( + AddEditNodeViewType.add, + widget.coin, + null, + CoinNodesView.routeName, + ), + ); + }, + ), + ), + ), + ], + ), + body: Padding( + padding: const EdgeInsets.only( + top: 12, + left: 12, + right: 12, + ), + child: SingleChildScrollView( + child: NodesList( + coin: widget.coin, + popBackToRoute: CoinNodesView.routeName, + ), ), ), - ), - ); + ); + } } } 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 3f832a4af..a94375742 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 @@ -19,6 +19,8 @@ import 'package:stackwallet/widgets/stack_dialog.dart'; import 'package:stackwallet/widgets/stack_text_field.dart'; import 'package:url_launcher/url_launcher.dart'; +import 'package:stackwallet/utilities/util.dart'; + class AutoBackupView extends ConsumerStatefulWidget { const AutoBackupView({Key? key}) : super(key: key); @@ -423,6 +425,8 @@ class _AutoBackupViewState extends ConsumerState { height: 10, ), TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, key: const Key("backupFrequencyFieldKey"), controller: frequencyController, enabled: false, 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 b44a473b4..3b5dbd0b0 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 @@ -27,6 +27,8 @@ import 'package:stackwallet/widgets/stack_dialog.dart'; import 'package:stackwallet/widgets/stack_text_field.dart'; import 'package:zxcvbn/zxcvbn.dart'; +import 'package:stackwallet/utilities/util.dart'; + class CreateAutoBackupView extends ConsumerStatefulWidget { const CreateAutoBackupView({ Key? key, @@ -146,6 +148,8 @@ class _EnableAutoBackupViewState extends ConsumerState { ), if (!Platform.isAndroid) TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, onTap: Platform.isAndroid ? null : () async { @@ -411,7 +415,9 @@ class _EnableAutoBackupViewState extends ConsumerState { ), Stack( children: [ - const TextField( + TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, readOnly: true, textInputAction: TextInputAction.none, ), 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 8dfc7588c..9242c0482 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 @@ -14,6 +14,7 @@ import 'package:stackwallet/utilities/enums/flush_bar_type.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/utilities/util.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; import 'package:stackwallet/widgets/progress_bar.dart'; import 'package:stackwallet/widgets/stack_dialog.dart'; @@ -129,6 +130,8 @@ class _RestoreFromFileViewState extends State { return Container( color: Colors.transparent, child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, onTap: Platform.isAndroid ? null : () async { 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 9368d3b77..105146aa0 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 @@ -27,6 +27,8 @@ import 'package:stackwallet/widgets/stack_dialog.dart'; import 'package:stackwallet/widgets/stack_text_field.dart'; import 'package:zxcvbn/zxcvbn.dart'; +import '../../../../utilities/util.dart'; + class EditAutoBackupView extends ConsumerStatefulWidget { const EditAutoBackupView({ Key? key, @@ -148,6 +150,8 @@ class _EditAutoBackupViewState extends ConsumerState { ), if (!Platform.isAndroid) TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, onTap: Platform.isAndroid ? null : () async { @@ -413,7 +417,9 @@ class _EditAutoBackupViewState extends ConsumerState { ), Stack( children: [ - const TextField( + TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, readOnly: true, textInputAction: TextInputAction.none, ), 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 cec114023..232be9028 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 @@ -20,6 +20,8 @@ import 'package:stackwallet/widgets/loading_indicator.dart'; import 'package:stackwallet/widgets/stack_text_field.dart'; import 'package:tuple/tuple.dart'; +import 'package:stackwallet/utilities/util.dart'; + class RestoreFromFileView extends ConsumerStatefulWidget { const RestoreFromFileView({Key? key}) : super(key: key); @@ -96,6 +98,8 @@ class _RestoreFromFileViewState extends ConsumerState { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, onTap: () async { try { await stackFileSystem.prepareStorage(); 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 6e5cdd5ed..2d8909245 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 @@ -30,6 +30,8 @@ import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; import 'package:tuple/tuple.dart'; +import 'package:stackwallet/utilities/util.dart'; + /// [eventBus] should only be set during testing class WalletSettingsView extends StatefulWidget { const WalletSettingsView({ @@ -374,6 +376,8 @@ class _EpiBoxInfoFormState extends ConsumerState { crossAxisAlignment: CrossAxisAlignment.stretch, children: [ TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, controller: hostController, decoration: const InputDecoration(hintText: "Host"), ), @@ -381,6 +385,8 @@ class _EpiBoxInfoFormState extends ConsumerState { height: 8, ), TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, controller: portController, decoration: const InputDecoration(hintText: "Port"), keyboardType: const TextInputType.numberWithOptions(), 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 b876216e0..e9eb14868 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 @@ -11,6 +11,8 @@ import 'package:stackwallet/widgets/icon_widgets/x_icon.dart'; import 'package:stackwallet/widgets/stack_text_field.dart'; import 'package:stackwallet/widgets/textfield_icon_button.dart'; +import 'package:stackwallet/utilities/util.dart'; + class RenameWalletView extends ConsumerStatefulWidget { const RenameWalletView({ Key? key, @@ -74,6 +76,8 @@ class _RenameWalletViewState extends ConsumerState { Constants.size.circularBorderRadius, ), child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, controller: _controller, focusNode: _focusNode, style: STextStyles.field(context), diff --git a/lib/pages/wallet_view/transaction_views/all_transactions_view.dart b/lib/pages/wallet_view/transaction_views/all_transactions_view.dart index 78f24ba6a..4194a7307 100644 --- a/lib/pages/wallet_view/transaction_views/all_transactions_view.dart +++ b/lib/pages/wallet_view/transaction_views/all_transactions_view.dart @@ -21,6 +21,8 @@ import 'package:stackwallet/widgets/textfield_icon_button.dart'; import 'package:stackwallet/widgets/transaction_card.dart'; import 'package:tuple/tuple.dart'; +import 'package:stackwallet/utilities/util.dart'; + class AllTransactionsView extends ConsumerStatefulWidget { const AllTransactionsView({ Key? key, @@ -234,6 +236,8 @@ class _TransactionDetailsViewState extends ConsumerState { Constants.size.circularBorderRadius, ), child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, controller: _searchController, focusNode: searchFieldFocusNode, onChanged: (value) { 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 aa085429b..b811dc62d 100644 --- a/lib/pages/wallet_view/transaction_views/edit_note_view.dart +++ b/lib/pages/wallet_view/transaction_views/edit_note_view.dart @@ -9,6 +9,8 @@ import 'package:stackwallet/widgets/icon_widgets/x_icon.dart'; import 'package:stackwallet/widgets/stack_text_field.dart'; import 'package:stackwallet/widgets/textfield_icon_button.dart'; +import 'package:stackwallet/utilities/util.dart'; + class EditNoteView extends ConsumerStatefulWidget { const EditNoteView({ Key? key, @@ -87,6 +89,8 @@ class _EditNoteViewState extends ConsumerState { Constants.size.circularBorderRadius, ), child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, controller: _noteController, style: STextStyles.field(context), focusNode: noteFieldFocusNode, 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 8175597f6..f9932c672 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 @@ -569,6 +569,8 @@ class _TransactionSearchViewState Constants.size.circularBorderRadius, ), child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, key: const Key("transactionSearchViewAmountFieldKey"), controller: _amountTextEditingController, focusNode: amountTextFieldFocusNode, @@ -636,6 +638,8 @@ class _TransactionSearchViewState Constants.size.circularBorderRadius, ), child: TextField( + autocorrect: Util.isDesktop ? false : true, + enableSuggestions: Util.isDesktop ? false : true, key: const Key("transactionSearchViewKeywordFieldKey"), controller: _keywordTextEditingController, diff --git a/lib/pages_desktop_specific/home/desktop_home_view.dart b/lib/pages_desktop_specific/home/desktop_home_view.dart index 4ca78894b..6aa104081 100644 --- a/lib/pages_desktop_specific/home/desktop_home_view.dart +++ b/lib/pages_desktop_specific/home/desktop_home_view.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:stackwallet/pages_desktop_specific/home/desktop_menu.dart'; +import 'package:stackwallet/pages_desktop_specific/home/desktop_settings_view.dart'; import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/my_stack_view.dart'; -import 'package:stackwallet/pages_desktop_specific/home/settings_menu/settings_menu.dart'; import 'package:stackwallet/route_generator.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; @@ -19,6 +19,7 @@ class _DesktopHomeViewState extends ConsumerState { int currentViewIndex = 0; final List contentViews = [ const Navigator( + key: Key("desktopStackHomeKey"), onGenerateRoute: RouteGenerator.generateRoute, initialRoute: MyStackView.routeName, ), @@ -32,8 +33,9 @@ class _DesktopHomeViewState extends ConsumerState { color: Colors.orange, ), const Navigator( + key: Key("desktopSettingHomeKey"), onGenerateRoute: RouteGenerator.generateRoute, - initialRoute: SettingsMenu.routeName, + initialRoute: DesktopSettingsView.routeName, ), Container( color: Colors.blue, @@ -41,9 +43,6 @@ class _DesktopHomeViewState extends ConsumerState { Container( color: Colors.pink, ), - Container( - color: Colors.purple, - ), ]; void onMenuSelectionChanged(int newIndex) { @@ -61,6 +60,10 @@ class _DesktopHomeViewState extends ConsumerState { DesktopMenu( onSelectionChanged: onMenuSelectionChanged, ), + Container( + width: 1, + color: Theme.of(context).extension()!.background, + ), Expanded( child: contentViews[currentViewIndex], ), diff --git a/lib/pages_desktop_specific/home/desktop_menu.dart b/lib/pages_desktop_specific/home/desktop_menu.dart index b71c20f6e..7409a4156 100644 --- a/lib/pages_desktop_specific/home/desktop_menu.dart +++ b/lib/pages_desktop_specific/home/desktop_menu.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; @@ -70,136 +72,197 @@ class _DesktopMenuState extends ConsumerState { const SizedBox( height: 60, ), - SizedBox( - width: _width == expandedWidth - ? _width - 32 // 16 padding on either side - : _width - 16, // 8 padding on either side - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - DesktopMenuItem( - icon: SvgPicture.asset( - Assets.svg.walletFa, - width: 20, - height: 20, + Expanded( + child: SizedBox( + width: _width == expandedWidth + ? _width - 32 // 16 padding on either side + : _width - 16, // 8 padding on either side + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + DesktopMenuItem( + icon: SvgPicture.asset( + Assets.svg.walletDesktop, + width: 20, + height: 20, + color: 0 == selectedMenuItem + ? Theme.of(context) + .extension()! + .textDark + : Theme.of(context) + .extension()! + .textDark + .withOpacity(0.8), + ), + label: "My Stack", + value: 0, + group: selectedMenuItem, + onChanged: updateSelectedMenuItem, + iconOnly: _width == minimizedWidth, ), - label: "My Stack", - value: 0, - group: selectedMenuItem, - onChanged: updateSelectedMenuItem, - iconOnly: _width == minimizedWidth, - ), - const SizedBox( - height: 2, - ), - DesktopMenuItem( - icon: SvgPicture.asset( - Assets.svg.exchange3, - width: 20, - height: 20, + const SizedBox( + height: 2, ), - label: "Exchange", - value: 1, - group: selectedMenuItem, - onChanged: updateSelectedMenuItem, - iconOnly: _width == minimizedWidth, - ), - const SizedBox( - height: 2, - ), - DesktopMenuItem( - icon: SvgPicture.asset( - Assets.svg.bell, - width: 20, - height: 20, + DesktopMenuItem( + icon: SvgPicture.asset( + Assets.svg.exchangeDesktop, + width: 20, + height: 20, + color: 1 == selectedMenuItem + ? Theme.of(context) + .extension()! + .textDark + : Theme.of(context) + .extension()! + .textDark + .withOpacity(0.8), + ), + label: "Exchange", + value: 1, + group: selectedMenuItem, + onChanged: updateSelectedMenuItem, + iconOnly: _width == minimizedWidth, ), - label: "Notifications", - value: 2, - group: selectedMenuItem, - onChanged: updateSelectedMenuItem, - iconOnly: _width == minimizedWidth, - ), - const SizedBox( - height: 2, - ), - DesktopMenuItem( - icon: SvgPicture.asset( - Assets.svg.addressBook2, - width: 20, - height: 20, + const SizedBox( + height: 2, ), - label: "Address Book", - value: 3, - group: selectedMenuItem, - onChanged: updateSelectedMenuItem, - iconOnly: _width == minimizedWidth, - ), - const SizedBox( - height: 2, - ), - DesktopMenuItem( - icon: SvgPicture.asset( - Assets.svg.gear, - width: 20, - height: 20, + DesktopMenuItem( + icon: SvgPicture.asset( + Assets.svg.bell, + width: 20, + height: 20, + color: 2 == selectedMenuItem + ? Theme.of(context) + .extension()! + .textDark + : Theme.of(context) + .extension()! + .textDark + .withOpacity(0.8), + ), + label: "Notifications", + value: 2, + group: selectedMenuItem, + onChanged: updateSelectedMenuItem, + iconOnly: _width == minimizedWidth, ), - label: "Settings", - value: 4, - group: selectedMenuItem, - onChanged: updateSelectedMenuItem, - iconOnly: _width == minimizedWidth, - ), - const SizedBox( - height: 2, - ), - DesktopMenuItem( - icon: SvgPicture.asset( - Assets.svg.messageQuestion, - width: 20, - height: 20, + const SizedBox( + height: 2, ), - label: "Support", - value: 5, - group: selectedMenuItem, - onChanged: updateSelectedMenuItem, - iconOnly: _width == minimizedWidth, - ), - const SizedBox( - height: 2, - ), - DesktopMenuItem( - icon: SvgPicture.asset( - Assets.svg.messageQuestion, - width: 20, - height: 20, + DesktopMenuItem( + icon: SvgPicture.asset( + Assets.svg.addressBookDesktop, + width: 20, + height: 20, + color: 3 == selectedMenuItem + ? Theme.of(context) + .extension()! + .textDark + : Theme.of(context) + .extension()! + .textDark + .withOpacity(0.8), + ), + label: "Address Book", + value: 3, + group: selectedMenuItem, + onChanged: updateSelectedMenuItem, + iconOnly: _width == minimizedWidth, ), - label: "About", - value: 6, - group: selectedMenuItem, - onChanged: updateSelectedMenuItem, - iconOnly: _width == minimizedWidth, - ), - const SizedBox( - height: 2, - ), - DesktopMenuItem( - icon: SvgPicture.asset( - Assets.svg.messageQuestion, - width: 20, - height: 20, + const SizedBox( + height: 2, ), - label: "Exit", - value: 7, - group: selectedMenuItem, - onChanged: updateSelectedMenuItem, - iconOnly: _width == minimizedWidth, - ), - ], + DesktopMenuItem( + icon: SvgPicture.asset( + Assets.svg.gear, + width: 20, + height: 20, + color: 4 == selectedMenuItem + ? Theme.of(context) + .extension()! + .textDark + : Theme.of(context) + .extension()! + .textDark + .withOpacity(0.8), + ), + label: "Settings", + value: 4, + group: selectedMenuItem, + onChanged: updateSelectedMenuItem, + iconOnly: _width == minimizedWidth, + ), + const SizedBox( + height: 2, + ), + DesktopMenuItem( + icon: SvgPicture.asset( + Assets.svg.messageQuestion, + width: 20, + height: 20, + color: 5 == selectedMenuItem + ? Theme.of(context) + .extension()! + .textDark + : Theme.of(context) + .extension()! + .textDark + .withOpacity(0.8), + ), + label: "Support", + value: 5, + group: selectedMenuItem, + onChanged: updateSelectedMenuItem, + iconOnly: _width == minimizedWidth, + ), + const SizedBox( + height: 2, + ), + DesktopMenuItem( + icon: SvgPicture.asset( + Assets.svg.aboutDesktop, + width: 20, + height: 20, + color: 6 == selectedMenuItem + ? Theme.of(context) + .extension()! + .textDark + : Theme.of(context) + .extension()! + .textDark + .withOpacity(0.8), + ), + label: "About", + value: 6, + group: selectedMenuItem, + onChanged: updateSelectedMenuItem, + iconOnly: _width == minimizedWidth, + ), + const Spacer(), + DesktopMenuItem( + icon: SvgPicture.asset( + Assets.svg.exitDesktop, + width: 20, + height: 20, + color: Theme.of(context) + .extension()! + .textDark + .withOpacity(0.8), + ), + label: "Exit", + value: 7, + group: selectedMenuItem, + onChanged: (_) { + // todo: save stuff/ notify before exit? + exit(0); + }, + iconOnly: _width == minimizedWidth, + ), + ], + ), ), ), - const Spacer(), Row( - mainAxisAlignment: MainAxisAlignment.end, children: [ const Spacer(), IconButton( @@ -212,7 +275,7 @@ class _DesktopMenuState extends ConsumerState { ), ), ], - ) + ), ], ), ), diff --git a/lib/pages_desktop_specific/home/desktop_settings_view.dart b/lib/pages_desktop_specific/home/desktop_settings_view.dart index bfe9272f2..7aff94b66 100644 --- a/lib/pages_desktop_specific/home/desktop_settings_view.dart +++ b/lib/pages_desktop_specific/home/desktop_settings_view.dart @@ -1,7 +1,19 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:stackwallet/pages_desktop_specific/home/settings_menu/advanced_settings.dart'; +import 'package:stackwallet/pages_desktop_specific/home/settings_menu/appearance_settings.dart'; +import 'package:stackwallet/pages_desktop_specific/home/settings_menu/backup_and_restore_settings.dart'; +import 'package:stackwallet/pages_desktop_specific/home/settings_menu/currency_settings.dart'; +import 'package:stackwallet/pages_desktop_specific/home/settings_menu/language_settings.dart'; +import 'package:stackwallet/pages_desktop_specific/home/settings_menu/nodes_settings.dart'; +import 'package:stackwallet/pages_desktop_specific/home/settings_menu/security_settings.dart'; import 'package:stackwallet/pages_desktop_specific/home/settings_menu/settings_menu.dart'; +import 'package:stackwallet/pages_desktop_specific/home/settings_menu/syncing_preferences_settings.dart'; +import 'package:stackwallet/route_generator.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart'; +import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart'; class DesktopSettingsView extends ConsumerStatefulWidget { const DesktopSettingsView({Key? key}) : super(key: key); @@ -16,29 +28,45 @@ class DesktopSettingsView extends ConsumerStatefulWidget { class _DesktopSettingsViewState extends ConsumerState { int currentViewIndex = 0; final List contentViews = [ - Container( - color: Colors.lime, + const Navigator( + key: Key("settingsBackupRestoreDesktopKey"), + onGenerateRoute: RouteGenerator.generateRoute, + initialRoute: BackupRestoreSettings.routeName, ), //b+r - Container( - color: Colors.green, + const Navigator( + key: Key("settingsSecurityDesktopKey"), + onGenerateRoute: RouteGenerator.generateRoute, + initialRoute: SecuritySettings.routeName, ), //security - Container( - color: Colors.red, + const Navigator( + key: Key("settingsCurrencyDesktopKey"), + onGenerateRoute: RouteGenerator.generateRoute, + initialRoute: CurrencySettings.routeName, ), //currency - Container( - color: Colors.orange, + const Navigator( + key: Key("settingsLanguageDesktopKey"), + onGenerateRoute: RouteGenerator.generateRoute, + initialRoute: LanguageOptionSettings.routeName, ), //language - Container( - color: Colors.yellow, + const Navigator( + key: Key("settingsNodesDesktopKey"), + onGenerateRoute: RouteGenerator.generateRoute, + initialRoute: NodesSettings.routeName, ), //nodes - Container( - color: Colors.blue, + const Navigator( + key: Key("settingsSyncingPreferencesDesktopKey"), + onGenerateRoute: RouteGenerator.generateRoute, + initialRoute: SyncingPreferencesSettings.routeName, ), //syncing prefs - Container( - color: Colors.pink, + const Navigator( + key: Key("settingsAppearanceDesktopKey"), + onGenerateRoute: RouteGenerator.generateRoute, + initialRoute: AppearanceOptionSettings.routeName, ), //appearance - Container( - color: Colors.purple, + const Navigator( + key: Key("settingsAdvancedDesktopKey"), + onGenerateRoute: RouteGenerator.generateRoute, + initialRoute: AdvancedSettings.routeName, ), //advanced ]; @@ -48,12 +76,26 @@ class _DesktopSettingsViewState extends ConsumerState { }); } - // will have a row with two items: SettingsMenu and settings contentxd @override Widget build(BuildContext context) { - return Material( - color: Theme.of(context).extension()!.background, - child: Row( + return DesktopScaffold( + background: Theme.of(context).extension()!.background, + appBar: DesktopAppBar( + isCompactHeight: true, + leading: Row( + children: [ + const SizedBox( + width: 24, + height: 24, + ), + Text( + "Settings", + style: STextStyles.desktopH3(context), + ) + ], + ), + ), + body: Row( children: [ SettingsMenu( onSelectionChanged: onMenuSelectionChanged, diff --git a/lib/pages_desktop_specific/home/my_stack_view/coin_wallets_table.dart b/lib/pages_desktop_specific/home/my_stack_view/coin_wallets_table.dart index 64e4a23d3..b16a9bc58 100644 --- a/lib/pages_desktop_specific/home/my_stack_view/coin_wallets_table.dart +++ b/lib/pages_desktop_specific/home/my_stack_view/coin_wallets_table.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart'; import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/widgets/wallet_info_row/wallet_info_row.dart'; @@ -37,6 +38,12 @@ class CoinWalletsTable extends ConsumerWidget { ), WalletInfoRow( walletId: walletIds[i], + onPressed: () async { + await Navigator.of(context).pushNamed( + DesktopWalletView.routeName, + arguments: walletIds[i], + ); + }, ), ], ), diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_summary.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_summary.dart new file mode 100644 index 000000000..fe2cfa7b2 --- /dev/null +++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_summary.dart @@ -0,0 +1,283 @@ +import 'package:decimal/decimal.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:stackwallet/pages/wallet_view/sub_widgets/wallet_balance_toggle_sheet.dart'; +import 'package:stackwallet/pages/wallet_view/sub_widgets/wallet_refresh_button.dart'; +import 'package:stackwallet/providers/providers.dart'; +import 'package:stackwallet/providers/wallet/wallet_balance_toggle_state_provider.dart'; +import 'package:stackwallet/services/coins/firo/firo_wallet.dart'; +import 'package:stackwallet/services/coins/manager.dart'; +import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/enums/wallet_balance_toggle_state.dart'; +import 'package:stackwallet/utilities/format.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/widgets/animated_text.dart'; + +class DesktopWalletSummary extends StatefulWidget { + const DesktopWalletSummary({ + Key? key, + required this.walletId, + required this.managerProvider, + required this.initialSyncStatus, + }) : super(key: key); + + final String walletId; + final ChangeNotifierProvider managerProvider; + final WalletSyncStatus initialSyncStatus; + + @override + State createState() => _WDesktopWalletSummaryState(); +} + +class _WDesktopWalletSummaryState extends State { + late final String walletId; + late final ChangeNotifierProvider managerProvider; + + void showSheet() { + showModalBottomSheet( + backgroundColor: Colors.transparent, + context: context, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical( + top: Radius.circular(20), + ), + ), + builder: (_) => WalletBalanceToggleSheet(walletId: walletId), + ); + } + + Decimal? _balanceTotalCached; + Decimal? _balanceCached; + + @override + void initState() { + walletId = widget.walletId; + managerProvider = widget.managerProvider; + super.initState(); + } + + @override + Widget build(BuildContext context) { + debugPrint("BUILD: $runtimeType"); + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + children: [ + Consumer( + builder: (_, ref, __) { + final Coin coin = + ref.watch(managerProvider.select((value) => value.coin)); + final externalCalls = ref.watch(prefsChangeNotifierProvider + .select((value) => value.externalCalls)); + + Future? totalBalanceFuture; + Future? availableBalanceFuture; + if (coin == Coin.firo || coin == Coin.firoTestNet) { + final firoWallet = + ref.watch(managerProvider.select((value) => value.wallet)) + as FiroWallet; + totalBalanceFuture = firoWallet.availablePublicBalance(); + availableBalanceFuture = firoWallet.availablePrivateBalance(); + } else { + totalBalanceFuture = ref.watch( + managerProvider.select((value) => value.totalBalance)); + + availableBalanceFuture = ref.watch(managerProvider + .select((value) => value.availableBalance)); + } + + final locale = ref.watch(localeServiceChangeNotifierProvider + .select((value) => value.locale)); + + final baseCurrency = ref.watch(prefsChangeNotifierProvider + .select((value) => value.currency)); + + final priceTuple = ref.watch(priceAnd24hChangeNotifierProvider + .select((value) => value.getPrice(coin))); + + final _showAvailable = + ref.watch(walletBalanceToggleStateProvider.state).state == + WalletBalanceToggleState.available; + + return FutureBuilder( + future: _showAvailable + ? availableBalanceFuture + : totalBalanceFuture, + builder: (fbContext, AsyncSnapshot snapshot) { + if (snapshot.connectionState == ConnectionState.done && + snapshot.hasData && + snapshot.data != null) { + if (_showAvailable) { + _balanceCached = snapshot.data!; + } else { + _balanceTotalCached = snapshot.data!; + } + } + Decimal? balanceToShow = + _showAvailable ? _balanceCached : _balanceTotalCached; + + if (balanceToShow != null) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + GestureDetector( + onTap: showSheet, + child: Row( + children: [ + if (coin == Coin.firo || + coin == Coin.firoTestNet) + Text( + "${_showAvailable ? "Private" : "Public"} Balance", + style: STextStyles.subtitle500(context) + .copyWith( + color: Theme.of(context) + .extension()! + .textFavoriteCard, + ), + ), + if (coin != Coin.firo && + coin != Coin.firoTestNet) + Text( + "${_showAvailable ? "Available" : "Full"} Balance", + style: STextStyles.subtitle500(context) + .copyWith( + color: Theme.of(context) + .extension()! + .textFavoriteCard, + ), + ), + const SizedBox( + width: 4, + ), + SvgPicture.asset( + Assets.svg.chevronDown, + color: Theme.of(context) + .extension()! + .textFavoriteCard, + width: 8, + height: 4, + ), + ], + ), + ), + FittedBox( + fit: BoxFit.scaleDown, + child: Text( + "${Format.localizedStringAsFixed( + value: balanceToShow, + locale: locale, + decimalPlaces: 8, + )} ${coin.ticker}", + style: STextStyles.desktopH3(context), + ), + ), + if (externalCalls) + Text( + "${Format.localizedStringAsFixed( + value: priceTuple.item1 * balanceToShow, + locale: locale, + decimalPlaces: 2, + )} $baseCurrency", + style: STextStyles.desktopTextExtraSmall(context) + .copyWith( + color: Theme.of(context) + .extension()! + .textSubtitle1, + ), + ), + ], + ); + } else { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + GestureDetector( + onTap: showSheet, + child: Row( + children: [ + if (coin == Coin.firo || + coin == Coin.firoTestNet) + Text( + "${_showAvailable ? "Private" : "Public"} Balance", + style: STextStyles.subtitle500(context) + .copyWith( + color: Theme.of(context) + .extension()! + .textFavoriteCard, + ), + ), + if (coin != Coin.firo && + coin != Coin.firoTestNet) + Text( + "${_showAvailable ? "Available" : "Full"} Balance", + style: STextStyles.subtitle500(context) + .copyWith( + color: Theme.of(context) + .extension()! + .textFavoriteCard, + ), + ), + const SizedBox( + width: 4, + ), + SvgPicture.asset( + Assets.svg.chevronDown, + width: 8, + height: 4, + color: Theme.of(context) + .extension()! + .textFavoriteCard, + ), + ], + ), + ), + AnimatedText( + stringsToLoopThrough: const [ + "Loading balance ", + "Loading balance. ", + "Loading balance.. ", + "Loading balance..." + ], + style: STextStyles.desktopH3(context).copyWith( + fontSize: 24, + color: Theme.of(context) + .extension()! + .textFavoriteCard, + ), + ), + AnimatedText( + stringsToLoopThrough: const [ + "Loading balance ", + "Loading balance. ", + "Loading balance.. ", + "Loading balance..." + ], + style: STextStyles.desktopTextExtraSmall(context) + .copyWith( + color: Theme.of(context) + .extension()! + .textSubtitle1, + ), + ), + ], + ); + } + }, + ); + }, + ), + ], + ), + WalletRefreshButton( + walletId: walletId, + initialSyncStatus: widget.initialSyncStatus, + ) + ], + ); + } +} diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart new file mode 100644 index 000000000..7f13c7fd8 --- /dev/null +++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart @@ -0,0 +1,485 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_summary.dart'; +import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/receive/desktop_receive.dart'; +import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/send/desktop_send.dart'; +import 'package:stackwallet/providers/providers.dart'; +import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/constants.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; +import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart'; +import 'package:stackwallet/widgets/desktop/desktop_app_bar.dart'; +import 'package:stackwallet/widgets/desktop/desktop_scaffold.dart'; +import 'package:stackwallet/widgets/desktop/secondary_button.dart'; +import 'package:stackwallet/widgets/rounded_white_container.dart'; + +class DesktopWalletView extends ConsumerStatefulWidget { + const DesktopWalletView({ + Key? key, + required this.walletId, + }) : super(key: key); + + static const String routeName = "/desktopWalletView"; + + final String walletId; + + @override + ConsumerState createState() => _DesktopWalletViewState(); +} + +class _DesktopWalletViewState extends ConsumerState { + late final String walletId; + + Future onBackPressed() async { + // TODO log out and close wallet before popping back + Navigator.of(context).pop(); + } + + @override + void initState() { + walletId = widget.walletId; + super.initState(); + } + + @override + Widget build(BuildContext context) { + final manager = ref.watch(walletsChangeNotifierProvider + .select((value) => value.getManager(walletId))); + final coin = manager.coin; + final managerProvider = ref.watch(walletsChangeNotifierProvider + .select((value) => value.getManagerProvider(walletId))); + + return DesktopScaffold( + appBar: DesktopAppBar( + background: Theme.of(context).extension()!.popupBG, + leading: Row( + children: [ + const SizedBox( + width: 32, + ), + AppBarIconButton( + size: 32, + color: Theme.of(context) + .extension()! + .textFieldDefaultBG, + shadows: const [], + icon: SvgPicture.asset( + Assets.svg.arrowLeft, + width: 18, + height: 18, + color: Theme.of(context) + .extension()! + .topNavIconPrimary, + ), + onPressed: onBackPressed, + ), + const SizedBox( + width: 15, + ), + SvgPicture.asset( + Assets.svg.iconFor(coin: coin), + width: 32, + height: 32, + ), + const SizedBox( + width: 12, + ), + Text( + manager.walletName, + style: STextStyles.desktopH3(context), + ), + ], + ), + trailing: Row( + children: const [ + NetworkInfoButton(), + SizedBox( + width: 12, + ), + WalletKeysButton(), + SizedBox( + width: 32, + ), + ], + ), + isCompactHeight: true, + ), + body: Padding( + padding: const EdgeInsets.all(24), + child: Column( + children: [ + RoundedWhiteContainer( + padding: const EdgeInsets.all(20), + child: Row( + children: [ + SvgPicture.asset( + Assets.svg.iconFor(coin: coin), + width: 40, + height: 40, + ), + const SizedBox( + width: 10, + ), + DesktopWalletSummary( + walletId: walletId, + managerProvider: managerProvider, + initialSyncStatus: ref.watch(managerProvider + .select((value) => value.isRefreshing)) + ? WalletSyncStatus.syncing + : WalletSyncStatus.synced, + ), + // Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // Row( + // children: [ + // Text( + // "TODO: balance", + // style: STextStyles.desktopH3(context), + // ), + // const SizedBox( + // width: 8, + // ), + // Container( + // color: Colors.red, + // width: 20, + // height: 20, + // ), + // ], + // ), + // Text( + // "todo: fiat balance", + // style: + // STextStyles.desktopTextExtraSmall(context).copyWith( + // color: Theme.of(context) + // .extension()! + // .textSubtitle1, + // ), + // ) + // ], + // ), + const Spacer(), + SecondaryButton( + width: 180, + height: 56, + onPressed: () { + // todo: go to wallet initiated exchange + }, + label: "Exchange", + icon: Container( + color: Colors.red, + width: 20, + height: 20, + ), + ) + ], + ), + ), + const SizedBox( + height: 24, + ), + Expanded( + child: Row( + children: [ + SizedBox( + width: 450, + child: MyWallet( + walletId: walletId, + ), + ), + const SizedBox( + width: 16, + ), + Expanded( + child: RecentDesktopTransactions(), + ), + ], + ), + ), + ], + ), + ), + ); + } +} + +class MyWallet extends StatefulWidget { + const MyWallet({ + Key? key, + required this.walletId, + }) : super(key: key); + + final String walletId; + + @override + State createState() => _MyWalletState(); +} + +class _MyWalletState extends State { + int _selectedIndex = 0; + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "My wallet", + style: STextStyles.desktopTextExtraSmall(context).copyWith( + color: Theme.of(context) + .extension()! + .textFieldActiveSearchIconLeft, + ), + ), + const SizedBox( + height: 16, + ), + Container( + decoration: BoxDecoration( + color: Theme.of(context).extension()!.popupBG, + borderRadius: BorderRadius.vertical( + top: Radius.circular( + Constants.size.circularBorderRadius, + ), + ), + ), + child: SendReceiveTabMenu( + onChanged: (index) { + setState(() { + _selectedIndex = index; + }); + }, + ), + ), + Container( + decoration: BoxDecoration( + color: Theme.of(context).extension()!.popupBG, + borderRadius: BorderRadius.vertical( + bottom: Radius.circular( + Constants.size.circularBorderRadius, + ), + ), + ), + child: IndexedStack( + index: _selectedIndex, + children: [ + Padding( + key: const Key("desktopSendViewPortKey"), + padding: const EdgeInsets.all(20), + child: DesktopSend( + walletId: widget.walletId, + ), + ), + Padding( + key: const Key("desktopReceiveViewPortKey"), + padding: const EdgeInsets.all(20), + child: DesktopReceive( + walletId: widget.walletId, + ), + ), + ], + ), + ), + const Spacer(), + ], + ); + } +} + +class SendReceiveTabMenu extends StatefulWidget { + const SendReceiveTabMenu({ + Key? key, + this.initialIndex = 0, + this.onChanged, + }) : super(key: key); + + final int initialIndex; + final void Function(int)? onChanged; + + @override + State createState() => _SendReceiveTabMenuState(); +} + +class _SendReceiveTabMenuState extends State { + late int _selectedIndex; + + void _onChanged(int newIndex) { + if (_selectedIndex != newIndex) { + setState(() { + _selectedIndex = newIndex; + }); + widget.onChanged?.call(_selectedIndex); + } + } + + @override + void initState() { + _selectedIndex = widget.initialIndex; + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Row( + children: [ + Expanded( + child: GestureDetector( + onTap: () => _onChanged(0), + child: Container( + color: Colors.transparent, + child: Column( + children: [ + const SizedBox( + height: 16, + ), + Text( + "Send", + style: STextStyles.desktopTextExtraSmall(context).copyWith( + color: _selectedIndex == 0 + ? Theme.of(context) + .extension()! + .accentColorBlue + : Theme.of(context) + .extension()! + .textSubtitle1, + ), + ), + const SizedBox( + height: 19, + ), + Container( + height: 2, + decoration: BoxDecoration( + color: _selectedIndex == 0 + ? Theme.of(context) + .extension()! + .accentColorBlue + : Theme.of(context) + .extension()! + .background, + ), + ), + ], + ), + ), + ), + ), + Expanded( + child: GestureDetector( + onTap: () => _onChanged(1), + child: Container( + color: Colors.transparent, + child: Column( + children: [ + const SizedBox( + height: 16, + ), + Text( + "Receive", + style: STextStyles.desktopTextExtraSmall(context).copyWith( + color: _selectedIndex == 1 + ? Theme.of(context) + .extension()! + .accentColorBlue + : Theme.of(context) + .extension()! + .textSubtitle1, + ), + ), + const SizedBox( + height: 19, + ), + Container( + height: 2, + decoration: BoxDecoration( + color: _selectedIndex == 1 + ? Theme.of(context) + .extension()! + .accentColorBlue + : Theme.of(context) + .extension()! + .background, + ), + ), + ], + ), + ), + ), + ), + ], + ); + } +} + +class RecentDesktopTransactions extends StatefulWidget { + const RecentDesktopTransactions({Key? key}) : super(key: key); + + @override + State createState() => + _RecentDesktopTransactionsState(); +} + +class _RecentDesktopTransactionsState extends State { + @override + Widget build(BuildContext context) { + return Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Recent transactions", + style: STextStyles.desktopTextExtraSmall(context).copyWith( + color: Theme.of(context) + .extension()! + .textFieldActiveSearchIconLeft, + ), + ), + BlueTextButton( + text: "See all", + onTap: () { + // todo: show all txns + }, + ), + ], + ), + const SizedBox( + height: 16, + ), + Expanded( + child: RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: Container(), + ), + ), + ], + ); + } +} + +class NetworkInfoButton extends StatelessWidget { + const NetworkInfoButton({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + child: Text("todo: sync status"), + ); + } +} + +class WalletKeysButton extends StatelessWidget { + const WalletKeysButton({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + child: Text("todo: wallet keys"), + ); + } +} diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/receive/desktop_receive.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/receive/desktop_receive.dart new file mode 100644 index 000000000..79e3b81cf --- /dev/null +++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/receive/desktop_receive.dart @@ -0,0 +1,236 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:qr_flutter/qr_flutter.dart'; +import 'package:stackwallet/notifications/show_flush_bar.dart'; +import 'package:stackwallet/pages/receive_view/generate_receiving_uri_qr_code_view.dart'; +import 'package:stackwallet/providers/providers.dart'; +import 'package:stackwallet/route_generator.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/clipboard_interface.dart'; +import 'package:stackwallet/utilities/constants.dart'; +import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/enums/flush_bar_type.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart'; +import 'package:stackwallet/widgets/custom_loading_overlay.dart'; +import 'package:stackwallet/widgets/desktop/secondary_button.dart'; +import 'package:stackwallet/widgets/rounded_white_container.dart'; + +class DesktopReceive extends ConsumerStatefulWidget { + const DesktopReceive({ + Key? key, + required this.walletId, + this.clipboard = const ClipboardWrapper(), + }) : super(key: key); + + final String walletId; + final ClipboardInterface clipboard; + + @override + ConsumerState createState() => _DesktopReceiveState(); +} + +class _DesktopReceiveState extends ConsumerState { + late final Coin coin; + late final String walletId; + late final ClipboardInterface clipboard; + + Future generateNewAddress() async { + bool shouldPop = false; + unawaited( + showDialog( + context: context, + builder: (_) { + return WillPopScope( + onWillPop: () async => shouldPop, + child: Container( + color: Theme.of(context) + .extension()! + .overlay + .withOpacity(0.5), + child: const CustomLoadingOverlay( + message: "Generating address", + eventBus: null, + ), + ), + ); + }, + ), + ); + + await ref + .read(walletsChangeNotifierProvider) + .getManager(walletId) + .generateNewAddress(); + + shouldPop = true; + + if (mounted) { + Navigator.of(context, rootNavigator: true).pop(); + } + } + + String receivingAddress = ""; + + @override + void initState() { + walletId = widget.walletId; + coin = ref.read(walletsChangeNotifierProvider).getManager(walletId).coin; + clipboard = widget.clipboard; + + WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { + final address = await ref + .read(walletsChangeNotifierProvider) + .getManager(walletId) + .currentReceivingAddress; + setState(() { + receivingAddress = address; + }); + }); + + super.initState(); + } + + @override + Widget build(BuildContext context) { + debugPrint("BUILD: $runtimeType"); + + ref.listen( + ref + .read(walletsChangeNotifierProvider) + .getManagerProvider(walletId) + .select((value) => value.currentReceivingAddress), + (previous, next) { + if (next is Future) { + next.then((value) => setState(() => receivingAddress = value)); + } + }); + + return Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + GestureDetector( + onTap: () { + clipboard.setData( + ClipboardData(text: receivingAddress), + ); + showFloatingFlushBar( + type: FlushBarType.info, + message: "Copied to clipboard", + iconAsset: Assets.svg.copy, + context: context, + ); + }, + child: Container( + decoration: BoxDecoration( + border: Border.all( + color: Theme.of(context).extension()!.background, + width: 2, + ), + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + child: RoundedWhiteContainer( + child: Column( + children: [ + Row( + children: [ + Text( + "Your ${coin.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( + receivingAddress, + style: STextStyles.itemSubtitle12(context), + ), + ), + ], + ), + ], + ), + ), + ), + ), + if (coin != Coin.epicCash) + const SizedBox( + height: 20, + ), + if (coin != Coin.epicCash) + SecondaryButton( + height: 56, + onPressed: generateNewAddress, + label: "Generate new address", + ), + const SizedBox( + height: 32, + ), + Center( + child: QrImage( + data: "${coin.uriScheme}:$receivingAddress", + size: 200, + foregroundColor: + Theme.of(context).extension()!.accentColorDark, + ), + ), + const SizedBox( + height: 32, + ), + Center( + child: BlueTextButton( + text: "Create new QR code", + onTap: () async { + unawaited( + Navigator.of(context).push( + RouteGenerator.getRoute( + shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute, + builder: (_) => GenerateUriQrCodeView( + coin: coin, + receivingAddress: receivingAddress, + ), + settings: const RouteSettings( + name: GenerateUriQrCodeView.routeName, + ), + ), + ), + ); + }, + ), + ), + ], + ); + } +} diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/send/desktop_send.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/send/desktop_send.dart new file mode 100644 index 000000000..1579b2367 --- /dev/null +++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/send/desktop_send.dart @@ -0,0 +1,1164 @@ +import 'dart:async'; + +import 'package:decimal/decimal.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:stackwallet/models/send_view_auto_fill_data.dart'; +import 'package:stackwallet/pages/address_book_views/address_book_view.dart'; +import 'package:stackwallet/pages/send_view/sub_widgets/firo_balance_selection_sheet.dart'; +import 'package:stackwallet/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart'; +import 'package:stackwallet/providers/providers.dart'; +import 'package:stackwallet/providers/ui/fee_rate_type_state_provider.dart'; +import 'package:stackwallet/providers/ui/preview_tx_button_state_provider.dart'; +import 'package:stackwallet/providers/wallet/public_private_balance_state_provider.dart'; +import 'package:stackwallet/route_generator.dart'; +import 'package:stackwallet/services/coins/firo/firo_wallet.dart'; +import 'package:stackwallet/services/coins/manager.dart'; +import 'package:stackwallet/utilities/address_utils.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/barcode_scanner_interface.dart'; +import 'package:stackwallet/utilities/clipboard_interface.dart'; +import 'package:stackwallet/utilities/constants.dart'; +import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/enums/fee_rate_type_enum.dart'; +import 'package:stackwallet/utilities/format.dart'; +import 'package:stackwallet/utilities/logger.dart'; +import 'package:stackwallet/utilities/prefs.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/utilities/util.dart'; +import 'package:stackwallet/widgets/animated_text.dart'; +import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart'; +import 'package:stackwallet/widgets/desktop/primary_button.dart'; +import 'package:stackwallet/widgets/icon_widgets/addressbook_icon.dart'; +import 'package:stackwallet/widgets/icon_widgets/clipboard_icon.dart'; +import 'package:stackwallet/widgets/icon_widgets/qrcode_icon.dart'; +import 'package:stackwallet/widgets/icon_widgets/x_icon.dart'; +import 'package:stackwallet/widgets/stack_dialog.dart'; +import 'package:stackwallet/widgets/stack_text_field.dart'; +import 'package:stackwallet/widgets/textfield_icon_button.dart'; + +import '../../../../../pages/send_view/confirm_transaction_view.dart'; +import '../../../../../pages/send_view/sub_widgets/building_transaction_dialog.dart'; + +class DesktopSend extends ConsumerStatefulWidget { + const DesktopSend({ + Key? key, + required this.walletId, + this.autoFillData, + this.clipboard = const ClipboardWrapper(), + this.barcodeScanner = const BarcodeScannerWrapper(), + }) : super(key: key); + + final String walletId; + final SendViewAutoFillData? autoFillData; + final ClipboardInterface clipboard; + final BarcodeScannerInterface barcodeScanner; + + @override + ConsumerState createState() => _DesktopSendState(); +} + +class _DesktopSendState extends ConsumerState { + late final String walletId; + late final Coin coin; + late final ClipboardInterface clipboard; + late final BarcodeScannerInterface scanner; + + late TextEditingController sendToController; + late TextEditingController cryptoAmountController; + late TextEditingController baseAmountController; + late TextEditingController noteController; + late TextEditingController feeController; + + late final SendViewAutoFillData? _data; + + final _addressFocusNode = FocusNode(); + final _noteFocusNode = FocusNode(); + final _cryptoFocus = FocusNode(); + final _baseFocus = FocusNode(); + + Decimal? _amountToSend; + Decimal? _cachedAmountToSend; + String? _address; + + String? _privateBalanceString; + String? _publicBalanceString; + + bool _addressToggleFlag = false; + + bool _cryptoAmountChangeLock = false; + late VoidCallback onCryptoAmountChanged; + + Decimal? _cachedBalance; + + Future previewSend() async { + // wait for keyboard to disappear + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 100), + ); + final manager = + ref.read(walletsChangeNotifierProvider).getManager(walletId); + + // TODO: remove the need for this!! + final bool isOwnAddress = await manager.isOwnAddress(_address!); + if (isOwnAddress) { + await showDialog( + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return StackDialog( + title: "Transaction failed", + message: "Sending to self is currently disabled", + rightButton: TextButton( + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonColor(context), + child: Text( + "Ok", + style: STextStyles.button(context).copyWith( + color: Theme.of(context) + .extension()! + .accentColorDark), + ), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ); + }, + ); + return; + } + + final amount = Format.decimalAmountToSatoshis(_amountToSend!); + int availableBalance; + if ((coin == Coin.firo || coin == Coin.firoTestNet)) { + if (ref.read(publicPrivateBalanceStateProvider.state).state == + "Private") { + availableBalance = Format.decimalAmountToSatoshis( + await (manager.wallet as FiroWallet).availablePrivateBalance()); + } else { + availableBalance = Format.decimalAmountToSatoshis( + await (manager.wallet as FiroWallet).availablePublicBalance()); + } + } else { + availableBalance = + Format.decimalAmountToSatoshis(await manager.availableBalance); + } + + // confirm send all + if (amount == availableBalance) { + final bool? shouldSendAll = await showDialog( + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return StackDialog( + title: "Confirm send all", + message: + "You are about to send your entire balance. Would you like to continue?", + leftButton: TextButton( + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonColor(context), + child: Text( + "Cancel", + style: STextStyles.button(context).copyWith( + color: Theme.of(context) + .extension()! + .accentColorDark), + ), + onPressed: () { + Navigator.of(context).pop(false); + }, + ), + rightButton: TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonColor(context), + child: Text( + "Yes", + style: STextStyles.button(context), + ), + onPressed: () { + Navigator.of(context).pop(true); + }, + ), + ); + }, + ); + + if (shouldSendAll == null || shouldSendAll == false) { + // cancel preview + return; + } + } + + try { + bool wasCancelled = false; + + unawaited(showDialog( + context: context, + useSafeArea: false, + barrierDismissible: false, + builder: (context) { + return BuildingTransactionDialog( + onCancel: () { + wasCancelled = true; + + Navigator.of(context).pop(); + }, + ); + }, + )); + + Map txData; + + if ((coin == Coin.firo || coin == Coin.firoTestNet) && + ref.read(publicPrivateBalanceStateProvider.state).state != + "Private") { + txData = await (manager.wallet as FiroWallet).prepareSendPublic( + address: _address!, + satoshiAmount: amount, + args: {"feeRate": ref.read(feeRateTypeStateProvider)}, + ); + } else { + txData = await manager.prepareSend( + address: _address!, + satoshiAmount: amount, + args: {"feeRate": ref.read(feeRateTypeStateProvider)}, + ); + } + + if (!wasCancelled && mounted) { + // pop building dialog + Navigator.of(context).pop(); + txData["note"] = noteController.text; + txData["address"] = _address; + + unawaited(Navigator.of(context).push( + RouteGenerator.getRoute( + shouldUseMaterialRoute: RouteGenerator.useMaterialPageRoute, + builder: (_) => ConfirmTransactionView( + transactionInfo: txData, + walletId: walletId, + ), + settings: const RouteSettings( + name: ConfirmTransactionView.routeName, + ), + ), + )); + } + } catch (e) { + if (mounted) { + // pop building dialog + Navigator.of(context).pop(); + + unawaited(showDialog( + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return StackDialog( + title: "Transaction failed", + message: e.toString(), + rightButton: TextButton( + style: Theme.of(context) + .extension()! + .getSecondaryEnabledButtonColor(context), + child: Text( + "Ok", + style: STextStyles.button(context).copyWith( + color: Theme.of(context) + .extension()! + .accentColorDark), + ), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ); + }, + )); + } + } + } + + void _cryptoAmountChanged() async { + if (!_cryptoAmountChangeLock) { + final String cryptoAmount = cryptoAmountController.text; + if (cryptoAmount.isNotEmpty && + cryptoAmount != "." && + cryptoAmount != ",") { + _amountToSend = cryptoAmount.contains(",") + ? Decimal.parse(cryptoAmount.replaceFirst(",", ".")) + : Decimal.parse(cryptoAmount); + if (_cachedAmountToSend != null && + _cachedAmountToSend == _amountToSend) { + return; + } + _cachedAmountToSend = _amountToSend; + Logging.instance.log("it changed $_amountToSend $_cachedAmountToSend", + level: LogLevel.Info); + + final price = + ref.read(priceAnd24hChangeNotifierProvider).getPrice(coin).item1; + + if (price > Decimal.zero) { + final String fiatAmountString = Format.localizedStringAsFixed( + value: _amountToSend! * price, + locale: ref.read(localeServiceChangeNotifierProvider).locale, + decimalPlaces: 2, + ); + + baseAmountController.text = fiatAmountString; + } + } else { + _amountToSend = null; + baseAmountController.text = ""; + } + + _updatePreviewButtonState(_address, _amountToSend); + } + } + + String? _updateInvalidAddressText(String address, Manager manager) { + if (_data != null && _data!.contactLabel == address) { + return null; + } + if (address.isNotEmpty && !manager.validateAddress(address)) { + return "Invalid address"; + } + return null; + } + + void _updatePreviewButtonState(String? address, Decimal? amount) { + final isValidAddress = ref + .read(walletsChangeNotifierProvider) + .getManager(walletId) + .validateAddress(address ?? ""); + ref.read(previewTxButtonStateProvider.state).state = + (isValidAddress && amount != null && amount > Decimal.zero); + } + + late Future _calculateFeesFuture; + + Map cachedFees = {}; + Map cachedFiroPrivateFees = {}; + Map cachedFiroPublicFees = {}; + + Future calculateFees(int amount) async { + if (amount <= 0) { + return "0"; + } + + if (coin == Coin.firo || coin == Coin.firoTestNet) { + if (ref.read(publicPrivateBalanceStateProvider.state).state == + "Private") { + if (cachedFiroPrivateFees[amount] != null) { + return cachedFiroPrivateFees[amount]!; + } + } else { + if (cachedFiroPublicFees[amount] != null) { + return cachedFiroPublicFees[amount]!; + } + } + } else if (cachedFees[amount] != null) { + return cachedFees[amount]!; + } + + final manager = + ref.read(walletsChangeNotifierProvider).getManager(walletId); + final feeObject = await manager.fees; + + late final int feeRate; + + switch (ref.read(feeRateTypeStateProvider.state).state) { + case FeeRateType.fast: + feeRate = feeObject.fast; + break; + case FeeRateType.average: + feeRate = feeObject.medium; + break; + case FeeRateType.slow: + feeRate = feeObject.slow; + break; + } + + int fee; + + if (coin == Coin.firo || coin == Coin.firoTestNet) { + if (ref.read(publicPrivateBalanceStateProvider.state).state == + "Private") { + fee = await manager.estimateFeeFor(amount, feeRate); + + cachedFiroPrivateFees[amount] = Format.satoshisToAmount(fee) + .toStringAsFixed(Constants.decimalPlaces); + + return cachedFiroPrivateFees[amount]!; + } else { + fee = await (manager.wallet as FiroWallet) + .estimateFeeForPublic(amount, feeRate); + + cachedFiroPublicFees[amount] = Format.satoshisToAmount(fee) + .toStringAsFixed(Constants.decimalPlaces); + + return cachedFiroPublicFees[amount]!; + } + } else { + fee = await manager.estimateFeeFor(amount, feeRate); + cachedFees[amount] = + Format.satoshisToAmount(fee).toStringAsFixed(Constants.decimalPlaces); + + return cachedFees[amount]!; + } + } + + Future _firoBalanceFuture( + ChangeNotifierProvider provider, String locale) async { + final wallet = ref.read(provider).wallet as FiroWallet?; + + if (wallet != null) { + Decimal? balance; + if (ref.read(publicPrivateBalanceStateProvider.state).state == + "Private") { + balance = await wallet.availablePrivateBalance(); + } else { + balance = await wallet.availablePublicBalance(); + } + + return Format.localizedStringAsFixed( + value: balance, locale: locale, decimalPlaces: 8); + } + + return null; + } + + @override + void initState() { + ref.refresh(feeSheetSessionCacheProvider); + + _calculateFeesFuture = calculateFees(0); + _data = widget.autoFillData; + walletId = widget.walletId; + coin = ref.read(walletsChangeNotifierProvider).getManager(walletId).coin; + clipboard = widget.clipboard; + scanner = widget.barcodeScanner; + + sendToController = TextEditingController(); + cryptoAmountController = TextEditingController(); + baseAmountController = TextEditingController(); + noteController = TextEditingController(); + feeController = TextEditingController(); + + onCryptoAmountChanged = _cryptoAmountChanged; + cryptoAmountController.addListener(onCryptoAmountChanged); + + if (_data != null) { + if (_data!.amount != null) { + cryptoAmountController.text = _data!.amount!.toString(); + } + sendToController.text = _data!.contactLabel; + _address = _data!.address; + _addressToggleFlag = true; + } + + _cryptoFocus.addListener(() { + if (!_cryptoFocus.hasFocus && !_baseFocus.hasFocus) { + if (_amountToSend == null) { + setState(() { + _calculateFeesFuture = calculateFees(0); + }); + } else { + setState(() { + _calculateFeesFuture = + calculateFees(Format.decimalAmountToSatoshis(_amountToSend!)); + }); + } + } + }); + + _baseFocus.addListener(() { + if (!_cryptoFocus.hasFocus && !_baseFocus.hasFocus) { + if (_amountToSend == null) { + setState(() { + _calculateFeesFuture = calculateFees(0); + }); + } else { + setState(() { + _calculateFeesFuture = + calculateFees(Format.decimalAmountToSatoshis(_amountToSend!)); + }); + } + } + }); + + super.initState(); + } + + @override + void dispose() { + cryptoAmountController.removeListener(onCryptoAmountChanged); + + sendToController.dispose(); + cryptoAmountController.dispose(); + baseAmountController.dispose(); + noteController.dispose(); + feeController.dispose(); + + _noteFocusNode.dispose(); + _addressFocusNode.dispose(); + _cryptoFocus.dispose(); + _baseFocus.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + debugPrint("BUILD: $runtimeType"); + final provider = ref.watch(walletsChangeNotifierProvider + .select((value) => value.getManagerProvider(walletId))); + final String locale = ref.watch( + localeServiceChangeNotifierProvider.select((value) => value.locale)); + + if (coin == Coin.firo || coin == Coin.firoTestNet) { + ref.listen(publicPrivateBalanceStateProvider, (previous, next) { + if (_amountToSend == null) { + setState(() { + _calculateFeesFuture = calculateFees(0); + }); + } else { + setState(() { + _calculateFeesFuture = + calculateFees(Format.decimalAmountToSatoshis(_amountToSend!)); + }); + } + }); + } + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox( + height: 4, + ), + if (coin == Coin.firo) + Text( + "Send from", + style: STextStyles.smallMed12(context), + textAlign: TextAlign.left, + ), + if (coin == Coin.firo) + const SizedBox( + height: 10, + ), + if (coin == Coin.firo) + 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(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} balance", + style: STextStyles.itemSubtitle12(context), + ), + const SizedBox( + width: 10, + ), + FutureBuilder( + future: _firoBalanceFuture(provider, locale), + builder: + (context, AsyncSnapshot snapshot) { + if (snapshot.connectionState == + ConnectionState.done && + snapshot.hasData) { + if (ref + .read(publicPrivateBalanceStateProvider + .state) + .state == + "Private") { + _privateBalanceString = snapshot.data!; + } else { + _publicBalanceString = snapshot.data!; + } + } + if (ref + .read( + publicPrivateBalanceStateProvider + .state) + .state == + "Private" && + _privateBalanceString != null) { + return Text( + "$_privateBalanceString ${coin.ticker}", + style: STextStyles.itemSubtitle(context), + ); + } else if (ref + .read( + publicPrivateBalanceStateProvider + .state) + .state == + "Public" && + _publicBalanceString != null) { + return Text( + "$_publicBalanceString ${coin.ticker}", + style: STextStyles.itemSubtitle(context), + ); + } else { + return AnimatedText( + stringsToLoopThrough: const [ + "Loading balance", + "Loading balance.", + "Loading balance..", + "Loading balance...", + ], + style: STextStyles.itemSubtitle(context), + ); + } + }, + ), + ], + ), + SvgPicture.asset( + Assets.svg.chevronDown, + width: 8, + height: 4, + color: Theme.of(context) + .extension()! + .textSubtitle2, + ), + ], + ), + ), + ) + ], + ), + if (coin == Coin.firo) + const SizedBox( + height: 20, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Amount", + style: STextStyles.smallMed12(context), + textAlign: TextAlign.left, + ), + BlueTextButton( + text: "Send all ${coin.ticker}", + onTap: () async { + if (coin == Coin.firo || coin == Coin.firoTestNet) { + final firoWallet = ref.read(provider).wallet as FiroWallet; + if (ref.read(publicPrivateBalanceStateProvider.state).state == + "Private") { + cryptoAmountController.text = + (await firoWallet.availablePrivateBalance()) + .toStringAsFixed(Constants.decimalPlaces); + } else { + cryptoAmountController.text = + (await firoWallet.availablePublicBalance()) + .toStringAsFixed(Constants.decimalPlaces); + } + } else { + cryptoAmountController.text = + (await ref.read(provider).availableBalance) + .toStringAsFixed(Constants.decimalPlaces); + } + }, + ), + ], + ), + const SizedBox( + height: 10, + ), + 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: const TextInputType.numberWithOptions( + signed: false, + decimal: true, + ), + textAlign: TextAlign.right, + inputFormatters: [ + // 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( + coin.ticker, + style: STextStyles.smallMed14(context).copyWith( + color: Theme.of(context) + .extension()! + .accentColorDark), + ), + ), + ), + ), + ), + if (Prefs.instance.externalCalls) + const SizedBox( + height: 10, + ), + 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: const TextInputType.numberWithOptions( + signed: false, + decimal: true, + ), + textAlign: TextAlign.right, + inputFormatters: [ + // 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: (baseAmountString) { + if (baseAmountString.isNotEmpty && + baseAmountString != "." && + baseAmountString != ",") { + final baseAmount = baseAmountString.contains(",") + ? Decimal.parse(baseAmountString.replaceFirst(",", ".")) + : Decimal.parse(baseAmountString); + + var _price = ref + .read(priceAnd24hChangeNotifierProvider) + .getPrice(coin) + .item1; + + if (_price == Decimal.zero) { + _amountToSend = Decimal.zero; + } else { + _amountToSend = baseAmount <= Decimal.zero + ? Decimal.zero + : (baseAmount / _price).toDecimal( + scaleOnInfinitePrecision: Constants.decimalPlaces); + } + if (_cachedAmountToSend != null && + _cachedAmountToSend == _amountToSend) { + return; + } + _cachedAmountToSend = _amountToSend; + Logging.instance.log( + "it changed $_amountToSend $_cachedAmountToSend", + level: LogLevel.Info); + + final amountString = Format.localizedStringAsFixed( + value: _amountToSend!, + locale: ref.read(localeServiceChangeNotifierProvider).locale, + decimalPlaces: Constants.decimalPlaces, + ); + + _cryptoAmountChangeLock = true; + cryptoAmountController.text = amountString; + _cryptoAmountChangeLock = false; + } else { + _amountToSend = Decimal.zero; + _cryptoAmountChangeLock = true; + cryptoAmountController.text = ""; + _cryptoAmountChangeLock = false; + } + // setState(() { + // _calculateFeesFuture = calculateFees( + // Format.decimalAmountToSatoshis( + // _amountToSend!)); + // }); + _updatePreviewButtonState(_address, _amountToSend); + }, + 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), + ), + ), + ), + ), + ), + const SizedBox( + height: 20, + ), + Text( + "Send to", + style: STextStyles.smallMed12(context), + textAlign: TextAlign.left, + ), + const SizedBox( + height: 10, + ), + ClipRRect( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + 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) { + _address = newValue; + _updatePreviewButtonState(_address, _amountToSend); + + 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( + key: const Key( + "sendViewClearAddressFieldButtonKey"), + onTap: () { + sendToController.text = ""; + _address = ""; + _updatePreviewButtonState( + _address, _amountToSend); + setState(() { + _addressToggleFlag = false; + }); + }, + 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) { + String content = data.text!.trim(); + if (content.contains("\n")) { + content = content.substring( + 0, content.indexOf("\n")); + } + + sendToController.text = content; + _address = content; + + _updatePreviewButtonState( + _address, _amountToSend); + setState(() { + _addressToggleFlag = + sendToController.text.isNotEmpty; + }); + } + }, + child: sendToController.text.isEmpty + ? const ClipboardIcon() + : const XIcon(), + ), + if (sendToController.text.isEmpty) + TextFieldIconButton( + key: const Key("sendViewAddressBookButtonKey"), + onTap: () { + Navigator.of(context).pushNamed( + AddressBookView.routeName, + arguments: coin, + ); + }, + child: const AddressBookIcon(), + ), + if (sendToController.text.isEmpty) + TextFieldIconButton( + key: const Key("sendViewScanQrButtonKey"), + onTap: () async { + try { + if (FocusScope.of(context).hasFocus) { + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 75)); + } + + final qrResult = await scanner.scan(); + + Logging.instance.log( + "qrResult content: ${qrResult.rawContent}", + level: LogLevel.Info); + + final results = + AddressUtils.parseUri(qrResult.rawContent); + + Logging.instance.log("qrResult parsed: $results", + level: LogLevel.Info); + + if (results.isNotEmpty && + results["scheme"] == coin.uriScheme) { + // auto fill address + _address = results["address"] ?? ""; + sendToController.text = _address!; + + // autofill notes field + if (results["message"] != null) { + noteController.text = results["message"]!; + } else if (results["label"] != null) { + noteController.text = results["label"]!; + } + + // autofill amount field + if (results["amount"] != null) { + final amount = + Decimal.parse(results["amount"]!); + cryptoAmountController.text = + Format.localizedStringAsFixed( + value: amount, + locale: ref + .read( + localeServiceChangeNotifierProvider) + .locale, + decimalPlaces: Constants.decimalPlaces, + ); + amount.toString(); + _amountToSend = amount; + } + + _updatePreviewButtonState( + _address, _amountToSend); + setState(() { + _addressToggleFlag = + sendToController.text.isNotEmpty; + }); + + // now check for non standard encoded basic address + } else if (ref + .read(walletsChangeNotifierProvider) + .getManager(walletId) + .validateAddress(qrResult.rawContent)) { + _address = qrResult.rawContent; + sendToController.text = _address ?? ""; + + _updatePreviewButtonState( + _address, _amountToSend); + setState(() { + _addressToggleFlag = + sendToController.text.isNotEmpty; + }); + } + } on PlatformException catch (e, s) { + // here we ignore the exception caused by not giving permission + // to use the camera to scan a qr code + Logging.instance.log( + "Failed to get camera permissions while trying to scan qr code in SendView: $e\n$s", + level: LogLevel.Warning); + } + }, + child: const QrCodeIcon(), + ) + ], + ), + ), + ), + ), + ), + ), + Builder( + builder: (_) { + final error = _updateInvalidAddressText( + _address ?? "", + ref.read(walletsChangeNotifierProvider).getManager(walletId), + ); + + 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: 20, + ), + Text( + "Note (optional)", + style: STextStyles.smallMed12(context), + textAlign: TextAlign.left, + ), + const SizedBox( + height: 10, + ), + 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: 36, + ), + PrimaryButton( + height: 56, + label: "Preview send", + enabled: ref.watch(previewTxButtonStateProvider.state).state, + onPressed: ref.watch(previewTxButtonStateProvider.state).state + ? previewSend + : null, + ) + ], + ); + } +} diff --git a/lib/pages_desktop_specific/home/settings_menu/advanced_settings.dart b/lib/pages_desktop_specific/home/settings_menu/advanced_settings.dart new file mode 100644 index 000000000..e470a73aa --- /dev/null +++ b/lib/pages_desktop_specific/home/settings_menu/advanced_settings.dart @@ -0,0 +1,104 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/widgets/rounded_white_container.dart'; + +class AdvancedSettings extends ConsumerStatefulWidget { + const AdvancedSettings({Key? key}) : super(key: key); + + static const String routeName = "/settingsMenuAdvanced"; + + @override + ConsumerState createState() => _AdvancedSettings(); +} + +class _AdvancedSettings extends ConsumerState { + @override + Widget build(BuildContext context) { + debugPrint("BUILD: $runtimeType"); + return Column( + children: [ + Padding( + padding: const EdgeInsets.only( + right: 30, + ), + child: RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SvgPicture.asset( + Assets.svg.circleLanguage, + width: 48, + height: 48, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Padding( + padding: const EdgeInsets.all(10), + child: RichText( + textAlign: TextAlign.start, + text: TextSpan( + children: [ + TextSpan( + text: "Advanced", + style: STextStyles.desktopTextSmall(context), + ), + TextSpan( + text: + "\n\nConfigurate these settings only if you know what you are doing!", + style: STextStyles.desktopTextExtraExtraSmall( + context), + ), + ], + ), + ), + ), + ], + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: const [ + Padding( + padding: EdgeInsets.all( + 10, + ), + child: ShowLogsButton(), + ), + ], + ), + ], + ), + ), + ), + ], + ); + } +} + +class ShowLogsButton extends ConsumerWidget { + const ShowLogsButton({ + Key? key, + }) : super(key: key); + @override + Widget build(BuildContext context, WidgetRef ref) { + return SizedBox( + width: 200, + height: 48, + child: TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonColor(context), + onPressed: () {}, + child: Text( + "Show logs", + style: STextStyles.button(context), + ), + ), + ); + } +} diff --git a/lib/pages_desktop_specific/home/settings_menu/appearance_settings.dart b/lib/pages_desktop_specific/home/settings_menu/appearance_settings.dart new file mode 100644 index 000000000..d524453e2 --- /dev/null +++ b/lib/pages_desktop_specific/home/settings_menu/appearance_settings.dart @@ -0,0 +1,315 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/widgets/rounded_white_container.dart'; + +import '../../../providers/global/prefs_provider.dart'; +import '../../../utilities/constants.dart'; +import '../../../widgets/custom_buttons/draggable_switch_button.dart'; + +class AppearanceOptionSettings extends ConsumerStatefulWidget { + const AppearanceOptionSettings({Key? key}) : super(key: key); + + static const String routeName = "/settingsMenuAppearance"; + + @override + ConsumerState createState() => + _AppearanceOptionSettings(); +} + +class _AppearanceOptionSettings + extends ConsumerState { + @override + Widget build(BuildContext context) { + debugPrint("BUILD: $runtimeType"); + return Column( + children: [ + Padding( + padding: const EdgeInsets.only( + right: 30, + ), + child: RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SvgPicture.asset( + Assets.svg.circleSun, + width: 48, + height: 48, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Padding( + padding: const EdgeInsets.all(10), + child: RichText( + textAlign: TextAlign.left, + text: TextSpan( + children: [ + TextSpan( + text: "Appearances", + style: STextStyles.desktopTextSmall(context), + ), + TextSpan( + text: + "\n\nCustomize how your Stack Wallet looks according to your preferences.", + style: STextStyles.desktopTextExtraExtraSmall( + context), + ), + ], + ), + ), + ), + ], + ), + const Padding( + padding: EdgeInsets.all(10.0), + child: Divider( + thickness: 0.5, + ), + ), + Padding( + padding: const EdgeInsets.all(10.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Display favorite wallets", + style: STextStyles.desktopTextExtraSmall(context) + .copyWith( + color: Theme.of(context) + .extension()! + .textDark), + 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; + }, + ), + ) + ], + ), + ), + const Padding( + padding: EdgeInsets.all(10.0), + child: Divider( + thickness: 0.5, + ), + ), + Padding( + padding: const EdgeInsets.all(10.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Choose theme", + style: STextStyles.desktopTextExtraSmall(context) + .copyWith( + color: Theme.of(context) + .extension()! + .textDark), + textAlign: TextAlign.left, + ), + ], + ), + ), + const Padding( + padding: EdgeInsets.only( + left: 10, + right: 10, + ), + child: ThemeToggle(), + ), + ], + ), + ), + ), + ], + ); + } +} + +class ThemeToggle extends StatefulWidget { + const ThemeToggle({ + Key? key, + }) : super(key: key); + + // final bool externalCallsEnabled; + // final void Function(bool)? onChanged; + + @override + State createState() => _ThemeToggle(); +} + +class _ThemeToggle extends State { + // late bool externalCallsEnabled; + + @override + Widget build(BuildContext context) { + return Row( + // mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: RawMaterialButton( + elevation: 0, + hoverColor: Colors.transparent, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius * 2, + ), + ), + onPressed: () {}, //onPressed + child: Stack( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only( + left: 24, + ), + child: SvgPicture.asset( + Assets.svg.themeLight, + ), + ), + Padding( + padding: const EdgeInsets.only( + left: 50, + top: 12, + ), + child: Text( + "Light", + style: + STextStyles.desktopTextExtraSmall(context).copyWith( + color: Theme.of(context) + .extension()! + .textDark, + ), + ), + ) + ], + ), + // if (externalCallsEnabled) + Positioned( + bottom: 0, + left: 6, + child: SvgPicture.asset( + Assets.svg.checkCircle, + width: 20, + height: 20, + color: Theme.of(context) + .extension()! + .infoItemIcons, + ), + ), + // if (!externalCallsEnabled) + // Positioned( + // top: 4, + // right: 4, + // child: Container( + // width: 20, + // height: 20, + // decoration: BoxDecoration( + // borderRadius: BorderRadius.circular(1000), + // color: Theme.of(context) + // .extension()! + // .textFieldDefaultBG, + // ), + // ), + // ), + ], + ), + ), + ), + const SizedBox( + width: 1, + ), + Expanded( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: RawMaterialButton( + elevation: 0, + hoverColor: Colors.transparent, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius * 2, + ), + ), + onPressed: () {}, //onPressed + child: Stack( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SvgPicture.asset( + Assets.svg.themeDark, + ), + Padding( + padding: const EdgeInsets.only( + left: 50, + top: 12, + ), + child: Text( + "Dark", + style: STextStyles.desktopTextExtraSmall(context) + .copyWith( + color: Theme.of(context) + .extension()! + .textDark, + ), + ), + ), + ], + ), + // if (externalCallsEnabled) + Positioned( + bottom: 0, + left: 0, + child: SvgPicture.asset( + Assets.svg.checkCircle, + width: 20, + height: 20, + color: Theme.of(context) + .extension()! + .infoItemIcons, + ), + ), + // if (!externalCallsEnabled) + // Positioned( + // top: 4, + // right: 4, + // child: Container( + // width: 20, + // height: 20, + // decoration: BoxDecoration( + // borderRadius: BorderRadius.circular(1000), + // color: Theme.of(context) + // .extension()! + // .textFieldDefaultBG, + // ), + // ), + // ), + ], + ), + ), + ), + ), + ], + ); + } +} diff --git a/lib/pages_desktop_specific/home/settings_menu/backup_and_restore.dart b/lib/pages_desktop_specific/home/settings_menu/backup_and_restore.dart deleted file mode 100644 index e69de29bb..000000000 diff --git a/lib/pages_desktop_specific/home/settings_menu/backup_and_restore_settings.dart b/lib/pages_desktop_specific/home/settings_menu/backup_and_restore_settings.dart new file mode 100644 index 000000000..04c23ee83 --- /dev/null +++ b/lib/pages_desktop_specific/home/settings_menu/backup_and_restore_settings.dart @@ -0,0 +1,282 @@ +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/widgets/rounded_white_container.dart'; +import 'package:url_launcher/url_launcher.dart'; + +class BackupRestoreSettings extends ConsumerStatefulWidget { + const BackupRestoreSettings({Key? key}) : super(key: key); + + static const String routeName = "/settingsMenuBackupRestore"; + + @override + ConsumerState createState() => + _BackupRestoreSettings(); +} + +class _BackupRestoreSettings extends ConsumerState { + @override + Widget build(BuildContext context) { + debugPrint("BUILD: $runtimeType"); + return ListView( + shrinkWrap: true, + scrollDirection: Axis.vertical, + children: [ + Padding( + padding: const EdgeInsets.only( + right: 30, + ), + child: RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SvgPicture.asset( + Assets.svg.backupAuto, + width: 48, + height: 48, + ), + Center( + child: Padding( + padding: const EdgeInsets.all(10), + child: RichText( + textAlign: TextAlign.start, + text: TextSpan( + children: [ + TextSpan( + text: "Auto Backup", + style: STextStyles.desktopTextSmall(context), + ), + TextSpan( + text: + "\n\nAuto backup is a custom Stack Wallet feature that offers a convenient backup of your data." + "To 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.", + style: + STextStyles.desktopTextExtraExtraSmall(context), + ), + TextSpan( + text: + "\n\nFor more information, please see our website ", + style: + STextStyles.desktopTextExtraExtraSmall(context), + ), + TextSpan( + text: "stackwallet.com", + style: STextStyles.richLink(context) + .copyWith(fontSize: 14), + recognizer: TapGestureRecognizer() + ..onTap = () { + launchUrl( + Uri.parse("https://stackwallet.com/"), + mode: LaunchMode.externalApplication, + ); + }, + ), + ], + ), + ), + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: const [ + Padding( + padding: EdgeInsets.all( + 10, + ), + child: AutoBackupButton(), + ), + ], + ), + ], + ), + ), + ), + const SizedBox( + height: 25, + ), + Padding( + padding: const EdgeInsets.only( + right: 30, + ), + child: RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SvgPicture.asset( + Assets.svg.backupAdd, + width: 48, + height: 48, + alignment: Alignment.topLeft, + ), + Center( + child: Padding( + padding: const EdgeInsets.all(10), + child: RichText( + textAlign: TextAlign.start, + text: TextSpan( + children: [ + TextSpan( + text: "Manual Backup", + style: STextStyles.desktopTextSmall(context), + ), + TextSpan( + text: + "\n\nCreate manual backup to easily transfer your data between devices. " + "You will create a backup file that can be later used in the Restore option. " + "Use a strong password to encrypt your data.", + style: + STextStyles.desktopTextExtraExtraSmall(context), + ), + ], + ), + ), + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: const [ + Padding( + padding: EdgeInsets.all( + 10, + ), + child: ManualBackupButton(), + ), + ], + ), + ], + ), + ), + ), + const SizedBox( + height: 25, + ), + Padding( + padding: const EdgeInsets.only( + right: 30, + ), + child: RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SvgPicture.asset( + Assets.svg.backupRestore, + width: 48, + height: 48, + alignment: Alignment.topLeft, + ), + Center( + child: Padding( + padding: const EdgeInsets.all(10), + child: RichText( + textAlign: TextAlign.start, + text: TextSpan( + children: [ + TextSpan( + text: "Restore Backup", + style: STextStyles.desktopTextSmall(context), + ), + TextSpan( + text: + "\n\nUse your Stack Wallet backup file to restore your wallets, address book " + "and wallet preferences.", + style: + STextStyles.desktopTextExtraExtraSmall(context), + ), + ], + ), + ), + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: const [ + Padding( + padding: EdgeInsets.all( + 10, + ), + child: ManualBackupButton(), + ), + ], + ), + ], + ), + ), + ), + ], + ); + } +} + +class AutoBackupButton extends ConsumerWidget { + const AutoBackupButton({ + Key? key, + }) : super(key: key); + @override + Widget build(BuildContext context, WidgetRef ref) { + return SizedBox( + width: 200, + height: 48, + child: TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonColor(context), + onPressed: () {}, + child: Text( + "Enable auto backup", + style: STextStyles.button(context), + ), + ), + ); + } +} + +class ManualBackupButton extends ConsumerWidget { + const ManualBackupButton({ + Key? key, + }) : super(key: key); + @override + Widget build(BuildContext context, WidgetRef ref) { + return SizedBox( + width: 200, + height: 48, + child: TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonColor(context), + onPressed: () {}, + child: Text( + "Create manual backup", + style: STextStyles.button(context), + ), + ), + ); + } +} + +class RestoreBackupButton extends ConsumerWidget { + const RestoreBackupButton({ + Key? key, + }) : super(key: key); + @override + Widget build(BuildContext context, WidgetRef ref) { + return SizedBox( + width: 200, + height: 48, + child: TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonColor(context), + onPressed: () {}, + child: Text( + "Restore backup", + style: STextStyles.button(context), + ), + ), + ); + } +} diff --git a/lib/pages_desktop_specific/home/settings_menu/currency_settings.dart b/lib/pages_desktop_specific/home/settings_menu/currency_settings.dart new file mode 100644 index 000000000..4327b320b --- /dev/null +++ b/lib/pages_desktop_specific/home/settings_menu/currency_settings.dart @@ -0,0 +1,102 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/widgets/rounded_white_container.dart'; + +class CurrencySettings extends ConsumerStatefulWidget { + const CurrencySettings({Key? key}) : super(key: key); + + static const String routeName = "/settingsMenuCurrency"; + + @override + ConsumerState createState() => _CurrencySettings(); +} + +class _CurrencySettings extends ConsumerState { + @override + Widget build(BuildContext context) { + debugPrint("BUILD: $runtimeType"); + return Column( + children: [ + Padding( + padding: const EdgeInsets.only( + right: 30, + ), + child: RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SvgPicture.asset( + Assets.svg.circleDollarSign, + width: 48, + height: 48, + ), + Center( + child: Padding( + padding: const EdgeInsets.all(10), + child: RichText( + textAlign: TextAlign.start, + text: TextSpan( + children: [ + TextSpan( + text: "Currency", + style: STextStyles.desktopTextSmall(context), + ), + TextSpan( + text: + "\n\nProtect your Stack Wallet with a strong password. Stack Wallet does not store " + "your password, and is therefore NOT able to restore it. Keep your password safe and secure.", + style: + STextStyles.desktopTextExtraExtraSmall(context), + ), + ], + ), + ), + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: const [ + Padding( + padding: EdgeInsets.all( + 10, + ), + child: NewPasswordButton(), + ), + ], + ), + ], + ), + ), + ), + ], + ); + } +} + +class NewPasswordButton extends ConsumerWidget { + const NewPasswordButton({ + Key? key, + }) : super(key: key); + @override + Widget build(BuildContext context, WidgetRef ref) { + return SizedBox( + width: 200, + height: 48, + child: TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonColor(context), + onPressed: () {}, + child: Text( + "Set up new password", + style: STextStyles.button(context), + ), + ), + ); + } +} diff --git a/lib/pages_desktop_specific/home/settings_menu/enable_backup_dialog.dart b/lib/pages_desktop_specific/home/settings_menu/enable_backup_dialog.dart new file mode 100644 index 000000000..4925177c3 --- /dev/null +++ b/lib/pages_desktop_specific/home/settings_menu/enable_backup_dialog.dart @@ -0,0 +1,73 @@ +import 'package:flutter/material.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog.dart'; +import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart'; +import 'package:stackwallet/widgets/desktop/primary_button.dart'; +import 'package:stackwallet/widgets/desktop/secondary_button.dart'; + +class EnableBackupDialog extends StatelessWidget { + const EnableBackupDialog({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return DesktopDialog( + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Padding( + padding: const EdgeInsets.all(32), + child: Text( + "Enable Auto Backup", + style: STextStyles.desktopH3(context), + textAlign: TextAlign.center, + ), + ), + const DesktopDialogCloseButton(), + ], + ), + const SizedBox( + height: 30, + ), + Text( + "To enable Auto Backup, you need to create a backup file.", + style: STextStyles.desktopTextSmall(context).copyWith( + color: Theme.of(context).extension()!.textDark3, + ), + textAlign: TextAlign.center, + ), + const Spacer(), + Padding( + padding: const EdgeInsets.all(32), + child: Row( + children: [ + Expanded( + child: SecondaryButton( + label: "Cancel", + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ), + const SizedBox( + width: 16, + ), + Expanded( + child: PrimaryButton( + label: "Continue", + onPressed: () { + // Navigator.of(context).pop(); + // onConfirm.call(); + }, + ), + ) + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/pages_desktop_specific/home/settings_menu/language_settings.dart b/lib/pages_desktop_specific/home/settings_menu/language_settings.dart new file mode 100644 index 000000000..7655188e1 --- /dev/null +++ b/lib/pages_desktop_specific/home/settings_menu/language_settings.dart @@ -0,0 +1,105 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/widgets/rounded_white_container.dart'; + +class LanguageOptionSettings extends ConsumerStatefulWidget { + const LanguageOptionSettings({Key? key}) : super(key: key); + + static const String routeName = "/settingsMenuLanguage"; + + @override + ConsumerState createState() => + _LanguageOptionSettings(); +} + +class _LanguageOptionSettings extends ConsumerState { + @override + Widget build(BuildContext context) { + debugPrint("BUILD: $runtimeType"); + return Column( + children: [ + Padding( + padding: const EdgeInsets.only( + right: 30, + ), + child: RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SvgPicture.asset( + Assets.svg.circleLanguage, + width: 48, + height: 48, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Padding( + padding: const EdgeInsets.all(10), + child: RichText( + textAlign: TextAlign.start, + text: TextSpan( + children: [ + TextSpan( + text: "Language", + style: STextStyles.desktopTextSmall(context), + ), + TextSpan( + text: + "\n\nSelect the language of your wallet. We use your system language by default.", + style: STextStyles.desktopTextExtraExtraSmall( + context), + ), + ], + ), + ), + ), + ], + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: const [ + Padding( + padding: EdgeInsets.all( + 10, + ), + child: ChangeLanguageButton(), + ), + ], + ), + ], + ), + ), + ), + ], + ); + } +} + +class ChangeLanguageButton extends ConsumerWidget { + const ChangeLanguageButton({ + Key? key, + }) : super(key: key); + @override + Widget build(BuildContext context, WidgetRef ref) { + return SizedBox( + width: 200, + height: 48, + child: TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonColor(context), + onPressed: () {}, + child: Text( + "Change language", + style: STextStyles.button(context), + ), + ), + ); + } +} diff --git a/lib/pages_desktop_specific/home/settings_menu/nodes_settings.dart b/lib/pages_desktop_specific/home/settings_menu/nodes_settings.dart new file mode 100644 index 000000000..f354927c4 --- /dev/null +++ b/lib/pages_desktop_specific/home/settings_menu/nodes_settings.dart @@ -0,0 +1,180 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:stackwallet/providers/global/node_service_provider.dart'; +import 'package:stackwallet/providers/global/prefs_provider.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/enums/coin_enum.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/widgets/rounded_white_container.dart'; + +import '../../../pages/settings_views/global_settings_view/manage_nodes_views/coin_nodes_view.dart'; +import '../../../utilities/constants.dart'; + +class NodesSettings extends ConsumerStatefulWidget { + const NodesSettings({Key? key}) : super(key: key); + + static const String routeName = "/settingsMenuNodes"; + + @override + ConsumerState createState() => _NodesSettings(); +} + +class _NodesSettings extends ConsumerState { + List _coins = [...Coin.values]; + + @override + void initState() { + _coins = _coins.toList(); + _coins.remove(Coin.firoTestNet); + super.initState(); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + bool showTestNet = ref.watch( + prefsChangeNotifierProvider.select((value) => value.showTestNetCoins), + ); + + List coins = showTestNet + ? _coins + : _coins.sublist(0, _coins.length - kTestNetCoinCount); + + debugPrint("BUILD: $runtimeType"); + return Column( + children: [ + Padding( + padding: const EdgeInsets.only( + right: 30, + ), + child: RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SvgPicture.asset( + Assets.svg.circleNode, + width: 48, + height: 48, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Padding( + padding: const EdgeInsets.all(10), + child: RichText( + textAlign: TextAlign.start, + text: TextSpan( + children: [ + TextSpan( + text: "Nodes", + style: STextStyles.desktopTextSmall(context), + ), + TextSpan( + text: "\n\nSelect a coin to see nodes", + style: STextStyles.desktopTextExtraExtraSmall( + context), + ), + ], + ), + ), + ), + ], + ), + //TODO: add search bar + 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(0), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + // side: BorderSide( + // color: Theme.of(context) + // .extension()! + // .shadow), + ), + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + onPressed: () { + Navigator.of(context).pushNamed( + CoinNodesView.routeName, + arguments: coin, + ); + }, + child: Padding( + padding: const EdgeInsets.all( + 12.0, + ), + child: Row( + children: [ + Row( + children: [ + SvgPicture.asset( + Assets.svg.iconFor(coin: coin), + width: 24, + height: 24, + ), + const SizedBox( + width: 12, + ), + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "${coin.prettyName} nodes", + style: STextStyles.titleBold12( + context), + ), + Text( + count > 1 + ? "$count nodes" + : "Default", + style: STextStyles.label(context), + ), + ], + ), + ], + ), + Expanded( + child: SvgPicture.asset( + Assets.svg.chevronRight, + alignment: Alignment.centerRight, + ), + ), + ], + ), + ), + ), + ); + }, + ), + ], + ), + ), + ], + ), + ), + ), + ], + ); + } +} diff --git a/lib/pages_desktop_specific/home/settings_menu/security_settings.dart b/lib/pages_desktop_specific/home/settings_menu/security_settings.dart new file mode 100644 index 000000000..7c36be8cd --- /dev/null +++ b/lib/pages_desktop_specific/home/settings_menu/security_settings.dart @@ -0,0 +1,141 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/widgets/rounded_white_container.dart'; + +import '../../../utilities/theme/stack_colors.dart'; +import 'enable_backup_dialog.dart'; + +class SecuritySettings extends ConsumerStatefulWidget { + const SecuritySettings({Key? key}) : super(key: key); + + static const String routeName = "/settingsMenuSecurity"; + + @override + ConsumerState createState() => _SecuritySettings(); +} + +class _SecuritySettings extends ConsumerState { + Future enableAutoBackup() async { + // wait for keyboard to disappear + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 100), + ); + + await showDialog( + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return EnableBackupDialog(); + }, + ); + } + + @override + Widget build(BuildContext context) { + debugPrint("BUILD: $runtimeType"); + return Column( + children: [ + Padding( + padding: const EdgeInsets.only( + right: 30, + ), + child: RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SvgPicture.asset( + Assets.svg.circleLock, + width: 48, + height: 48, + ), + Center( + child: Padding( + padding: const EdgeInsets.all(10), + child: RichText( + textAlign: TextAlign.start, + text: TextSpan( + children: [ + TextSpan( + text: "Change Password", + style: STextStyles.desktopTextSmall(context), + ), + TextSpan( + text: + "\n\nProtect your Stack Wallet with a strong password. Stack Wallet does not store " + "your password, and is therefore NOT able to restore it. Keep your password safe and secure.", + style: + STextStyles.desktopTextExtraExtraSmall(context), + ), + ], + ), + ), + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: const [ + Padding( + padding: EdgeInsets.all( + 10, + ), + child: NewPasswordButton(), + ), + ], + ), + ], + ), + ), + ), + ], + ); + } +} + +class NewPasswordButton extends ConsumerWidget { + const NewPasswordButton({ + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context, WidgetRef ref) { + Future enableAutoBackup() async { + // wait for keyboard to disappear + FocusScope.of(context).unfocus(); + await Future.delayed( + const Duration(milliseconds: 100), + ); + + await showDialog( + context: context, + useSafeArea: false, + barrierDismissible: true, + builder: (context) { + return EnableBackupDialog(); + }, + ); + } + + return SizedBox( + width: 200, + height: 48, + child: TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonColor(context), + onPressed: () { + enableAutoBackup(); + }, + child: Text( + "Set up new password", + style: STextStyles.button(context), + ), + ), + ); + } +} diff --git a/lib/pages_desktop_specific/home/settings_menu/settings_menu.dart b/lib/pages_desktop_specific/home/settings_menu/settings_menu.dart index de800b51f..b743fdb39 100644 --- a/lib/pages_desktop_specific/home/settings_menu/settings_menu.dart +++ b/lib/pages_desktop_specific/home/settings_menu/settings_menu.dart @@ -3,7 +3,6 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:stackwallet/pages_desktop_specific/home/settings_menu_item.dart'; import 'package:stackwallet/utilities/assets.dart'; -import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; class SettingsMenu extends ConsumerStatefulWidget { @@ -35,155 +34,167 @@ class _SettingsMenuState extends ConsumerState { Widget build(BuildContext context) { debugPrint("BUILD: $runtimeType"); - return Material( - color: Theme.of(context).extension()!.background, - child: SizedBox( - width: 300, - child: Padding( - padding: const EdgeInsets.fromLTRB(24.0, 10.0, 0, 0), + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(left: 15), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - SizedBox( - height: 20, - // width: 300, - ), - Text( - "Settings", - style: STextStyles.desktopH3(context).copyWith( - fontSize: 24, + SettingsMenuItem( + icon: SvgPicture.asset( + Assets.svg.polygon, + width: 11, + height: 11, + color: selectedMenuItem == 0 + ? Theme.of(context) + .extension()! + .accentColorBlue + : Colors.transparent, ), + label: "Backup and restore", + value: 0, + group: selectedMenuItem, + onChanged: updateSelectedMenuItem, ), - Row( - children: [ - Padding( - padding: const EdgeInsets.fromLTRB( - 3.0, - 30.0, - 55.0, - 0, - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SettingsMenuItem( - icon: SvgPicture.asset( - Assets.svg.polygon, - width: 11, - height: 11, - ), - label: "Backup and restore", - value: 0, - group: selectedMenuItem, - onChanged: updateSelectedMenuItem, - ), - const SizedBox( - height: 2, - ), - SettingsMenuItem( - icon: SvgPicture.asset( - Assets.svg.polygon, - width: 11, - height: 11, - ), - label: "Security", - value: 1, - group: selectedMenuItem, - onChanged: updateSelectedMenuItem, - ), - const SizedBox( - height: 2, - ), - SettingsMenuItem( - icon: SvgPicture.asset( - Assets.svg.polygon, - width: 11, - height: 11, - ), - label: "Currency", - value: 2, - group: selectedMenuItem, - onChanged: updateSelectedMenuItem, - ), - const SizedBox( - height: 2, - ), - SettingsMenuItem( - icon: SvgPicture.asset( - Assets.svg.polygon, - width: 11, - height: 11, - ), - label: "Language", - value: 3, - group: selectedMenuItem, - onChanged: updateSelectedMenuItem, - ), - const SizedBox( - height: 2, - ), - SettingsMenuItem( - icon: SvgPicture.asset( - Assets.svg.polygon, - width: 11, - height: 11, - ), - label: "Nodes", - value: 4, - group: selectedMenuItem, - onChanged: updateSelectedMenuItem, - ), - const SizedBox( - height: 2, - ), - SettingsMenuItem( - icon: SvgPicture.asset( - Assets.svg.polygon, - width: 11, - height: 11, - ), - label: "Syncing preferences", - value: 5, - group: selectedMenuItem, - onChanged: updateSelectedMenuItem, - ), - const SizedBox( - height: 2, - ), - SettingsMenuItem( - icon: SvgPicture.asset( - Assets.svg.polygon, - width: 11, - height: 11, - ), - label: "Appearance", - value: 6, - group: selectedMenuItem, - onChanged: updateSelectedMenuItem, - ), - const SizedBox( - height: 2, - ), - SettingsMenuItem( - icon: SvgPicture.asset( - Assets.svg.polygon, - width: 11, - height: 11, - ), - label: "Advanced", - value: 7, - group: selectedMenuItem, - onChanged: updateSelectedMenuItem, - ), - ], - ), - ), - ], + const SizedBox( + height: 2, + ), + SettingsMenuItem( + icon: SvgPicture.asset( + Assets.svg.polygon, + width: 11, + height: 11, + color: selectedMenuItem == 1 + ? Theme.of(context) + .extension()! + .accentColorBlue + : Colors.transparent, + ), + label: "Security", + value: 1, + group: selectedMenuItem, + onChanged: updateSelectedMenuItem, + ), + const SizedBox( + height: 2, + ), + SettingsMenuItem( + icon: SvgPicture.asset( + Assets.svg.polygon, + width: 11, + height: 11, + color: selectedMenuItem == 2 + ? Theme.of(context) + .extension()! + .accentColorBlue + : Colors.transparent, + ), + label: "Currency", + value: 2, + group: selectedMenuItem, + onChanged: updateSelectedMenuItem, + ), + const SizedBox( + height: 2, + ), + SettingsMenuItem( + icon: SvgPicture.asset( + Assets.svg.polygon, + width: 11, + height: 11, + color: selectedMenuItem == 3 + ? Theme.of(context) + .extension()! + .accentColorBlue + : Colors.transparent, + ), + label: "Language", + value: 3, + group: selectedMenuItem, + onChanged: updateSelectedMenuItem, + ), + const SizedBox( + height: 2, + ), + SettingsMenuItem( + icon: SvgPicture.asset( + Assets.svg.polygon, + width: 11, + height: 11, + color: selectedMenuItem == 4 + ? Theme.of(context) + .extension()! + .accentColorBlue + : Colors.transparent, + ), + label: "Nodes", + value: 4, + group: selectedMenuItem, + onChanged: updateSelectedMenuItem, + ), + const SizedBox( + height: 2, + ), + SettingsMenuItem( + icon: SvgPicture.asset( + Assets.svg.polygon, + width: 11, + height: 11, + color: selectedMenuItem == 5 + ? Theme.of(context) + .extension()! + .accentColorBlue + : Colors.transparent, + ), + label: "Syncing preferences", + value: 5, + group: selectedMenuItem, + onChanged: updateSelectedMenuItem, + ), + const SizedBox( + height: 2, + ), + SettingsMenuItem( + icon: SvgPicture.asset( + Assets.svg.polygon, + width: 11, + height: 11, + color: selectedMenuItem == 6 + ? Theme.of(context) + .extension()! + .accentColorBlue + : Colors.transparent, + ), + label: "Appearance", + value: 6, + group: selectedMenuItem, + onChanged: updateSelectedMenuItem, + ), + const SizedBox( + height: 2, + ), + SettingsMenuItem( + icon: SvgPicture.asset( + Assets.svg.polygon, + width: 11, + height: 11, + color: selectedMenuItem == 7 + ? Theme.of(context) + .extension()! + .accentColorBlue + : Colors.transparent, + ), + label: "Advanced", + value: 7, + group: selectedMenuItem, + onChanged: updateSelectedMenuItem, ), ], ), ), - ), + ], ); } } diff --git a/lib/pages_desktop_specific/home/settings_menu/syncing_preferences_settings.dart b/lib/pages_desktop_specific/home/settings_menu/syncing_preferences_settings.dart new file mode 100644 index 000000000..9b6c6c85c --- /dev/null +++ b/lib/pages_desktop_specific/home/settings_menu/syncing_preferences_settings.dart @@ -0,0 +1,106 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/src/widgets/framework.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/widgets/rounded_white_container.dart'; + +class SyncingPreferencesSettings extends ConsumerStatefulWidget { + const SyncingPreferencesSettings({Key? key}) : super(key: key); + + static const String routeName = "/settingsMenuSyncingPref"; + + @override + ConsumerState createState() => + _SyncingPreferencesSettings(); +} + +class _SyncingPreferencesSettings + extends ConsumerState { + @override + Widget build(BuildContext context) { + debugPrint("BUILD: $runtimeType"); + return Column( + children: [ + Padding( + padding: const EdgeInsets.only( + right: 30, + ), + child: RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SvgPicture.asset( + Assets.svg.circleArrowRotate, + width: 48, + height: 48, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Padding( + padding: const EdgeInsets.all(10), + child: RichText( + textAlign: TextAlign.start, + text: TextSpan( + children: [ + TextSpan( + text: "Syncing Preferences", + style: STextStyles.desktopTextSmall(context), + ), + TextSpan( + text: + "\nSet up your syncing preferences for all wallets in your Stack.", + style: STextStyles.desktopTextExtraExtraSmall( + context), + ), + ], + ), + ), + ), + ], + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: const [ + Padding( + padding: EdgeInsets.all( + 10, + ), + child: ChangePrefButton(), + ), + ], + ), + ], + ), + ), + ), + ], + ); + } +} + +class ChangePrefButton extends ConsumerWidget { + const ChangePrefButton({ + Key? key, + }) : super(key: key); + @override + Widget build(BuildContext context, WidgetRef ref) { + return SizedBox( + width: 200, + height: 48, + child: TextButton( + style: Theme.of(context) + .extension()! + .getPrimaryEnabledButtonColor(context), + onPressed: () {}, + child: Text( + "Change preferences", + style: STextStyles.button(context), + ), + ), + ); + } +} diff --git a/lib/route_generator.dart b/lib/route_generator.dart index d318b85a6..f915e7837 100644 --- a/lib/route_generator.dart +++ b/lib/route_generator.dart @@ -86,7 +86,16 @@ import 'package:stackwallet/pages_desktop_specific/create_password/create_passwo import 'package:stackwallet/pages_desktop_specific/home/desktop_home_view.dart'; import 'package:stackwallet/pages_desktop_specific/home/desktop_settings_view.dart'; import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/my_stack_view.dart'; +import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart'; +import 'package:stackwallet/pages_desktop_specific/home/settings_menu/advanced_settings.dart'; +import 'package:stackwallet/pages_desktop_specific/home/settings_menu/appearance_settings.dart'; +import 'package:stackwallet/pages_desktop_specific/home/settings_menu/backup_and_restore_settings.dart'; +import 'package:stackwallet/pages_desktop_specific/home/settings_menu/currency_settings.dart'; +import 'package:stackwallet/pages_desktop_specific/home/settings_menu/language_settings.dart'; +import 'package:stackwallet/pages_desktop_specific/home/settings_menu/nodes_settings.dart'; +import 'package:stackwallet/pages_desktop_specific/home/settings_menu/security_settings.dart'; import 'package:stackwallet/pages_desktop_specific/home/settings_menu/settings_menu.dart'; +import 'package:stackwallet/pages_desktop_specific/home/settings_menu/syncing_preferences_settings.dart'; import 'package:stackwallet/services/coins/manager.dart'; import 'package:stackwallet/services/event_bus/events/global/node_connection_status_changed_event.dart'; import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart'; @@ -957,11 +966,11 @@ class RouteGenerator { builder: (_) => const DesktopHomeView(), settings: RouteSettings(name: settings.name)); - // case DesktopSettingsView.routeName: - // return getRoute( - // shouldUseMaterialRoute: useMaterialPageRoute, - // builder: (_) => const DesktopSettingsView(), - // settings: RouteSettings(name: settings.name)); + case DesktopSettingsView.routeName: + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: (_) => const DesktopSettingsView(), + settings: RouteSettings(name: settings.name)); case MyStackView.routeName: return getRoute( @@ -969,6 +978,20 @@ class RouteGenerator { builder: (_) => const MyStackView(), settings: RouteSettings(name: settings.name)); + case DesktopWalletView.routeName: + if (args is String) { + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: (_) => DesktopWalletView( + walletId: args, + ), + settings: RouteSettings( + name: settings.name, + ), + ); + } + return _routeError("${settings.name} invalid args: ${args.toString()}"); + case SettingsMenu.routeName: return getRoute( shouldUseMaterialRoute: useMaterialPageRoute, @@ -977,6 +1000,54 @@ class RouteGenerator { ), settings: RouteSettings(name: settings.name)); + case BackupRestoreSettings.routeName: + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: (_) => const BackupRestoreSettings(), + settings: RouteSettings(name: settings.name)); + + case SecuritySettings.routeName: + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: (_) => const SecuritySettings(), + settings: RouteSettings(name: settings.name)); + + case CurrencySettings.routeName: + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: (_) => const CurrencySettings(), + settings: RouteSettings(name: settings.name)); + + case LanguageOptionSettings.routeName: + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: (_) => const LanguageOptionSettings(), + settings: RouteSettings(name: settings.name)); + + case NodesSettings.routeName: + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: (_) => const NodesSettings(), + settings: RouteSettings(name: settings.name)); + + case SyncingPreferencesSettings.routeName: + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: (_) => const SyncingPreferencesSettings(), + settings: RouteSettings(name: settings.name)); + + case AppearanceOptionSettings.routeName: + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: (_) => const AppearanceOptionSettings(), + settings: RouteSettings(name: settings.name)); + + case AdvancedSettings.routeName: + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: (_) => const AdvancedSettings(), + settings: RouteSettings(name: settings.name)); + // == End of desktop specific routes ===================================== default: diff --git a/lib/utilities/assets.dart b/lib/utilities/assets.dart index 1410d6442..ebe2d9848 100644 --- a/lib/utilities/assets.dart +++ b/lib/utilities/assets.dart @@ -59,6 +59,15 @@ class _SVG { String txExchangeFailed(BuildContext context) => "assets/svg/${Theme.of(context).extension()!.themeType.name}/tx-exchange-icon-failed.svg"; + String get themeLight => "assets/svg/light/light-mode.svg"; + String get themeDark => "assets/svg/dark/dark-theme.svg"; + String get circleNode => "assets/svg/node-circle.svg"; + String get circleSun => "assets/svg/sun-circle.svg"; + String get circleArrowRotate => "assets/svg/rotate-circle.svg"; + String get circleLanguage => "assets/svg/language-circle.svg"; + String get circleDollarSign => "assets/svg/dollar-sign-circle.svg"; + String get circleLock => "assets/svg/lock-circle.svg"; + String get disableButton => "assets/svg/Button.svg"; String get polygon => "assets/svg/Polygon.svg"; String get personaIncognito => "assets/svg/persona-incognito-1.svg"; String get personaEasy => "assets/svg/persona-easy-1.svg"; @@ -130,6 +139,11 @@ class _SVG { String get anonymize => "assets/svg/tx-icon-anonymize.svg"; String get anonymizePending => "assets/svg/tx-icon-anonymize-pending.svg"; String get anonymizeFailed => "assets/svg/tx-icon-anonymize-failed.svg"; + String get addressBookDesktop => "assets/svg/address-book-desktop.svg"; + String get exchangeDesktop => "assets/svg/exchange-desktop.svg"; + String get aboutDesktop => "assets/svg/about-desktop.svg"; + String get walletDesktop => "assets/svg/wallet-desktop.svg"; + String get exitDesktop => "assets/svg/exit-desktop.svg"; String get ellipse1 => "assets/svg/Ellipse-43.svg"; String get ellipse2 => "assets/svg/Ellipse-42.svg"; diff --git a/lib/utilities/text_styles.dart b/lib/utilities/text_styles.dart index c3a6929fe..82e2ad349 100644 --- a/lib/utilities/text_styles.dart +++ b/lib/utilities/text_styles.dart @@ -679,6 +679,25 @@ class STextStyles { } } + static TextStyle desktopTextSmall(BuildContext context) { + switch (_theme(context).themeType) { + case ThemeType.light: + return GoogleFonts.inter( + color: _theme(context).textDark, + fontWeight: FontWeight.w500, + fontSize: 18, + height: 27 / 18, + ); + case ThemeType.dark: + return GoogleFonts.inter( + color: _theme(context).buttonTextPrimaryDisabled, + fontWeight: FontWeight.w500, + fontSize: 18, + height: 27 / 18, + ); + } + } + static TextStyle desktopTextExtraSmall(BuildContext context) { switch (_theme(context).themeType) { case ThemeType.light: diff --git a/lib/utilities/theme/stack_colors.dart b/lib/utilities/theme/stack_colors.dart index 0481268b5..67f1601f1 100644 --- a/lib/utilities/theme/stack_colors.dart +++ b/lib/utilities/theme/stack_colors.dart @@ -1519,5 +1519,8 @@ class StackColors extends ThemeExtension { backgroundColor: MaterialStateProperty.all( background, ), + overlayColor: MaterialStateProperty.all( + Colors.transparent, + ), ); } diff --git a/lib/utilities/util.dart b/lib/utilities/util.dart index 8a98787f2..5963bfee9 100644 --- a/lib/utilities/util.dart +++ b/lib/utilities/util.dart @@ -1,9 +1,14 @@ import 'dart:io'; import 'package:flutter/material.dart'; +import 'package:path_provider/path_provider.dart'; abstract class Util { + static Directory? libraryPath; static bool get isDesktop { + if(Platform.isIOS && libraryPath != null && !libraryPath!.path.contains("/var/mobile/")){ + return true; + } return Platform.isLinux || Platform.isMacOS || Platform.isWindows; } diff --git a/lib/widgets/wallet_info_row/wallet_info_row.dart b/lib/widgets/wallet_info_row/wallet_info_row.dart index 4840e9b01..d5e42e814 100644 --- a/lib/widgets/wallet_info_row/wallet_info_row.dart +++ b/lib/widgets/wallet_info_row/wallet_info_row.dart @@ -25,9 +25,13 @@ class WalletInfoRow extends ConsumerWidget { .watch(walletsChangeNotifierProvider.notifier) .getManagerProvider(walletId)); - return Row( - children: Util.isDesktop - ? [ + if (Util.isDesktop) { + return GestureDetector( + onTap: onPressed, + child: Container( + color: Colors.transparent, + child: Row( + children: [ Expanded( flex: 4, child: Row( @@ -38,11 +42,9 @@ class WalletInfoRow extends ConsumerWidget { ), Text( manager.walletName, - style: - STextStyles.desktopTextExtraSmall(context).copyWith( - color: Theme.of(context) - .extension()! - .textDark, + style: STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of(context).extension()!.textDark, ), ), ], @@ -70,29 +72,35 @@ class WalletInfoRow extends ConsumerWidget { ], ), ) - ] - : [ - WalletInfoCoinIcon(coin: manager.coin), - const SizedBox( - width: 12, - ), - Expanded( - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - manager.walletName, - style: STextStyles.titleBold12(context), - ), - const SizedBox( - height: 2, - ), - WalletInfoRowBalanceFuture(walletId: walletId), - ], - ), - ), ], - ); + ), + ), + ); + } else { + return Row( + children: [ + WalletInfoCoinIcon(coin: manager.coin), + const SizedBox( + width: 12, + ), + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + manager.walletName, + style: STextStyles.titleBold12(context), + ), + const SizedBox( + height: 2, + ), + WalletInfoRowBalanceFuture(walletId: walletId), + ], + ), + ), + ], + ); + } } } diff --git a/pubspec.lock b/pubspec.lock index 2a680284c..394d1ec8e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -42,7 +42,7 @@ packages: name: archive url: "https://pub.dartlang.org" source: hosted - version: "3.3.0" + version: "3.1.11" args: dependency: transitive description: @@ -63,7 +63,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.9.0" + version: "2.8.2" barcode_scan2: dependency: "direct main" description: @@ -190,7 +190,14 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.2.1" + version: "1.2.0" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.1" checked_yaml: dependency: transitive description: @@ -204,7 +211,7 @@ packages: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.1.1" + version: "1.1.0" code_builder: dependency: transitive description: @@ -274,7 +281,7 @@ packages: name: coverage url: "https://pub.dartlang.org" source: hosted - version: "1.5.0" + version: "1.2.0" cross_file: dependency: transitive description: @@ -428,7 +435,7 @@ packages: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.3.1" + version: "1.3.0" ffi: dependency: "direct main" description: @@ -543,7 +550,7 @@ packages: name: flutter_native_splash url: "https://pub.dartlang.org" source: hosted - version: "2.2.11" + version: "2.2.9" flutter_plugin_android_lifecycle: dependency: transitive description: @@ -816,6 +823,13 @@ packages: relative: true source: path version: "0.0.1" + lint: + dependency: transitive + description: + name: lint + url: "https://pub.dartlang.org" + source: hosted + version: "1.10.0" lints: dependency: transitive description: @@ -843,28 +857,28 @@ packages: name: lottie url: "https://pub.dartlang.org" source: hosted - version: "1.4.3" + version: "1.4.2" matcher: dependency: transitive description: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.12" + version: "0.12.11" material_color_utilities: dependency: transitive description: name: material_color_utilities url: "https://pub.dartlang.org" source: hosted - version: "0.1.5" + version: "0.1.4" meta: dependency: transitive description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.8.0" + version: "1.7.0" mime: dependency: transitive description: @@ -976,7 +990,7 @@ packages: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.8.2" + version: "1.8.1" path_drawing: dependency: transitive description: @@ -1352,7 +1366,7 @@ packages: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.9.0" + version: "1.8.2" stack_trace: dependency: transitive description: @@ -1410,42 +1424,42 @@ packages: name: sync_http url: "https://pub.dartlang.org" source: hosted - version: "0.3.1" + version: "0.3.0" term_glyph: dependency: transitive description: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.2.1" + version: "1.2.0" test: dependency: transitive description: name: test url: "https://pub.dartlang.org" source: hosted - version: "1.21.4" + version: "1.21.1" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.12" + version: "0.4.9" test_core: dependency: transitive description: name: test_core url: "https://pub.dartlang.org" source: hosted - version: "0.4.16" + version: "0.4.13" time: dependency: transitive description: name: time url: "https://pub.dartlang.org" source: hosted - version: "2.1.3" + version: "2.1.2" timezone: dependency: transitive description: @@ -1487,7 +1501,7 @@ packages: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.3.1" + version: "1.3.0" universal_io: dependency: transitive description: @@ -1571,7 +1585,7 @@ packages: name: vm_service url: "https://pub.dartlang.org" source: hosted - version: "9.0.0" + version: "8.2.2" wakelock: dependency: "direct main" description: @@ -1687,5 +1701,5 @@ packages: source: hosted version: "1.0.0" sdks: - dart: ">=2.18.0 <3.0.0" - flutter: ">=3.3.0" + dart: ">=2.17.5 <3.0.0" + flutter: ">=3.0.1" diff --git a/pubspec.yaml b/pubspec.yaml index 3858c5a70..42934fd5c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -294,6 +294,20 @@ flutter: - assets/svg/Polygon.svg - assets/svg/persona-easy-1.svg - assets/svg/persona-incognito-1.svg + - assets/svg/Button.svg + - assets/svg/lock-circle.svg + - assets/svg/dollar-sign-circle.svg + - assets/svg/language-circle.svg + - assets/svg/rotate-circle.svg + - assets/svg/sun-circle.svg + - assets/svg/node-circle.svg + - assets/svg/dark/dark-theme.svg + - assets/svg/light/light-mode.svg + - assets/svg/address-book-desktop.svg + - assets/svg/about-desktop.svg + - assets/svg/exchange-desktop.svg + - assets/svg/wallet-desktop.svg + - assets/svg/exit-desktop.svg # coin icons - assets/svg/coin_icons/Bitcoin.svg - assets/svg/coin_icons/Bitcoincash.svg