New themes (#2239)

* Add theme base v2

* Initial new theme base files

* Typos

* Fixes

* Update theme files

* feat: Migrate to Material 3 Theming

Foundation, Theme Data Refactor, and First Extension Cleanup Batch.

This commit completes the first major phase of migrating to Material 3 theming by setting up the foundations for material 3 integration and begins the initial migration, removing custom theme extensions, updating theme data, and refactoring all relevant widget and page theming to use Material 3’s built-in color and typography tokens.

These changes:
- Lays the groundwork for Material 3 theming by restructuring the app’s theme configuration to use Material 3’s ColorScheme and TextTheme as the primary sources of color and typography throughout the app.
- Refactors the core theme config files by removing legacy custom color roles ensuring all color definitions now map directly to Material 3’s role.
- Begins the first batch migration of custom theme extensions (InfoTheme, PlaceholderTheme, KeyboardTheme, PinCodeTheme) and updates all affected widgets and pages to use Material 3 color and typography tokens instead of the custom properties.
- Cleans up the codebase by deleting the files of the initial set of migrated extensions and eliminating all related imports and usages.

* feat: Migrate to Material 3 Theming.

This change:
- Updates the themes README.md file to reflect the current structure and give more information based on the first major phase that was completed.

* feat: Migrate to Material 3 Theming

Deleting previous theme extensions

* feat: Migrate to Material 3 Theming

Another batch of migrations from existing extensions

* feat: Migration to Material 3 Theming

Third Migration batch for theme extensions

* fwat: Migration to Material 3 Theming

Final Migration batch for previous theme extensions

* Update onboarding hero

* Update button radius

* Add surfaceContainer to light theme

* feat(themes): Migrate to Material 3 Theming

This change:
- Adds new set of hero images
- Modifies the core structure for the themes
- Add missing color tokens to the theme classes
- Adds a CustomThemeColor class for custom color tokens
- Modifies the themelist to have a fall back for previous theme implementation
- Adds localization for some texts
- Modifies the flow for loading the theme on app start
- Add a WidgetsBindingObserver that listens for changes in the device theme and updates the app theme when there is a change
- Registers the themeStore as a Singleton for codebase wide use

* feat(themes): Migrate to Material 3 theming

This change:
- Migrates UI flows across the app to the new themes
- Confirms styling and typography of components across the app uses the new themes
- Remove instances of Palette use
- Switch TextStyles across the app to use theme text styles

* feat(themes): Migrate to Material 3 Theming.

This change:
- Adjusts bottomsheets styling and removes duplicate close button
- Removes more themedata extensions from the previous implementation

* - Remove outlines from cards and dock
- Update menu colors
- Update padding/divider size for cards

* - Update PIN screen
- Fix navigation dock shadow
- Update wallet screen colors

* Update border radius --skip-ci

* feat(themes): Migrate to Material 3 Theming.

This change:
- Adds gradient backgrounds to the dashbaord and balance cards.
- Migrates the input fields across the app to BaseTextFormFields.
- Removes dependence of input fields on individual styling, focusing instead on using theme defined InputDecoration styling with adjustments on individual components where needed.
- Applies new theme styling to BaseTextFormField, AddressTextField and CurrencyAmountTextField.

* - Switch some hero images to PNG
- Fix nagivation_dock shadow
- Minor fixes

* feat: Add fallback to previous underline styling in central widgets

This change:
- Adds a fallback to CurrencyAmountTextField, AddressTextField, and BaseTextFormField, allowing them use the previous theme styling.
- Adds localization for new texts

* feat(themes): Update warning box colors for dark and light themes

* feat(themes): Relaod themes when user restores from backup, ensuring the user previous theme preference is used.

* feat(themes): Handle themes logic during restore from backup

This change:
- Refactors theme loading logic to handle backup restore edgecase
- Refreshes the theme based on the user saved preference during restore from backup flow

* Fix card gradients and spacing

* Fix even more radiuses
Test new icons for navigation_dock.dart

* Update onboarding flow backgrounds
Fix swap icon clipping
Fix some text colors
Add more hero images

* Fix incorrect color for light theme

* Fix more hero images and cleanup

* Update text field icons
Fix info box CTA colors
Fix sync indicator colors

* Update toggle colors
Update dark theme colors (minor)
Update crypto_balance_widget.dart icon

* Update page transitions in router.dart
Fix some colors

* feat(themes): Display label by default for filled textfields

* feat(themes): Refactor theme handling across various components

This change:
- Fixes issue with themeMode resetting to system mode when app is restarted causing a UI glitch
- Updates theme checks from `currentTheme.type == ThemeType.dark` to `currentTheme.isDark` for consistency
- Adjusts UI components to use the theme directly from the themeStore

* feat(themes): Add animating tagline to the create pin welcome screen

* Revert text fields label temporarily, fix a couple colors, and cleanup some images

---------

Co-authored-by: OmarHatem <omarh.ismail1@gmail.com>
Co-authored-by: Blazebrain <davidadegoke16@gmail.com>
This commit is contained in:
tuxsudo 2025-05-25 20:11:45 +00:00 committed by GitHub
parent 7b8ddf9685
commit df88914628
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
412 changed files with 11173 additions and 13192 deletions

View file

@ -25,11 +25,6 @@ import 'package:cake_wallet/src/widgets/primary_button.dart';
import 'package:cake_wallet/src/widgets/scollable_with_bottom_section.dart';
import 'package:cake_wallet/src/widgets/template_tile.dart';
import 'package:cake_wallet/src/widgets/trail_button.dart';
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
import 'package:cake_wallet/themes/extensions/keyboard_theme.dart';
import 'package:cake_wallet/themes/extensions/seed_widget_theme.dart';
import 'package:cake_wallet/themes/extensions/send_page_theme.dart';
import 'package:cake_wallet/themes/theme_base.dart';
import 'package:cake_wallet/utils/payment_request.dart';
import 'package:cake_wallet/utils/request_review_handler.dart';
import 'package:cake_wallet/utils/responsive_layout_util.dart';
@ -87,11 +82,10 @@ class SendPage extends BasePage {
Widget? leading(BuildContext context) {
final _backButton = Icon(
Icons.arrow_back_ios,
color: titleColor(context),
color: Theme.of(context).colorScheme.primary,
size: 16,
);
final _closeButton =
currentTheme.type == ThemeType.dark ? closeButtonImageDarkTheme : closeButtonImage;
final _closeButton = currentTheme.isDark ? closeButtonImageDarkTheme : closeButtonImage;
bool isMobileView = responsiveLayoutUtil.shouldRenderMobileUI;
@ -105,7 +99,7 @@ class SendPage extends BasePage {
label: !isMobileView ? S.of(context).close : S.of(context).seed_alert_back,
child: TextButton(
style: ButtonStyle(
overlayColor: MaterialStateColor.resolveWith((states) => Colors.transparent),
overlayColor: WidgetStateColor.resolveWith((states) => Colors.transparent),
),
onPressed: () => onClose(context),
child: !isMobileView ? _closeButton : _backButton,
@ -143,25 +137,29 @@ class SendPage extends BasePage {
}
@override
Widget trailing(context) => Observer(builder: (_) {
return sendViewModel.isBatchSending
? TrailButton(
caption: S.of(context).remove,
onPressed: () {
var pageToJump = (controller.page?.round() ?? 0) - 1;
pageToJump = pageToJump > 0 ? pageToJump : 0;
final output = _defineCurrentOutput();
sendViewModel.removeOutput(output);
controller.jumpToPage(pageToJump);
})
: TrailButton(
caption: S.of(context).clear,
onPressed: () {
final output = _defineCurrentOutput();
_formKey.currentState?.reset();
output.reset();
});
});
Widget trailing(context) => Observer(
builder: (_) {
return sendViewModel.isBatchSending
? TrailButton(
caption: S.of(context).remove,
onPressed: () {
var pageToJump = (controller.page?.round() ?? 0) - 1;
pageToJump = pageToJump > 0 ? pageToJump : 0;
final output = _defineCurrentOutput();
sendViewModel.removeOutput(output);
controller.jumpToPage(pageToJump);
},
)
: TrailButton(
caption: S.of(context).clear,
onPressed: () {
final output = _defineCurrentOutput();
_formKey.currentState?.reset();
output.reset();
},
);
},
);
@override
Widget body(BuildContext context) {
@ -173,26 +171,36 @@ class SendPage extends BasePage {
for (var output in sendViewModel.outputs) {
var cryptoAmountFocus = FocusNode();
var fiatAmountFocus = FocusNode();
sendCards.add(SendCard(
currentTheme: currentTheme,
key: output.key,
output: output,
sendViewModel: sendViewModel,
initialPaymentRequest: initialPaymentRequest,
cryptoAmountFocus: cryptoAmountFocus,
fiatAmountFocus: fiatAmountFocus,
));
keyboardActions.add(KeyboardActionsItem(
focusNode: cryptoAmountFocus, toolbarButtons: [(_) => KeyboardDoneButton()]));
keyboardActions.add(KeyboardActionsItem(
focusNode: fiatAmountFocus, toolbarButtons: [(_) => KeyboardDoneButton()]));
sendCards.add(
SendCard(
currentTheme: currentTheme,
key: output.key,
output: output,
sendViewModel: sendViewModel,
initialPaymentRequest: initialPaymentRequest,
cryptoAmountFocus: cryptoAmountFocus,
fiatAmountFocus: fiatAmountFocus,
),
);
keyboardActions.add(
KeyboardActionsItem(
focusNode: cryptoAmountFocus,
toolbarButtons: [(_) => KeyboardDoneButton()],
),
);
keyboardActions.add(
KeyboardActionsItem(
focusNode: fiatAmountFocus,
toolbarButtons: [(_) => KeyboardDoneButton()],
),
);
}
return Stack(
children: [
KeyboardActions(
config: KeyboardActionsConfig(
keyboardActionsPlatform: KeyboardActionsPlatform.ALL,
keyboardBarColor: Theme.of(context).extension<KeyboardTheme>()!.keyboardBarColor,
keyboardBarColor: Theme.of(context).colorScheme.surface,
nextFocus: false,
actions: keyboardActions,
),
@ -236,17 +244,18 @@ class SendPage extends BasePage {
controller: controller,
count: count,
effect: ScrollingDotsEffect(
spacing: 6.0,
radius: 6.0,
dotWidth: 6.0,
dotHeight: 6.0,
dotColor: Theme.of(context)
.extension<SendPageTheme>()!
.indicatorDotColor,
activeDotColor: Theme.of(context)
.extension<SendPageTheme>()!
.templateBackgroundColor),
))
spacing: 6.0,
radius: 6.0,
dotWidth: 6.0,
dotHeight: 6.0,
dotColor: Theme.of(context)
.colorScheme
.primary
.withOpacity(0.4),
activeDotColor: Theme.of(context).colorScheme.primary,
),
),
)
: Offstage();
},
),
@ -367,8 +376,7 @@ class SendPage extends BasePage {
onPressed: () => presentCurrencyPicker(context),
text: 'Change your asset (${sendViewModel.selectedCryptoCurrency})',
color: Colors.transparent,
textColor:
Theme.of(context).extension<SeedWidgetTheme>()!.hintTextColor,
textColor: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
),
@ -385,12 +393,9 @@ class SendPage extends BasePage {
},
text: S.of(context).add_receiver,
color: Colors.transparent,
textColor:
Theme.of(context).extension<SeedWidgetTheme>()!.hintTextColor,
textColor: Theme.of(context).colorScheme.onSurfaceVariant,
isDottedBorder: true,
borderColor: Theme.of(context)
.extension<SendPageTheme>()!
.templateDottedBorderColor,
borderColor: Theme.of(context).colorScheme.outline,
)),
Observer(
builder: (_) {
@ -463,9 +468,11 @@ class SendPage extends BasePage {
},
);
},
text: sendViewModel.payjoinUri != null ? S.of(context).send_payjoin : S.of(context).send,
color: Theme.of(context).primaryColor,
textColor: Colors.white,
text: sendViewModel.payjoinUri != null
? S.of(context).send_payjoin
: S.of(context).send,
color: Theme.of(context).colorScheme.primary,
textColor: Theme.of(context).colorScheme.onPrimary,
isLoading: sendViewModel.state is IsExecutingState ||
sendViewModel.state is TransactionCommitting ||
sendViewModel.state is IsAwaitingDeviceResponseState ||
@ -507,19 +514,23 @@ class SendPage extends BasePage {
}
if (state is FailureState) {
WidgetsBinding.instance.addPostFrameCallback((_) {
showPopUp<void>(
WidgetsBinding.instance.addPostFrameCallback(
(_) {
showPopUp<void>(
context: context,
builder: (BuildContext context) {
return AlertWithOneAction(
key: ValueKey('send_page_send_failure_dialog_key'),
buttonKey: ValueKey('send_page_send_failure_dialog_button_key'),
alertTitle: S.of(context).error,
alertContent: state.error,
buttonText: S.of(context).ok,
buttonAction: () => Navigator.of(context).pop());
});
});
key: ValueKey('send_page_send_failure_dialog_key'),
buttonKey: ValueKey('send_page_send_failure_dialog_button_key'),
alertTitle: S.of(context).error,
alertContent: state.error,
buttonText: S.of(context).ok,
buttonAction: () => Navigator.of(context).pop(),
);
},
);
},
);
}
if (state is IsExecutingState) {
@ -604,15 +615,14 @@ class SendPage extends BasePage {
context: context,
isDismissible: false,
builder: (BuildContext bottomSheetContext) {
return showContactSheet &&
sendViewModel.ocpRequest == null
return showContactSheet && sendViewModel.ocpRequest == null
? InfoBottomSheet(
currentTheme: currentTheme,
showDontAskMeCheckbox: true,
onCheckboxChanged: (value) => sendViewModel.setShowAddressBookPopup(!value),
titleText: S.of(bottomSheetContext).transaction_sent,
contentImage: 'assets/images/contact_icon.svg',
contentImageColor: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
contentImage: 'assets/images/contact.png',
contentImageColor: Theme.of(context).colorScheme.onSurface,
content: S.of(bottomSheetContext).add_contact_to_address_book,
isTwoAction: true,
leftButtonText: 'No',
@ -639,7 +649,7 @@ class SendPage extends BasePage {
: InfoBottomSheet(
currentTheme: currentTheme,
titleText: S.of(bottomSheetContext).transaction_sent,
contentImage: 'assets/images/birthday_cake.svg',
contentImage: 'assets/images/birthday_cake.png',
actionButtonText: S.of(bottomSheetContext).close,
actionButtonKey: ValueKey('send_page_sent_dialog_ok_button_key'),
actionButton: () {
@ -685,7 +695,7 @@ class SendPage extends BasePage {
currentTheme: currentTheme,
titleText: S.of(bottomSheetContext).proceed_on_device,
contentImage: 'assets/images/hardware_wallet/ledger_nano_x.png',
contentImageColor: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
contentImageColor: Theme.of(context).colorScheme.onSurface,
content: S.of(bottomSheetContext).proceed_on_device_description,
isTwoAction: false,
actionButtonText: S.of(context).cancel,