From 4797b083e27a7d76cef33ca1c7fcb589bb10fa9c Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 13 Apr 2023 08:53:17 -0600 Subject: [PATCH 1/8] mobile add tokens button fix --- .../edit_wallet_tokens_view.dart | 21 ++++++++++++++----- lib/pages/token_view/my_tokens_view.dart | 4 ++-- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/lib/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart b/lib/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart index 11f05c206..924202a52 100644 --- a/lib/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart +++ b/lib/pages/add_wallet_views/add_token_view/edit_wallet_tokens_view.dart @@ -134,9 +134,10 @@ class _EditWalletTokensViewState extends ConsumerState { ), ); } else { - contract = await Navigator.of(context).pushNamed( + final result = await Navigator.of(context).pushNamed( AddCustomTokenView.routeName, ); + contract = result as EthContract?; } if (contract != null) { @@ -442,16 +443,26 @@ class _EditWalletTokensViewState extends ConsumerState { }, ), actions: [ - AspectRatio( - aspectRatio: 1, - child: Padding( - padding: const EdgeInsets.all(8.0), + Padding( + padding: const EdgeInsets.only( + top: 10, + bottom: 10, + right: 20, + ), + child: AspectRatio( + aspectRatio: 1, child: AppBarIconButton( + size: 36, + shadows: const [], + color: + Theme.of(context).extension()!.background, icon: SvgPicture.asset( Assets.svg.circlePlusFilled, color: Theme.of(context) .extension()! .topNavIconPrimary, + width: 20, + height: 20, ), onPressed: _addToken, ), diff --git a/lib/pages/token_view/my_tokens_view.dart b/lib/pages/token_view/my_tokens_view.dart index 78fa352d0..b06f39741 100644 --- a/lib/pages/token_view/my_tokens_view.dart +++ b/lib/pages/token_view/my_tokens_view.dart @@ -100,10 +100,10 @@ class _MyTokensViewState extends ConsumerState { color: Theme.of(context).extension()!.background, icon: SvgPicture.asset( - Assets.svg.circlePlusDark, + Assets.svg.circlePlusFilled, color: Theme.of(context) .extension()! - .accentColorDark, + .topNavIconPrimary, width: 20, height: 20, ), From 5267d5f94990e7d879d77410ec79494b387107f1 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 13 Apr 2023 09:03:04 -0600 Subject: [PATCH 2/8] mobile eth fee selection sheet fix --- .../transaction_fee_selection_sheet.dart | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart b/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart index cba5f779f..7b6b1d5e2 100644 --- a/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart +++ b/lib/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart @@ -358,13 +358,15 @@ class _TransactionFeeSelectionSheetState const SizedBox( height: 2, ), - if (feeObject == null) + if (feeObject == null && + manager.coin != Coin.ethereum) AnimatedText( stringsToLoopThrough: stringsToLoopThrough, style: STextStyles.itemSubtitle(context), ), - if (feeObject != null) + if (feeObject != null && + manager.coin != Coin.ethereum) Text( estimatedTimeToBeIncludedInNextBlock( Constants.targetBlockTimeInSeconds( @@ -490,13 +492,15 @@ class _TransactionFeeSelectionSheetState const SizedBox( height: 2, ), - if (feeObject == null) + if (feeObject == null && + manager.coin != Coin.ethereum) AnimatedText( stringsToLoopThrough: stringsToLoopThrough, style: STextStyles.itemSubtitle(context), ), - if (feeObject != null) + if (feeObject != null && + manager.coin != Coin.ethereum) Text( estimatedTimeToBeIncludedInNextBlock( Constants.targetBlockTimeInSeconds( @@ -622,13 +626,15 @@ class _TransactionFeeSelectionSheetState const SizedBox( height: 2, ), - if (feeObject == null) + if (feeObject == null && + manager.coin != Coin.ethereum) AnimatedText( stringsToLoopThrough: stringsToLoopThrough, style: STextStyles.itemSubtitle(context), ), - if (feeObject != null) + if (feeObject != null && + manager.coin != Coin.ethereum) Text( estimatedTimeToBeIncludedInNextBlock( Constants.targetBlockTimeInSeconds( From 49b6e65ffeaac6cc7a297746bfd7f230a9b8a2ee Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 13 Apr 2023 09:17:05 -0600 Subject: [PATCH 3/8] remove a couple default tokens --- lib/utilities/default_eth_tokens.dart | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/lib/utilities/default_eth_tokens.dart b/lib/utilities/default_eth_tokens.dart index a13a890f5..eb04118bc 100644 --- a/lib/utilities/default_eth_tokens.dart +++ b/lib/utilities/default_eth_tokens.dart @@ -23,20 +23,6 @@ abstract class DefaultTokens { decimals: 18, type: EthContractType.erc20, ), - EthContract( - address: "0xB8c77482e45F1F44dE1745F52C74426C631bDD52", - name: "BNB Token", - symbol: "BNB", - decimals: 18, - type: EthContractType.erc20, - ), - EthContract( - address: "0x4Fabb145d64652a948d72533023f6E7A623C7C53", - name: "BUSD", - symbol: "BUSD", - decimals: 18, - type: EthContractType.erc20, - ), EthContract( address: "0x514910771af9ca656af840dff83e8264ecf986ca", name: "Chainlink", From 07f25cc9ffb3f689658190a2f62d3465034dab10 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 13 Apr 2023 09:21:27 -0600 Subject: [PATCH 4/8] token send form state fixes --- .../sub_widgets/desktop_fee_dropdown.dart | 50 +++++++++++++++---- .../sub_widgets/desktop_token_send.dart | 35 +++++++------ .../ui/preview_tx_button_state_provider.dart | 11 ++-- 3 files changed, 64 insertions(+), 32 deletions(-) diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_fee_dropdown.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_fee_dropdown.dart index fc049e093..557d4549c 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_fee_dropdown.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_fee_dropdown.dart @@ -19,6 +19,11 @@ import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/widgets/animated_text.dart'; +final tokenFeeSessionCacheProvider = + ChangeNotifierProvider((ref) { + return FeeSheetSessionCache(); +}); + class DesktopFeeDropDown extends ConsumerStatefulWidget { const DesktopFeeDropDown({ Key? key, @@ -54,7 +59,12 @@ class _DesktopFeeDropDownState extends ConsumerState { }) async { switch (feeRateType) { case FeeRateType.fast: - if (ref.read(feeSheetSessionCacheProvider).fast[amount] == null) { + if (ref + .read(widget.isToken + ? tokenFeeSessionCacheProvider + : feeSheetSessionCacheProvider) + .fast[amount] == + null) { if (widget.isToken == false) { final manager = ref.read(walletsChangeNotifierProvider).getManager(walletId); @@ -76,13 +86,22 @@ class _DesktopFeeDropDownState extends ConsumerState { } else { final tokenWallet = ref.read(tokenServiceProvider)!; final fee = tokenWallet.estimateFeeFor(feeRate); - ref.read(feeSheetSessionCacheProvider).fast[amount] = fee; + ref.read(tokenFeeSessionCacheProvider).fast[amount] = fee; } } - return ref.read(feeSheetSessionCacheProvider).fast[amount]!; + return ref + .read(widget.isToken + ? tokenFeeSessionCacheProvider + : feeSheetSessionCacheProvider) + .fast[amount]!; case FeeRateType.average: - if (ref.read(feeSheetSessionCacheProvider).average[amount] == null) { + if (ref + .read(widget.isToken + ? tokenFeeSessionCacheProvider + : feeSheetSessionCacheProvider) + .average[amount] == + null) { if (widget.isToken == false) { final manager = ref.read(walletsChangeNotifierProvider).getManager(walletId); @@ -104,13 +123,22 @@ class _DesktopFeeDropDownState extends ConsumerState { } else { final tokenWallet = ref.read(tokenServiceProvider)!; final fee = tokenWallet.estimateFeeFor(feeRate); - ref.read(feeSheetSessionCacheProvider).average[amount] = fee; + ref.read(tokenFeeSessionCacheProvider).average[amount] = fee; } } - return ref.read(feeSheetSessionCacheProvider).average[amount]!; + return ref + .read(widget.isToken + ? tokenFeeSessionCacheProvider + : feeSheetSessionCacheProvider) + .average[amount]!; case FeeRateType.slow: - if (ref.read(feeSheetSessionCacheProvider).slow[amount] == null) { + if (ref + .read(widget.isToken + ? tokenFeeSessionCacheProvider + : feeSheetSessionCacheProvider) + .slow[amount] == + null) { if (widget.isToken == false) { final manager = ref.read(walletsChangeNotifierProvider).getManager(walletId); @@ -132,10 +160,14 @@ class _DesktopFeeDropDownState extends ConsumerState { } else { final tokenWallet = ref.read(tokenServiceProvider)!; final fee = tokenWallet.estimateFeeFor(feeRate); - ref.read(feeSheetSessionCacheProvider).slow[amount] = fee; + ref.read(tokenFeeSessionCacheProvider).slow[amount] = fee; } } - return ref.read(feeSheetSessionCacheProvider).slow[amount]!; + return ref + .read(widget.isToken + ? tokenFeeSessionCacheProvider + : feeSheetSessionCacheProvider) + .slow[amount]!; } } diff --git a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart index e418c4283..127798d4a 100644 --- a/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart +++ b/lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_token_send.dart @@ -9,7 +9,6 @@ import 'package:stackwallet/models/paynym/paynym_account_lite.dart'; import 'package:stackwallet/models/send_view_auto_fill_data.dart'; import 'package:stackwallet/pages/send_view/confirm_transaction_view.dart'; import 'package:stackwallet/pages/send_view/sub_widgets/building_transaction_dialog.dart'; -import 'package:stackwallet/pages/send_view/sub_widgets/transaction_fee_selection_sheet.dart'; import 'package:stackwallet/pages/token_view/token_view.dart'; import 'package:stackwallet/pages_desktop_specific/desktop_home_view.dart'; import 'package:stackwallet/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/address_book_address_chooser.dart'; @@ -416,7 +415,7 @@ class _DesktopTokenSendState extends ConsumerState { .read(walletsChangeNotifierProvider) .getManager(walletId) .validateAddress(address ?? ""); - ref.read(previewTxButtonStateProvider.state).state = + ref.read(previewTokenTxButtonStateProvider.state).state = (isValidAddress && amount != null && amount > Amount.zero); } @@ -574,8 +573,8 @@ class _DesktopTokenSendState extends ConsumerState { @override void initState() { WidgetsBinding.instance.addPostFrameCallback((_) { - ref.refresh(feeSheetSessionCacheProvider); - ref.read(previewTxButtonStateProvider.state).state = false; + ref.refresh(tokenFeeSessionCacheProvider); + ref.read(previewTokenTxButtonStateProvider.state).state = false; }); // _calculateFeesFuture = calculateFees(0); @@ -605,21 +604,25 @@ class _DesktopTokenSendState extends ConsumerState { _cryptoFocus.addListener(() { if (!_cryptoFocus.hasFocus && !_baseFocus.hasFocus) { - if (_amountToSend == null) { - ref.refresh(sendAmountProvider); - } else { - ref.read(sendAmountProvider.state).state = _amountToSend!; - } + WidgetsBinding.instance.addPostFrameCallback((_) { + if (_amountToSend == null) { + ref.refresh(sendAmountProvider); + } else { + ref.read(sendAmountProvider.state).state = _amountToSend!; + } + }); } }); _baseFocus.addListener(() { if (!_cryptoFocus.hasFocus && !_baseFocus.hasFocus) { - if (_amountToSend == null) { - ref.refresh(sendAmountProvider); - } else { - ref.read(sendAmountProvider.state).state = _amountToSend!; - } + WidgetsBinding.instance.addPostFrameCallback((_) { + if (_amountToSend == null) { + ref.refresh(sendAmountProvider); + } else { + ref.read(sendAmountProvider.state).state = _amountToSend!; + } + }); } }); @@ -1064,8 +1067,8 @@ class _DesktopTokenSendState extends ConsumerState { PrimaryButton( buttonHeight: ButtonHeight.l, label: "Preview send", - enabled: ref.watch(previewTxButtonStateProvider.state).state, - onPressed: ref.watch(previewTxButtonStateProvider.state).state + enabled: ref.watch(previewTokenTxButtonStateProvider.state).state, + onPressed: ref.watch(previewTokenTxButtonStateProvider.state).state ? previewSend : null, ) diff --git a/lib/providers/ui/preview_tx_button_state_provider.dart b/lib/providers/ui/preview_tx_button_state_provider.dart index 740356a20..68d4fc531 100644 --- a/lib/providers/ui/preview_tx_button_state_provider.dart +++ b/lib/providers/ui/preview_tx_button_state_provider.dart @@ -1,12 +1,9 @@ -import 'package:flutter/foundation.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -int _count = 0; - final previewTxButtonStateProvider = StateProvider.autoDispose((_) { - if (kDebugMode) { - _count++; - } - + return false; +}); + +final previewTokenTxButtonStateProvider = StateProvider.autoDispose((_) { return false; }); From 362c70822594983c56defe5a6582694bf0cc3bfc Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 13 Apr 2023 10:32:57 -0600 Subject: [PATCH 5/8] WIP wallet state management improvements --- lib/providers/wallet_provider.dart | 60 ++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 lib/providers/wallet_provider.dart diff --git a/lib/providers/wallet_provider.dart b/lib/providers/wallet_provider.dart new file mode 100644 index 000000000..15c7952b6 --- /dev/null +++ b/lib/providers/wallet_provider.dart @@ -0,0 +1,60 @@ +import 'package:equatable/equatable.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:stackwallet/providers/db/main_db_provider.dart'; +import 'package:stackwallet/providers/global/secure_store_provider.dart'; +import 'package:stackwallet/services/coins/ethereum/ethereum_wallet.dart'; +import 'package:stackwallet/services/coins/manager.dart'; +import 'package:stackwallet/services/ethereum/ethereum_token_service.dart'; +import 'package:stackwallet/services/transaction_notification_tracker.dart'; +import 'package:stackwallet/utilities/logger.dart'; + +class ContractWalletId implements Equatable { + final String walletId; + final String tokenContractAddress; + + ContractWalletId({ + required this.walletId, + required this.tokenContractAddress, + }); + + @override + List get props => [walletId, tokenContractAddress]; + + @override + bool? get stringify => true; +} + +/// provide the wallet for a given wallet id +final walletProvider = + ChangeNotifierProvider.family((ref, arg) => null); + +/// provide the token wallet given a contract address and eth wallet id +final tokenWalletProvider = + ChangeNotifierProvider.family( + (ref, arg) { + final ethWallet = + ref.watch(walletProvider(arg.walletId).select((value) => value?.wallet)) + as EthereumWallet?; + final contract = + ref.read(mainDBProvider).getEthContractSync(arg.tokenContractAddress); + + if (ethWallet == null || contract == null) { + Logging.instance.log( + "Attempted to access a token wallet with walletId=${arg.walletId} where" + " contractAddress=${arg.tokenContractAddress}", + level: LogLevel.Warning, + ); + return null; + } + + final secureStore = ref.watch(secureStoreProvider); + + return EthTokenWallet( + token: contract, + ethWallet: ethWallet, + secureStore: secureStore, + tracker: TransactionNotificationTracker( + walletId: arg.walletId, + ), + ); +}); From 9a23e311fd082c7a0ff479421e6c4c7b3327d48d Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 13 Apr 2023 13:04:08 -0600 Subject: [PATCH 6/8] WIP appearance settings code organisation --- .../appearance_settings_view.dart | 232 +----------------- .../sub_widgets/theme_option.dart | 70 ++++++ .../sub_widgets/theme_options_widget.dart | 50 ++++ ...ystem_brightness_theme_selection_view.dart | 130 ++++++++++ .../global_settings_view.dart | 2 +- lib/route_generator.dart | 3 +- 6 files changed, 256 insertions(+), 231 deletions(-) rename lib/pages/settings_views/global_settings_view/{ => appearance_settings}/appearance_settings_view.dart (64%) create mode 100644 lib/pages/settings_views/global_settings_view/appearance_settings/sub_widgets/theme_option.dart create mode 100644 lib/pages/settings_views/global_settings_view/appearance_settings/sub_widgets/theme_options_widget.dart create mode 100644 lib/pages/settings_views/global_settings_view/appearance_settings/system_brightness_theme_selection_view.dart diff --git a/lib/pages/settings_views/global_settings_view/appearance_settings_view.dart b/lib/pages/settings_views/global_settings_view/appearance_settings/appearance_settings_view.dart similarity index 64% rename from lib/pages/settings_views/global_settings_view/appearance_settings_view.dart rename to lib/pages/settings_views/global_settings_view/appearance_settings/appearance_settings_view.dart index 981ddc69c..3cc7edae5 100644 --- a/lib/pages/settings_views/global_settings_view/appearance_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/appearance_settings/appearance_settings_view.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings/sub_widgets/theme_options_widget.dart'; +import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings/system_brightness_theme_selection_view.dart'; import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/providers/ui/color_theme_provider.dart'; import 'package:stackwallet/utilities/assets.dart'; @@ -145,7 +147,7 @@ class AppearanceSettingsView extends ConsumerWidget { ), const Padding( padding: EdgeInsets.all(10), - child: ThemeOptionsView(), + child: ThemeOptionsWidget(), ), ], ), @@ -398,231 +400,3 @@ class _SystemBrightnessToggleState ); } } - -class ThemeOptionsView extends ConsumerWidget { - const ThemeOptionsView({Key? key}) : super(key: key); - - @override - Widget build(BuildContext context, WidgetRef ref) { - return Column( - children: [ - for (int i = 0; i < (2 * ThemeType.values.length) - 1; i++) - (i % 2 == 1) - ? const SizedBox( - height: 10, - ) - : ThemeOption( - onPressed: () { - ref.read(prefsChangeNotifierProvider.notifier).theme = - ThemeType.values[i ~/ 2]; - ref.read(colorThemeProvider.notifier).state = - StackColors.fromStackColorTheme( - ThemeType.values[i ~/ 2].colorTheme, - ); - Assets.precache(context); - }, - onChanged: (newValue) { - if (newValue == ThemeType.values[i ~/ 2]) { - ref.read(prefsChangeNotifierProvider.notifier).theme = - ThemeType.values[i ~/ 2]; - ref.read(colorThemeProvider.notifier).state = - StackColors.fromStackColorTheme( - ThemeType.values[i ~/ 2].colorTheme, - ); - Assets.precache(context); - } - }, - value: ThemeType.values[i ~/ 2], - groupValue: - Theme.of(context).extension()!.themeType, - ), - ], - ); - } -} - -class ThemeOption extends StatelessWidget { - const ThemeOption( - {Key? key, - required this.onPressed, - required this.onChanged, - required this.value, - required this.groupValue}) - : super(key: key); - - final VoidCallback onPressed; - final void Function(Object?) onChanged; - final ThemeType value; - final ThemeType groupValue; - - @override - Widget build(BuildContext context) { - return MaterialButton( - splashColor: Colors.transparent, - hoverColor: Colors.transparent, - padding: const EdgeInsets.all(0), - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: onPressed, - child: SizedBox( - width: 200, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Row( - children: [ - SizedBox( - width: 10, - height: 10, - child: Radio( - activeColor: Theme.of(context) - .extension()! - .radioButtonIconEnabled, - value: value, - groupValue: groupValue, - onChanged: onChanged, - ), - ), - const SizedBox( - width: 14, - ), - Text( - value.prettyName, - style: STextStyles.desktopTextExtraSmall(context).copyWith( - color: - Theme.of(context).extension()!.textDark2, - ), - ), - ], - ), - ], - ), - ), - ); - } -} - -class SystemBrightnessThemeSelectionView extends StatelessWidget { - const SystemBrightnessThemeSelectionView({ - Key? key, - required this.brightness, - required this.current, - }) : super(key: key); - - final String brightness; - final ThemeType current; - - static const String routeName = "/chooseSystemTheme"; - - @override - Widget build(BuildContext context) { - return Background( - child: Scaffold( - backgroundColor: Theme.of(context).extension()!.background, - appBar: AppBar( - leading: AppBarBackButton( - onPressed: () async { - Navigator.of(context).pop(); - }, - ), - title: Text( - "Choose $brightness theme", - style: STextStyles.navBarTitle(context), - ), - ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - padding: const EdgeInsets.all(0), - materialTapTargetSize: - MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: null, - child: Padding( - padding: const EdgeInsets.all(12), - child: Row( - children: [ - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.all(10), - child: Column( - children: [ - for (int i = 0; - i < - (2 * - ThemeType.values - .length) - - 1; - i++) - (i % 2 == 1) - ? const SizedBox( - height: 10, - ) - : ThemeOption( - onPressed: () { - Navigator.of(context) - .pop(ThemeType - .values[ - i ~/ 2]); - }, - onChanged: (newValue) { - if (newValue == - ThemeType.values[ - i ~/ 2]) { - Navigator.of(context) - .pop(ThemeType - .values[ - i ~/ 2]); - } - }, - value: ThemeType - .values[i ~/ 2], - groupValue: current, - ), - ], - ), - ), - ], - ), - ], - ), - ), - ), - ), - ], - ), - ), - ), - ); - }, - ), - ), - ), - ); - } -} diff --git a/lib/pages/settings_views/global_settings_view/appearance_settings/sub_widgets/theme_option.dart b/lib/pages/settings_views/global_settings_view/appearance_settings/sub_widgets/theme_option.dart new file mode 100644 index 000000000..0d3a22b64 --- /dev/null +++ b/lib/pages/settings_views/global_settings_view/appearance_settings/sub_widgets/theme_option.dart @@ -0,0 +1,70 @@ +import 'package:flutter/material.dart'; +import 'package:stackwallet/utilities/constants.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/theme/color_theme.dart'; +import 'package:stackwallet/utilities/theme/stack_colors.dart'; + +class ThemeOption extends StatelessWidget { + const ThemeOption( + {Key? key, + required this.onPressed, + required this.onChanged, + required this.value, + required this.groupValue}) + : super(key: key); + + final VoidCallback onPressed; + final void Function(Object?) onChanged; + final ThemeType value; + final ThemeType groupValue; + + @override + Widget build(BuildContext context) { + return MaterialButton( + splashColor: Colors.transparent, + hoverColor: Colors.transparent, + padding: const EdgeInsets.all(0), + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: onPressed, + child: SizedBox( + width: 200, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + children: [ + SizedBox( + width: 10, + height: 10, + child: Radio( + activeColor: Theme.of(context) + .extension()! + .radioButtonIconEnabled, + value: value, + groupValue: groupValue, + onChanged: onChanged, + ), + ), + const SizedBox( + width: 14, + ), + Text( + value.prettyName, + style: STextStyles.desktopTextExtraSmall(context).copyWith( + color: + Theme.of(context).extension()!.textDark2, + ), + ), + ], + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/settings_views/global_settings_view/appearance_settings/sub_widgets/theme_options_widget.dart b/lib/pages/settings_views/global_settings_view/appearance_settings/sub_widgets/theme_options_widget.dart new file mode 100644 index 000000000..4ad84c68f --- /dev/null +++ b/lib/pages/settings_views/global_settings_view/appearance_settings/sub_widgets/theme_options_widget.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings/sub_widgets/theme_option.dart'; +import 'package:stackwallet/providers/providers.dart'; +import 'package:stackwallet/providers/ui/color_theme_provider.dart'; +import 'package:stackwallet/utilities/assets.dart'; +import 'package:stackwallet/utilities/theme/color_theme.dart'; +import 'package:stackwallet/utilities/theme/stack_colors.dart'; + +class ThemeOptionsWidget extends ConsumerWidget { + const ThemeOptionsWidget({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context, WidgetRef ref) { + return Column( + children: [ + for (int i = 0; i < (2 * ThemeType.values.length) - 1; i++) + (i % 2 == 1) + ? const SizedBox( + height: 10, + ) + : ThemeOption( + onPressed: () { + ref.read(prefsChangeNotifierProvider.notifier).theme = + ThemeType.values[i ~/ 2]; + ref.read(colorThemeProvider.notifier).state = + StackColors.fromStackColorTheme( + ThemeType.values[i ~/ 2].colorTheme, + ); + Assets.precache(context); + }, + onChanged: (newValue) { + if (newValue == ThemeType.values[i ~/ 2]) { + ref.read(prefsChangeNotifierProvider.notifier).theme = + ThemeType.values[i ~/ 2]; + ref.read(colorThemeProvider.notifier).state = + StackColors.fromStackColorTheme( + ThemeType.values[i ~/ 2].colorTheme, + ); + Assets.precache(context); + } + }, + value: ThemeType.values[i ~/ 2], + groupValue: + Theme.of(context).extension()!.themeType, + ), + ], + ); + } +} diff --git a/lib/pages/settings_views/global_settings_view/appearance_settings/system_brightness_theme_selection_view.dart b/lib/pages/settings_views/global_settings_view/appearance_settings/system_brightness_theme_selection_view.dart new file mode 100644 index 000000000..676d52139 --- /dev/null +++ b/lib/pages/settings_views/global_settings_view/appearance_settings/system_brightness_theme_selection_view.dart @@ -0,0 +1,130 @@ +import 'package:flutter/material.dart'; +import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings/sub_widgets/theme_option.dart'; +import 'package:stackwallet/utilities/constants.dart'; +import 'package:stackwallet/utilities/text_styles.dart'; +import 'package:stackwallet/utilities/theme/color_theme.dart'; +import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/widgets/background.dart'; +import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; +import 'package:stackwallet/widgets/rounded_white_container.dart'; + +class SystemBrightnessThemeSelectionView extends StatelessWidget { + const SystemBrightnessThemeSelectionView({ + Key? key, + required this.brightness, + required this.current, + }) : super(key: key); + + final String brightness; + final ThemeType current; + + static const String routeName = "/chooseSystemTheme"; + + @override + Widget build(BuildContext context) { + return Background( + child: Scaffold( + backgroundColor: Theme.of(context).extension()!.background, + appBar: AppBar( + leading: AppBarBackButton( + onPressed: () async { + Navigator.of(context).pop(); + }, + ), + title: Text( + "Choose $brightness theme", + style: STextStyles.navBarTitle(context), + ), + ), + body: Padding( + padding: const EdgeInsets.all(16), + child: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, + padding: const EdgeInsets.all(0), + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: null, + child: Padding( + padding: const EdgeInsets.all(12), + child: Row( + children: [ + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.all(10), + child: Column( + children: [ + for (int i = 0; + i < + (2 * + ThemeType.values + .length) - + 1; + i++) + (i % 2 == 1) + ? const SizedBox( + height: 10, + ) + : ThemeOption( + onPressed: () { + Navigator.of(context) + .pop(ThemeType + .values[ + i ~/ 2]); + }, + onChanged: (newValue) { + if (newValue == + ThemeType.values[ + i ~/ 2]) { + Navigator.of(context) + .pop(ThemeType + .values[ + i ~/ 2]); + } + }, + value: ThemeType + .values[i ~/ 2], + groupValue: current, + ), + ], + ), + ), + ], + ), + ], + ), + ), + ), + ), + ], + ), + ), + ), + ); + }, + ), + ), + ), + ); + } +} diff --git a/lib/pages/settings_views/global_settings_view/global_settings_view.dart b/lib/pages/settings_views/global_settings_view/global_settings_view.dart index 49e7ea36c..627961bed 100644 --- a/lib/pages/settings_views/global_settings_view/global_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/global_settings_view.dart @@ -5,7 +5,7 @@ import 'package:stackwallet/pages/address_book_views/address_book_view.dart'; import 'package:stackwallet/pages/pinpad_views/lock_screen_view.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/about_view.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/advanced_views/advanced_settings_view.dart'; -import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings_view.dart'; +import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings/appearance_settings_view.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/currency_view.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/delete_account_view.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/language_view.dart'; diff --git a/lib/route_generator.dart b/lib/route_generator.dart index 41043f3bb..55fbe92a9 100644 --- a/lib/route_generator.dart +++ b/lib/route_generator.dart @@ -63,7 +63,8 @@ import 'package:stackwallet/pages/send_view/token_send_view.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/about_view.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/advanced_views/advanced_settings_view.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/advanced_views/debug_view.dart'; -import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings_view.dart'; +import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings/appearance_settings_view.dart'; +import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings/system_brightness_theme_selection_view.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/currency_view.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/delete_account_view.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/global_settings_view.dart'; From 9ab156562aa39aba39ada86a28ebfb4ce420865c Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 13 Apr 2023 14:40:48 -0600 Subject: [PATCH 7/8] system brightness theme selection gui updates --- .../appearance_settings_view.dart | 317 ++---------------- .../sub_widgets/theme_option.dart | 31 +- .../sub_widgets/theme_options_widget.dart | 212 ++++++++++-- ...ystem_brightness_theme_selection_view.dart | 258 +++++++++----- lib/route_generator.dart | 21 +- 5 files changed, 408 insertions(+), 431 deletions(-) diff --git a/lib/pages/settings_views/global_settings_view/appearance_settings/appearance_settings_view.dart b/lib/pages/settings_views/global_settings_view/appearance_settings/appearance_settings_view.dart index 3cc7edae5..62c93a7b2 100644 --- a/lib/pages/settings_views/global_settings_view/appearance_settings/appearance_settings_view.dart +++ b/lib/pages/settings_views/global_settings_view/appearance_settings/appearance_settings_view.dart @@ -1,22 +1,14 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:flutter_svg/flutter_svg.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings/sub_widgets/theme_options_widget.dart'; -import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings/system_brightness_theme_selection_view.dart'; import 'package:stackwallet/providers/providers.dart'; -import 'package:stackwallet/providers/ui/color_theme_provider.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/color_theme.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/widgets/background.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; import 'package:stackwallet/widgets/custom_buttons/draggable_switch_button.dart'; -import 'package:stackwallet/widgets/expandable.dart'; -import 'package:stackwallet/widgets/rounded_container.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; -import 'package:tuple/tuple.dart'; class AppearanceSettingsView extends ConsumerWidget { const AppearanceSettingsView({Key? key}) : super(key: key); @@ -106,56 +98,43 @@ class AppearanceSettingsView extends ConsumerWidget { const SizedBox( height: 10, ), - const SystemBrightnessToggle(), - if (!ref.watch( - prefsChangeNotifierProvider - .select((value) => value.enableSystemBrightness), - )) - const SizedBox( - height: 10, - ), - if (!ref.watch( - prefsChangeNotifierProvider - .select((value) => value.enableSystemBrightness), - )) - RoundedWhiteContainer( + RoundedWhiteContainer( + padding: const EdgeInsets.all(0), + child: RawMaterialButton( + // splashColor: Theme.of(context).extension()!.highlight, padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - padding: const EdgeInsets.all(0), - materialTapTargetSize: - MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), + materialTapTargetSize: + MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, ), - onPressed: null, - child: Padding( - padding: const EdgeInsets.all(12), - child: Row( - children: [ - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Text( - "Choose Theme", - style: - STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - const Padding( - padding: EdgeInsets.all(10), - child: ThemeOptionsWidget(), - ), - ], - ), - ], - ), + ), + onPressed: null, + child: Padding( + padding: const EdgeInsets.all(12), + child: Row( + children: [ + Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + Text( + "Choose Theme", + style: STextStyles.titleBold12(context), + textAlign: TextAlign.left, + ), + const Padding( + padding: EdgeInsets.all(10), + child: ThemeOptionsWidget(), + ), + ], + ), + ], ), ), ), + ), ], ), ), @@ -168,235 +147,3 @@ class AppearanceSettingsView extends ConsumerWidget { ); } } - -class SystemBrightnessToggle extends ConsumerStatefulWidget { - const SystemBrightnessToggle({Key? key}) : super(key: key); - - @override - ConsumerState createState() => - _SystemBrightnessToggleState(); -} - -class _SystemBrightnessToggleState - extends ConsumerState { - final controller = ExpandableController(); - - void _toggle(bool enable) { - ref.read(prefsChangeNotifierProvider).enableSystemBrightness = enable; - - if (enable && controller.state == ExpandableState.collapsed) { - controller.toggle?.call(); - } else if (!enable && controller.state == ExpandableState.expanded) { - controller.toggle?.call(); - } - - if (enable) { - final ThemeType type; - switch (MediaQuery.of(context).platformBrightness) { - case Brightness.dark: - type = ref - .read(prefsChangeNotifierProvider.notifier) - .systemBrightnessDarkTheme; - break; - case Brightness.light: - type = ref - .read(prefsChangeNotifierProvider.notifier) - .systemBrightnessLightTheme; - break; - } - ref.read(colorThemeProvider.notifier).state = - StackColors.fromStackColorTheme( - type.colorTheme, - ); - } else { - ref.read(prefsChangeNotifierProvider.notifier).theme = - ref.read(colorThemeProvider.notifier).state.themeType; - } - } - - @override - void initState() { - if (ref.read(prefsChangeNotifierProvider).enableSystemBrightness) { - WidgetsBinding.instance.addPostFrameCallback((_) { - controller.toggle?.call(); - }); - } - super.initState(); - } - - @override - Widget build(BuildContext context) { - final enable = ref.watch( - prefsChangeNotifierProvider - .select((value) => value.enableSystemBrightness), - ); - - return RoundedWhiteContainer( - child: Expandable( - controller: controller, - expandOverride: () { - _toggle( - !ref.read(prefsChangeNotifierProvider).enableSystemBrightness); - }, - header: RawMaterialButton( - splashColor: Theme.of(context).extension()!.highlight, - materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: null, - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 8), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "System brightness", - style: STextStyles.titleBold12(context), - textAlign: TextAlign.left, - ), - SizedBox( - key: Key("${enable}enableSystemBrightnessToggleKey"), - height: 20, - width: 40, - child: DraggableSwitchButton( - isOn: enable, - onValueChanged: _toggle, - ), - ) - ], - ), - ), - ), - body: Column( - children: [ - RoundedContainer( - color: Colors.transparent, - padding: EdgeInsets.zero, - onPressed: () async { - final result = await Navigator.of(context).pushNamed( - SystemBrightnessThemeSelectionView.routeName, - arguments: Tuple2( - "light", - ref - .read(prefsChangeNotifierProvider) - .systemBrightnessLightTheme), - ); - if (result is ThemeType) { - ref - .read(prefsChangeNotifierProvider) - .systemBrightnessLightTheme = result; - if (ref - .read(prefsChangeNotifierProvider) - .enableSystemBrightness) { - if (mounted && - MediaQuery.of(context).platformBrightness == - Brightness.light) { - ref.read(colorThemeProvider.notifier).state = - StackColors.fromStackColorTheme(result.colorTheme); - } - } - } - }, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Light theme", - style: STextStyles.itemSubtitle(context), - ), - const SizedBox( - height: 2, - ), - Text( - ref - .watch( - prefsChangeNotifierProvider.select((value) => - value.systemBrightnessLightTheme), - ) - .prettyName, - style: STextStyles.itemSubtitle12(context), - ), - ], - ), - ), - SvgPicture.asset( - Assets.svg.chevronRight, - color: Theme.of(context).extension()!.textDark, - ), - ], - ), - ), - RoundedContainer( - color: Colors.transparent, - padding: EdgeInsets.zero, - onPressed: () async { - final result = await Navigator.of(context).pushNamed( - SystemBrightnessThemeSelectionView.routeName, - arguments: Tuple2( - "dark", - ref - .read(prefsChangeNotifierProvider) - .systemBrightnessDarkTheme), - ); - if (result is ThemeType) { - ref - .read(prefsChangeNotifierProvider) - .systemBrightnessDarkTheme = result; - if (ref - .read(prefsChangeNotifierProvider) - .enableSystemBrightness) { - if (mounted && - MediaQuery.of(context).platformBrightness == - Brightness.dark) { - ref.read(colorThemeProvider.notifier).state = - StackColors.fromStackColorTheme(result.colorTheme); - } - } - } - }, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - "Dark theme", - style: STextStyles.itemSubtitle(context), - ), - const SizedBox( - height: 2, - ), - Text( - ref.watch( - prefsChangeNotifierProvider.select((value) => - value.systemBrightnessDarkTheme.prettyName), - ), - style: STextStyles.itemSubtitle12(context), - ), - ], - ), - ), - SvgPicture.asset( - Assets.svg.chevronRight, - color: Theme.of(context).extension()!.textDark, - ), - ], - ), - ) - ], - ), - ), - ); - } -} diff --git a/lib/pages/settings_views/global_settings_view/appearance_settings/sub_widgets/theme_option.dart b/lib/pages/settings_views/global_settings_view/appearance_settings/sub_widgets/theme_option.dart index 0d3a22b64..ec89b012c 100644 --- a/lib/pages/settings_views/global_settings_view/appearance_settings/sub_widgets/theme_option.dart +++ b/lib/pages/settings_views/global_settings_view/appearance_settings/sub_widgets/theme_option.dart @@ -1,22 +1,23 @@ import 'package:flutter/material.dart'; import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/text_styles.dart'; -import 'package:stackwallet/utilities/theme/color_theme.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; -class ThemeOption extends StatelessWidget { - const ThemeOption( - {Key? key, - required this.onPressed, - required this.onChanged, - required this.value, - required this.groupValue}) - : super(key: key); +class ThemeOption extends StatelessWidget { + const ThemeOption({ + Key? key, + required this.onPressed, + required this.onChanged, + required this.label, + required this.value, + required this.groupValue, + }) : super(key: key); final VoidCallback onPressed; final void Function(Object?) onChanged; - final ThemeType value; - final ThemeType groupValue; + final String label; + final T value; + final T groupValue; @override Widget build(BuildContext context) { @@ -39,9 +40,9 @@ class ThemeOption extends StatelessWidget { Row( children: [ SizedBox( - width: 10, - height: 10, - child: Radio( + width: 20, + height: 20, + child: Radio( activeColor: Theme.of(context) .extension()! .radioButtonIconEnabled, @@ -54,7 +55,7 @@ class ThemeOption extends StatelessWidget { width: 14, ), Text( - value.prettyName, + label, style: STextStyles.desktopTextExtraSmall(context).copyWith( color: Theme.of(context).extension()!.textDark2, diff --git a/lib/pages/settings_views/global_settings_view/appearance_settings/sub_widgets/theme_options_widget.dart b/lib/pages/settings_views/global_settings_view/appearance_settings/sub_widgets/theme_options_widget.dart index 4ad84c68f..8c9334ef3 100644 --- a/lib/pages/settings_views/global_settings_view/appearance_settings/sub_widgets/theme_options_widget.dart +++ b/lib/pages/settings_views/global_settings_view/appearance_settings/sub_widgets/theme_options_widget.dart @@ -1,49 +1,199 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings/sub_widgets/theme_option.dart'; +import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings/system_brightness_theme_selection_view.dart'; import 'package:stackwallet/providers/providers.dart'; import 'package:stackwallet/providers/ui/color_theme_provider.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/color_theme.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; +import 'package:stackwallet/widgets/conditional_parent.dart'; +import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart'; -class ThemeOptionsWidget extends ConsumerWidget { +class ThemeOptionsWidget extends ConsumerStatefulWidget { const ThemeOptionsWidget({Key? key}) : super(key: key); @override - Widget build(BuildContext context, WidgetRef ref) { + ConsumerState createState() => _ThemeOptionsWidgetState(); +} + +class _ThemeOptionsWidgetState extends ConsumerState { + final systemDefault = ThemeType.values.length; + late int _current; + + void setTheme(int index) { + if (index == _current) { + return; + } + + if (index == systemDefault) { + // update current index + _current = index; + + // enable system brightness setting + ref.read(prefsChangeNotifierProvider).enableSystemBrightness = true; + + // get theme + final ThemeType theme; + switch (MediaQuery.of(context).platformBrightness) { + case Brightness.dark: + theme = ref + .read(prefsChangeNotifierProvider.notifier) + .systemBrightnessDarkTheme; + break; + case Brightness.light: + theme = ref + .read(prefsChangeNotifierProvider.notifier) + .systemBrightnessLightTheme; + break; + } + + // apply theme + ref.read(colorThemeProvider.notifier).state = + StackColors.fromStackColorTheme( + theme.colorTheme, + ); + + Assets.precache(context); + } else { + if (_current == systemDefault) { + // disable system brightness setting + ref.read(prefsChangeNotifierProvider).enableSystemBrightness = false; + } + + // update current index + _current = index; + + // get theme + final theme = ThemeType.values[index]; + + // save theme setting + ref.read(prefsChangeNotifierProvider.notifier).theme = theme; + + // apply theme + ref.read(colorThemeProvider.notifier).state = + StackColors.fromStackColorTheme( + theme.colorTheme, + ); + + Assets.precache(context); + } + } + + @override + void initState() { + if (ref.read(prefsChangeNotifierProvider).enableSystemBrightness) { + _current = ThemeType.values.length; + } else { + _current = + ThemeType.values.indexOf(ref.read(prefsChangeNotifierProvider).theme); + } + + super.initState(); + } + + @override + Widget build(BuildContext context) { return Column( children: [ - for (int i = 0; i < (2 * ThemeType.values.length) - 1; i++) - (i % 2 == 1) - ? const SizedBox( - height: 10, - ) - : ThemeOption( - onPressed: () { - ref.read(prefsChangeNotifierProvider.notifier).theme = - ThemeType.values[i ~/ 2]; - ref.read(colorThemeProvider.notifier).state = - StackColors.fromStackColorTheme( - ThemeType.values[i ~/ 2].colorTheme, - ); - Assets.precache(context); - }, - onChanged: (newValue) { - if (newValue == ThemeType.values[i ~/ 2]) { - ref.read(prefsChangeNotifierProvider.notifier).theme = - ThemeType.values[i ~/ 2]; - ref.read(colorThemeProvider.notifier).state = - StackColors.fromStackColorTheme( - ThemeType.values[i ~/ 2].colorTheme, - ); - Assets.precache(context); - } - }, - value: ThemeType.values[i ~/ 2], - groupValue: - Theme.of(context).extension()!.themeType, + MaterialButton( + splashColor: Colors.transparent, + hoverColor: Colors.transparent, + padding: const EdgeInsets.all(0), + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + Constants.size.circularBorderRadius, + ), + ), + onPressed: () { + setTheme(systemDefault); + }, + child: SizedBox( + width: 200, + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: 20, + height: 26, + child: Radio( + activeColor: Theme.of(context) + .extension()! + .radioButtonIconEnabled, + value: ThemeType.values.length, + groupValue: _current, + onChanged: (newValue) { + if (newValue is int) { + setTheme(newValue); + } + }, + ), + ), + const SizedBox( + width: 14, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "System default", + style: STextStyles.desktopTextExtraSmall(context) + .copyWith( + color: Theme.of(context) + .extension()! + .textDark2, + ), + ), + const SizedBox( + height: 2, + ), + CustomTextButton( + text: "Options", + onTap: () { + Navigator.of(context).pushNamed( + SystemBrightnessThemeSelectionView.routeName, + ); + }, + ), + ], + ), + ], ), + ], + ), + ), + ), + const SizedBox( + height: 10, + ), + for (int i = 0; i < ThemeType.values.length; i++) + ConditionalParent( + condition: i > 0, + builder: (child) => Padding( + padding: const EdgeInsets.only(top: 10), + child: child, + ), + child: ThemeOption( + label: ThemeType.values[i].prettyName, + onPressed: () { + setTheme(i); + }, + onChanged: (newValue) { + if (newValue is int) { + setTheme(newValue); + } + }, + value: i, + groupValue: _current, + ), + ), ], ); } diff --git a/lib/pages/settings_views/global_settings_view/appearance_settings/system_brightness_theme_selection_view.dart b/lib/pages/settings_views/global_settings_view/appearance_settings/system_brightness_theme_selection_view.dart index 676d52139..bb73aa10b 100644 --- a/lib/pages/settings_views/global_settings_view/appearance_settings/system_brightness_theme_selection_view.dart +++ b/lib/pages/settings_views/global_settings_view/appearance_settings/system_brightness_theme_selection_view.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:stackwallet/pages/settings_views/global_settings_view/appearance_settings/sub_widgets/theme_option.dart'; -import 'package:stackwallet/utilities/constants.dart'; +import 'package:stackwallet/providers/global/prefs_provider.dart'; +import 'package:stackwallet/providers/ui/color_theme_provider.dart'; import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/theme/color_theme.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart'; @@ -8,20 +10,41 @@ import 'package:stackwallet/widgets/background.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; import 'package:stackwallet/widgets/rounded_white_container.dart'; -class SystemBrightnessThemeSelectionView extends StatelessWidget { +class SystemBrightnessThemeSelectionView extends ConsumerWidget { const SystemBrightnessThemeSelectionView({ Key? key, - required this.brightness, - required this.current, }) : super(key: key); - final String brightness; - final ThemeType current; - static const String routeName = "/chooseSystemTheme"; + void _setTheme({ + required BuildContext context, + required bool isDark, + required ThemeType type, + required WidgetRef ref, + }) { + final brightness = MediaQuery.of(context).platformBrightness; + if (isDark) { + ref.read(prefsChangeNotifierProvider).systemBrightnessDarkTheme = type; + if (brightness == Brightness.dark) { + ref.read(colorThemeProvider.notifier).state = + StackColors.fromStackColorTheme( + type.colorTheme, + ); + } + } else { + ref.read(prefsChangeNotifierProvider).systemBrightnessLightTheme = type; + if (brightness == Brightness.light) { + ref.read(colorThemeProvider.notifier).state = + StackColors.fromStackColorTheme( + type.colorTheme, + ); + } + } + } + @override - Widget build(BuildContext context) { + Widget build(BuildContext context, WidgetRef ref) { return Background( child: Scaffold( backgroundColor: Theme.of(context).extension()!.background, @@ -32,97 +55,160 @@ class SystemBrightnessThemeSelectionView extends StatelessWidget { }, ), title: Text( - "Choose $brightness theme", + "System default theme", style: STextStyles.navBarTitle(context), ), ), - body: Padding( - padding: const EdgeInsets.all(16), - child: LayoutBuilder( - builder: (context, constraints) { - return SingleChildScrollView( - child: ConstrainedBox( - constraints: BoxConstraints( - minHeight: constraints.maxHeight, - ), - child: IntrinsicHeight( + body: LayoutBuilder( + builder: (context, constraints) { + return SingleChildScrollView( + child: ConstrainedBox( + constraints: BoxConstraints( + minHeight: constraints.maxHeight, + ), + child: IntrinsicHeight( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ + const SizedBox( + height: 16, + ), RoundedWhiteContainer( - padding: const EdgeInsets.all(0), - child: RawMaterialButton( - // splashColor: Theme.of(context).extension()!.highlight, - padding: const EdgeInsets.all(0), - materialTapTargetSize: - MaterialTapTargetSize.shrinkWrap, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular( - Constants.size.circularBorderRadius, - ), - ), - onPressed: null, - child: Padding( - padding: const EdgeInsets.all(12), - child: Row( - children: [ - Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.all(10), - child: Column( - children: [ - for (int i = 0; - i < - (2 * - ThemeType.values - .length) - - 1; - i++) - (i % 2 == 1) - ? const SizedBox( - height: 10, - ) - : ThemeOption( - onPressed: () { - Navigator.of(context) - .pop(ThemeType - .values[ - i ~/ 2]); - }, - onChanged: (newValue) { - if (newValue == - ThemeType.values[ - i ~/ 2]) { - Navigator.of(context) - .pop(ThemeType - .values[ - i ~/ 2]); - } - }, - value: ThemeType - .values[i ~/ 2], - groupValue: current, - ), - ], - ), - ), - ], - ), - ], - ), - ), + child: Text( + "Select a light and dark theme that will be" + " activated automatically when your phone system" + " switches light and dark mode.", + style: STextStyles.smallMed12(context), ), ), + const SizedBox( + height: 10, + ), + RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Choose dark mode theme", + style: STextStyles.titleBold12(context), + ), + const SizedBox( + height: 18, + ), + for (int i = 0; + i < (2 * ThemeType.values.length) - 1; + i++) + (i % 2 == 1) + ? const SizedBox( + height: 10, + ) + : ThemeOption( + label: + ThemeType.values[i ~/ 2].prettyName, + onPressed: () { + _setTheme( + context: context, + isDark: false, + type: ThemeType.values[i ~/ 2], + ref: ref, + ); + }, + onChanged: (newValue) { + final value = + ThemeType.values[i ~/ 2]; + if (newValue == value && + ref + .read( + prefsChangeNotifierProvider) + .systemBrightnessLightTheme != + value) { + _setTheme( + context: context, + isDark: false, + type: value, + ref: ref, + ); + } + }, + value: ThemeType.values[i ~/ 2], + groupValue: ref.watch( + prefsChangeNotifierProvider.select( + (value) => value + .systemBrightnessLightTheme)), + ), + ], + ), + ), + const SizedBox( + height: 10, + ), + RoundedWhiteContainer( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "Choose dark mode theme", + style: STextStyles.titleBold12(context), + ), + const SizedBox( + height: 18, + ), + for (int i = 0; + i < (2 * ThemeType.values.length) - 1; + i++) + (i % 2 == 1) + ? const SizedBox( + height: 10, + ) + : ThemeOption( + label: + ThemeType.values[i ~/ 2].prettyName, + onPressed: () { + _setTheme( + context: context, + isDark: true, + type: ThemeType.values[i ~/ 2], + ref: ref, + ); + }, + onChanged: (newValue) { + final value = + ThemeType.values[i ~/ 2]; + if (newValue == value && + ref + .read( + prefsChangeNotifierProvider) + .systemBrightnessDarkTheme != + value) { + _setTheme( + context: context, + isDark: true, + type: value, + ref: ref, + ); + } + }, + value: ThemeType.values[i ~/ 2], + groupValue: ref.watch( + prefsChangeNotifierProvider.select( + (value) => value + .systemBrightnessDarkTheme)), + ), + ], + ), + ), + const SizedBox( + height: 16, + ), ], ), ), ), - ); - }, - ), + ), + ); + }, ), ), ); diff --git a/lib/route_generator.dart b/lib/route_generator.dart index 55fbe92a9..a5bf762af 100644 --- a/lib/route_generator.dart +++ b/lib/route_generator.dart @@ -148,7 +148,6 @@ import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_ import 'package:stackwallet/utilities/amount/amount.dart'; import 'package:stackwallet/utilities/enums/add_wallet_type_enum.dart'; import 'package:stackwallet/utilities/enums/coin_enum.dart'; -import 'package:stackwallet/utilities/theme/color_theme.dart'; import 'package:tuple/tuple.dart'; class RouteGenerator { @@ -762,19 +761,13 @@ class RouteGenerator { return _routeError("${settings.name} invalid args: ${args.toString()}"); case SystemBrightnessThemeSelectionView.routeName: - if (args is Tuple2) { - return getRoute( - shouldUseMaterialRoute: useMaterialPageRoute, - builder: (_) => SystemBrightnessThemeSelectionView( - brightness: args.item1, - current: args.item2, - ), - settings: RouteSettings( - name: settings.name, - ), - ); - } - return _routeError("${settings.name} invalid args: ${args.toString()}"); + return getRoute( + shouldUseMaterialRoute: useMaterialPageRoute, + builder: (_) => const SystemBrightnessThemeSelectionView(), + settings: RouteSettings( + name: settings.name, + ), + ); case WalletNetworkSettingsView.routeName: if (args is Tuple3) { From b358efe656ed709261188396a1d8afcf2c8da4b9 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 13 Apr 2023 14:46:20 -0600 Subject: [PATCH 8/8] mobile swap rate type toggle height fix --- lib/pages/exchange_view/exchange_form.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pages/exchange_view/exchange_form.dart b/lib/pages/exchange_view/exchange_form.dart index e7b2f79af..11b4f4e51 100644 --- a/lib/pages/exchange_view/exchange_form.dart +++ b/lib/pages/exchange_view/exchange_form.dart @@ -857,7 +857,7 @@ class _ExchangeFormState extends ConsumerState { height: isDesktop ? 20 : 12, ), SizedBox( - height: 60, + height: isDesktop ? 60 : 40, child: RateTypeToggle( key: UniqueKey(), onChanged: onRateTypeChanged,