mobile_nebula/lib/services/theme.dart
Ian VanSchooten 5a641be96f
Switch to Material 3 for Android (#224)
This exploration updates the Android app to use Google's Material 3 design, and changes up the colors a bit in the process.  
I used a source color of #5D23DD in https://material-foundation.github.io/material-theme-builder/, which generates a full set of material colors that I imported into `lib/services/theme.dart`.  It should be easy to tweak any of the colors that we want, vs previously it was somewhat more difficult because they were being generated "behind the scenes".

This doesn't necessarily need to be done now, but it does align better with more modern Android design patterns and Flutter has said at some point they will stop supporting Material 2.  

Note: this should not have any impact on iOS, since we use the default `CupertinoThemeData` there, without any custom theming.

Here are some before/after comparisons of interesting screens:

Adding a new site:
|Dark Before|Dark After|Light Before|Light After|
|---|---|---|---
|<img width="390" alt="Android Studio 2025-01-22 10 43 55" src="https://github.com/user-attachments/assets/c7954b7f-a8eb-48a5-bd47-237877f078fd" />|<img width="405" alt="Android Studio 2025-01-22 11 16 48" src="https://github.com/user-attachments/assets/b69c1e6f-3464-44af-9f9c-f6377b5ce1d1" />|<img width="389" alt="image" src="https://github.com/user-attachments/assets/40f1e40f-a1f5-42e4-909c-c07b3f82df2b" />|<img width="393" alt="image" src="https://github.com/user-attachments/assets/09f8f8ce-668e-4e69-a4a9-233fb970655f" />|


Confirmation dialog:
|Before|After|
|---|---|
|<img width="264" alt="image" src="https://github.com/user-attachments/assets/7cae1abc-621d-4c59-bf36-0ce3be0af88c" />|<img width="278" alt="Android Studio 2025-01-22 11 43 19" src="https://github.com/user-attachments/assets/d461a97f-d252-494f-8b30-49d33a5a9cda" />|

Settings page:
|Dark Before|Dark After|Light Before|Light After|
|---|---|---|---|
|<img width="394" alt="Android Studio 2025-01-22 11 46 01" src="https://github.com/user-attachments/assets/edfc6c40-ee72-4a7c-b9b7-7c3025f0cdfe" />|<img width="393" alt="Android Studio 2025-01-22 11 46 35" src="https://github.com/user-attachments/assets/d1445041-bbc0-4994-98d5-3eb149afceea" />|<img width="391" alt="Android Studio 2025-01-22 11 46 09" src="https://github.com/user-attachments/assets/295e5cc4-74e2-422a-b478-a3e0bd577b60" />|<img width="391" alt="Android Studio 2025-01-22 11 46 28" src="https://github.com/user-attachments/assets/098339de-f2df-4269-84cf-e3ae2c09a51d" />|

Site with errors:
|Dark Before|Dark After|Light Before|Light After|
|---|---|---|---|
|<img width="395" alt="Android Studio 2025-01-22 11 48 50" src="https://github.com/user-attachments/assets/4f8dd05d-ccc7-44eb-96e0-ffec63975085" />|<img width="390" alt="Android Studio 2025-01-22 11 48 06" src="https://github.com/user-attachments/assets/751f35e2-b801-4ddf-9655-15f0097e05ca" />|<img width="395" alt="image" src="https://github.com/user-attachments/assets/15ac20c9-4d40-4e51-aed6-fd69a001588b" />|<img width="388" alt="Android Studio 2025-01-22 11 48 20" src="https://github.com/user-attachments/assets/780bf849-9add-4f91-bac8-3cdd5fd89337" />|

Main page / site list:
|Light Before|Light After|Light Scrolled Before|Light Scrolled After|
|---|---|---|---|
|<img width="387" alt="Android Studio 2025-01-22 11 53 07" src="https://github.com/user-attachments/assets/ca426470-00c2-4dc3-bd22-4a336c4ec8cf" />|<img width="403" alt="Android Studio 2025-01-22 11 53 41" src="https://github.com/user-attachments/assets/abf755e3-df10-453b-a439-0aa3b21b7ef9" />|<img width="389" alt="Android Studio 2025-01-22 11 53 22" src="https://github.com/user-attachments/assets/a6cdfabf-5288-49fe-ac29-e73678d34ccb" />|<img width="396" alt="Android Studio 2025-01-22 11 53 51" src="https://github.com/user-attachments/assets/11eda1f4-cf2f-4848-9690-6093223a9e7e" />|

Certificate:
|Dark Before|Dark After|Light Before|Light After|
|---|---|---|---|
|<img width="388" alt="Android Studio 2025-01-22 11 57 25" src="https://github.com/user-attachments/assets/5a1db1ba-a560-4aa6-8649-9b41d9ba25b6" />|<img width="390" alt="Android Studio 2025-01-22 11 56 44" src="https://github.com/user-attachments/assets/5e1b9200-ea13-42e5-a55d-51a1fda4522f" />|<img width="397" alt="Android Studio 2025-01-22 11 57 01" src="https://github.com/user-attachments/assets/65c52218-3f90-40c7-bb21-e499c2e0b08c" />|<img width="392" alt="Android Studio 2025-01-22 11 56 21" src="https://github.com/user-attachments/assets/554847cd-e825-4691-ac21-1549ab5e7d21" />|
2025-01-23 10:49:32 -05:00

389 lines
14 KiB
Dart

import "package:flutter/material.dart";
// Originally generated by https://material-foundation.github.io/material-theme-builder/
// from a source color of #5D23DD
class MaterialTheme {
final TextTheme textTheme;
const MaterialTheme(this.textTheme);
static ColorScheme lightScheme() {
return const ColorScheme(
brightness: Brightness.light,
primary: Color(4284700303),
surfaceTint: Color(4284700303),
onPrimary: Color(4294967295),
primaryContainer: Color(4293451519),
onPrimaryContainer: Color(4283121270),
secondary: Color(4284570481),
onSecondary: Color(4294967295),
secondaryContainer: Color(4293385976),
onSecondaryContainer: Color(4282991704),
tertiary: Color(4286403169),
onTertiary: Color(4294967295),
tertiaryContainer: Color(4294957540),
onTertiaryContainer: Color(4284693322),
error: Color(4290386458),
onError: Color(4294967295),
errorContainer: Color(4294957782),
onErrorContainer: Color(4287823882),
surface: Color(4294834175),
onSurface: Color(4280032032),
onSurfaceVariant: Color(4282926414),
outline: Color(4286150015),
outlineVariant: Color(4291478735),
shadow: Color(4278190080),
scrim: Color(4278190080),
inverseSurface: Color(4281478965),
inversePrimary: Color(4291673599),
primaryFixed: Color(4293451519),
onPrimaryFixed: Color(4280225864),
primaryFixedDim: Color(4291673599),
onPrimaryFixedVariant: Color(4283121270),
secondaryFixed: Color(4293385976),
onSecondaryFixed: Color(4280097067),
secondaryFixedDim: Color(4291544028),
onSecondaryFixedVariant: Color(4282991704),
tertiaryFixed: Color(4294957540),
onTertiaryFixed: Color(4281405726),
tertiaryFixedDim: Color(4293834953),
onTertiaryFixedVariant: Color(4284693322),
surfaceDim: Color(4292729056),
surfaceBright: Color(4294834175),
surfaceContainerLowest: Color(4294967295),
surfaceContainerLow: Color(4294439674),
surfaceContainer: Color(4294110452),
surfaceContainerHigh: Color(4293715694),
surfaceContainerHighest: Color(4293321193),
);
}
ThemeData light() {
return theme(lightScheme());
}
static ColorScheme lightMediumContrastScheme() {
return const ColorScheme(
brightness: Brightness.light,
primary: Color(4282002788),
surfaceTint: Color(4284700303),
onPrimary: Color(4294967295),
primaryContainer: Color(4285686943),
onPrimaryContainer: Color(4294967295),
secondary: Color(4281873223),
onSecondary: Color(4294967295),
secondaryContainer: Color(4285557376),
onSecondaryContainer: Color(4294967295),
tertiary: Color(4283444025),
onTertiary: Color(4294967295),
tertiaryContainer: Color(4287455344),
onTertiaryContainer: Color(4294967295),
error: Color(4285792262),
onError: Color(4294967295),
errorContainer: Color(4291767335),
onErrorContainer: Color(4294967295),
surface: Color(4294834175),
onSurface: Color(4279373846),
onSurfaceVariant: Color(4281873725),
outline: Color(4283715930),
outlineVariant: Color(4285492085),
shadow: Color(4278190080),
scrim: Color(4278190080),
inverseSurface: Color(4281478965),
inversePrimary: Color(4291673599),
primaryFixed: Color(4285686943),
onPrimaryFixed: Color(4294967295),
primaryFixedDim: Color(4284042373),
onPrimaryFixedVariant: Color(4294967295),
secondaryFixed: Color(4285557376),
onSecondaryFixed: Color(4294967295),
secondaryFixedDim: Color(4283912807),
onSecondaryFixedVariant: Color(4294967295),
tertiaryFixed: Color(4287455344),
onTertiaryFixed: Color(4294967295),
tertiaryFixedDim: Color(4285679960),
onTertiaryFixedVariant: Color(4294967295),
surfaceDim: Color(4291478989),
surfaceBright: Color(4294834175),
surfaceContainerLowest: Color(4294967295),
surfaceContainerLow: Color(4294439674),
surfaceContainer: Color(4293715694),
surfaceContainerHigh: Color(4292926435),
surfaceContainerHighest: Color(4292202712),
);
}
ThemeData lightMediumContrast() {
return theme(lightMediumContrastScheme());
}
static ColorScheme lightHighContrastScheme() {
return const ColorScheme(
brightness: Brightness.light,
primary: Color(4281344857),
surfaceTint: Color(4284700303),
onPrimary: Color(4294967295),
primaryContainer: Color(4283252856),
onPrimaryContainer: Color(4294967295),
secondary: Color(4281215292),
onSecondary: Color(4294967295),
secondaryContainer: Color(4283123291),
onSecondaryContainer: Color(4294967295),
tertiary: Color(4282655023),
onTertiary: Color(4294967295),
tertiaryContainer: Color(4284824908),
onTertiaryContainer: Color(4294967295),
error: Color(4284481540),
onError: Color(4294967295),
errorContainer: Color(4288151562),
onErrorContainer: Color(4294967295),
surface: Color(4294834175),
onSurface: Color(4278190080),
onSurfaceVariant: Color(4278190080),
outline: Color(4281150259),
outlineVariant: Color(4283123793),
shadow: Color(4278190080),
scrim: Color(4278190080),
inverseSurface: Color(4281478965),
inversePrimary: Color(4291673599),
primaryFixed: Color(4283252856),
onPrimaryFixed: Color(4294967295),
primaryFixedDim: Color(4281739616),
onPrimaryFixedVariant: Color(4294967295),
secondaryFixed: Color(4283123291),
onSecondaryFixed: Color(4294967295),
secondaryFixedDim: Color(4281675843),
onSecondaryFixedVariant: Color(4294967295),
tertiaryFixed: Color(4284824908),
onTertiaryFixed: Color(4294967295),
tertiaryFixedDim: Color(4283180853),
onTertiaryFixedVariant: Color(4294967295),
surfaceDim: Color(4290557887),
surfaceBright: Color(4294834175),
surfaceContainerLowest: Color(4294967295),
surfaceContainerLow: Color(4294242295),
surfaceContainer: Color(4293321193),
surfaceContainerHigh: Color(4292400090),
surfaceContainerHighest: Color(4291478989),
);
}
ThemeData lightHighContrast() {
return theme(lightHighContrastScheme());
}
static ColorScheme darkScheme() {
return const ColorScheme(
brightness: Brightness.dark,
primary: Color(4291673599),
surfaceTint: Color(4291673599),
onPrimary: Color(4281608030),
primaryContainer: Color(4283121270),
onPrimaryContainer: Color(4293451519),
secondary: Color(4291544028),
onSecondary: Color(4281478721),
secondaryContainer: Color(4282991704),
onSecondaryContainer: Color(4293385976),
tertiary: Color(4293834953),
onTertiary: Color(4282983731),
tertiaryContainer: Color(4284693322),
onTertiaryContainer: Color(4294957540),
error: Color(4294948011),
onError: Color(4285071365),
errorContainer: Color(4287823882),
onErrorContainer: Color(4294957782),
surface: Color(4279505688),
onSurface: Color(4293321193),
onSurfaceVariant: Color(4291478735),
outline: Color(4287860633),
outlineVariant: Color(4282926414),
shadow: Color(4278190080),
scrim: Color(4278190080),
inverseSurface: Color(4293321193),
inversePrimary: Color(4284700303),
primaryFixed: Color(4293451519),
onPrimaryFixed: Color(4280225864),
primaryFixedDim: Color(4291673599),
onPrimaryFixedVariant: Color(4283121270),
secondaryFixed: Color(4293385976),
onSecondaryFixed: Color(4280097067),
secondaryFixedDim: Color(4291544028),
onSecondaryFixedVariant: Color(4282991704),
tertiaryFixed: Color(4294957540),
onTertiaryFixed: Color(4281405726),
tertiaryFixedDim: Color(4293834953),
onTertiaryFixedVariant: Color(4284693322),
surfaceDim: Color(4279505688),
surfaceBright: Color(4282005566),
surfaceContainerLowest: Color(4279176467),
surfaceContainerLow: Color(4280032032),
surfaceContainer: Color(4280295204),
surfaceContainerHigh: Color(4281018671),
surfaceContainerHighest: Color(4281742394),
);
}
ThemeData dark() {
return theme(darkScheme());
}
static ColorScheme darkMediumContrastScheme() {
return const ColorScheme(
brightness: Brightness.dark,
primary: Color(4293056255),
surfaceTint: Color(4291673599),
onPrimary: Color(4280884306),
primaryContainer: Color(4288055493),
onPrimaryContainer: Color(4278190080),
secondary: Color(4292991218),
onSecondary: Color(4280754998),
secondaryContainer: Color(4287925669),
onSecondaryContainer: Color(4278190080),
tertiary: Color(4294955230),
onTertiary: Color(4282194472),
tertiaryContainer: Color(4290020244),
onTertiaryContainer: Color(4278190080),
error: Color(4294955724),
onError: Color(4283695107),
errorContainer: Color(4294923337),
onErrorContainer: Color(4278190080),
surface: Color(4279505688),
onSurface: Color(4294967295),
onSurfaceVariant: Color(4292926181),
outline: Color(4290097339),
outlineVariant: Color(4287860377),
shadow: Color(4278190080),
scrim: Color(4278190080),
inverseSurface: Color(4293321193),
inversePrimary: Color(4283187063),
primaryFixed: Color(4293451519),
onPrimaryFixed: Color(4279501629),
primaryFixedDim: Color(4291673599),
onPrimaryFixedVariant: Color(4282002788),
secondaryFixed: Color(4293385976),
onSecondaryFixed: Color(4279438880),
secondaryFixedDim: Color(4291544028),
onSecondaryFixedVariant: Color(4281873223),
tertiaryFixed: Color(4294957540),
onTertiaryFixed: Color(4280550932),
tertiaryFixedDim: Color(4293834953),
onTertiaryFixedVariant: Color(4283444025),
surfaceDim: Color(4279505688),
surfaceBright: Color(4282794826),
surfaceContainerLowest: Color(4278716172),
surfaceContainerLow: Color(4280163618),
surfaceContainer: Color(4280887085),
surfaceContainerHigh: Color(4281610808),
surfaceContainerHighest: Color(4282334531),
);
}
ThemeData darkMediumContrast() {
return theme(darkMediumContrastScheme());
}
static ColorScheme darkHighContrastScheme() {
return const ColorScheme(
brightness: Brightness.dark,
primary: Color(4294241791),
surfaceTint: Color(4291673599),
onPrimary: Color(4278190080),
primaryContainer: Color(4291410427),
onPrimaryContainer: Color(4279107636),
secondary: Color(4294241791),
onSecondary: Color(4278190080),
secondaryContainer: Color(4291280856),
onSecondaryContainer: Color(4279044122),
tertiary: Color(4294962160),
onTertiary: Color(4278190080),
tertiaryContainer: Color(4293571782),
onTertiaryContainer: Color(4280091150),
error: Color(4294962409),
onError: Color(4278190080),
errorContainer: Color(4294946468),
onErrorContainer: Color(4280418305),
surface: Color(4279505688),
onSurface: Color(4294967295),
onSurfaceVariant: Color(4294967295),
outline: Color(4294242041),
outlineVariant: Color(4291215563),
shadow: Color(4278190080),
scrim: Color(4278190080),
inverseSurface: Color(4293321193),
inversePrimary: Color(4283187063),
primaryFixed: Color(4293451519),
onPrimaryFixed: Color(4278190080),
primaryFixedDim: Color(4291673599),
onPrimaryFixedVariant: Color(4279501629),
secondaryFixed: Color(4293385976),
onSecondaryFixed: Color(4278190080),
secondaryFixedDim: Color(4291544028),
onSecondaryFixedVariant: Color(4279438880),
tertiaryFixed: Color(4294957540),
onTertiaryFixed: Color(4278190080),
tertiaryFixedDim: Color(4293834953),
onTertiaryFixedVariant: Color(4280550932),
surfaceDim: Color(4279505688),
surfaceBright: Color(4283584341),
surfaceContainerLowest: Color(4278190080),
surfaceContainerLow: Color(4280295204),
surfaceContainer: Color(4281478965),
surfaceContainerHigh: Color(4282202689),
surfaceContainerHighest: Color(4282926668),
);
}
ThemeData darkHighContrast() {
return theme(darkHighContrastScheme());
}
ThemeData theme(ColorScheme colorScheme) => ThemeData(
useMaterial3: true,
brightness: colorScheme.brightness,
colorScheme: colorScheme,
textTheme: textTheme.apply(
bodyColor: colorScheme.onSurface,
displayColor: colorScheme.onSurface,
),
scaffoldBackgroundColor: colorScheme.background,
canvasColor: colorScheme.surface,
);
List<ExtendedColor> get extendedColors => [];
}
class ExtendedColor {
final Color seed, value;
final ColorFamily light;
final ColorFamily lightHighContrast;
final ColorFamily lightMediumContrast;
final ColorFamily dark;
final ColorFamily darkHighContrast;
final ColorFamily darkMediumContrast;
const ExtendedColor({
required this.seed,
required this.value,
required this.light,
required this.lightHighContrast,
required this.lightMediumContrast,
required this.dark,
required this.darkHighContrast,
required this.darkMediumContrast,
});
}
class ColorFamily {
const ColorFamily({
required this.color,
required this.onColor,
required this.colorContainer,
required this.onColorContainer,
});
final Color color;
final Color onColor;
final Color colorContainer;
final Color onColorContainer;
}