
Replaces hardcoded colors and standard Theme.of(context) accesses with a custom AppTheme. Introduces distinct light and dark themes and persists the selected theme mode using shared_preferences. Integrates the theme into the main app structure and applies it to various components and pages. Adds google_fonts dependency for theme typography.
382 lines
13 KiB
Dart
382 lines
13 KiB
Dart
// ignore_for_file: overridden_fields, annotate_overrides
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:google_fonts/google_fonts.dart';
|
|
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
const kThemeModeKey = '__theme_mode__';
|
|
|
|
SharedPreferences? _prefs;
|
|
|
|
abstract class AppTheme {
|
|
static Future initialize() async =>
|
|
_prefs = await SharedPreferences.getInstance();
|
|
|
|
static ThemeMode get themeMode {
|
|
final darkMode = _prefs?.getBool(kThemeModeKey);
|
|
return darkMode == null
|
|
? ThemeMode.system
|
|
: darkMode
|
|
? ThemeMode.dark
|
|
: ThemeMode.light;
|
|
}
|
|
|
|
static void saveThemeMode(ThemeMode mode) => mode == ThemeMode.system
|
|
? _prefs?.remove(kThemeModeKey)
|
|
: _prefs?.setBool(kThemeModeKey, mode == ThemeMode.dark);
|
|
|
|
static AppTheme of(BuildContext context) {
|
|
return Theme.of(context).brightness == Brightness.dark
|
|
? DarkModeTheme()
|
|
: LightModeTheme();
|
|
}
|
|
|
|
late Color primary;
|
|
late Color secondary;
|
|
late Color tertiary;
|
|
late Color alternate;
|
|
late Color primaryText;
|
|
late Color secondaryText;
|
|
late Color primaryBackground;
|
|
late Color secondaryBackground;
|
|
late Color accent1;
|
|
late Color accent2;
|
|
late Color accent3;
|
|
late Color accent4;
|
|
late Color success;
|
|
late Color warning;
|
|
late Color error;
|
|
late Color info;
|
|
|
|
late Color trueBlue;
|
|
late Color orangePeel;
|
|
late Color white;
|
|
late Color columbiaBlue;
|
|
late Color battleshipGray;
|
|
late Color backgroundTransparent;
|
|
|
|
String get displayLargeFamily => typography.displayLargeFamily;
|
|
bool get displayLargeIsCustom => typography.displayLargeIsCustom;
|
|
TextStyle get displayLarge => typography.displayLarge;
|
|
String get displayMediumFamily => typography.displayMediumFamily;
|
|
bool get displayMediumIsCustom => typography.displayMediumIsCustom;
|
|
TextStyle get displayMedium => typography.displayMedium;
|
|
String get displaySmallFamily => typography.displaySmallFamily;
|
|
bool get displaySmallIsCustom => typography.displaySmallIsCustom;
|
|
TextStyle get displaySmall => typography.displaySmall;
|
|
String get headlineLargeFamily => typography.headlineLargeFamily;
|
|
bool get headlineLargeIsCustom => typography.headlineLargeIsCustom;
|
|
TextStyle get headlineLarge => typography.headlineLarge;
|
|
String get headlineMediumFamily => typography.headlineMediumFamily;
|
|
bool get headlineMediumIsCustom => typography.headlineMediumIsCustom;
|
|
TextStyle get headlineMedium => typography.headlineMedium;
|
|
String get headlineSmallFamily => typography.headlineSmallFamily;
|
|
bool get headlineSmallIsCustom => typography.headlineSmallIsCustom;
|
|
TextStyle get headlineSmall => typography.headlineSmall;
|
|
String get titleLargeFamily => typography.titleLargeFamily;
|
|
bool get titleLargeIsCustom => typography.titleLargeIsCustom;
|
|
TextStyle get titleLarge => typography.titleLarge;
|
|
String get titleMediumFamily => typography.titleMediumFamily;
|
|
bool get titleMediumIsCustom => typography.titleMediumIsCustom;
|
|
TextStyle get titleMedium => typography.titleMedium;
|
|
String get titleSmallFamily => typography.titleSmallFamily;
|
|
bool get titleSmallIsCustom => typography.titleSmallIsCustom;
|
|
TextStyle get titleSmall => typography.titleSmall;
|
|
String get labelLargeFamily => typography.labelLargeFamily;
|
|
bool get labelLargeIsCustom => typography.labelLargeIsCustom;
|
|
TextStyle get labelLarge => typography.labelLarge;
|
|
String get labelMediumFamily => typography.labelMediumFamily;
|
|
bool get labelMediumIsCustom => typography.labelMediumIsCustom;
|
|
TextStyle get labelMedium => typography.labelMedium;
|
|
String get labelSmallFamily => typography.labelSmallFamily;
|
|
bool get labelSmallIsCustom => typography.labelSmallIsCustom;
|
|
TextStyle get labelSmall => typography.labelSmall;
|
|
String get bodyLargeFamily => typography.bodyLargeFamily;
|
|
bool get bodyLargeIsCustom => typography.bodyLargeIsCustom;
|
|
TextStyle get bodyLarge => typography.bodyLarge;
|
|
String get bodyMediumFamily => typography.bodyMediumFamily;
|
|
bool get bodyMediumIsCustom => typography.bodyMediumIsCustom;
|
|
TextStyle get bodyMedium => typography.bodyMedium;
|
|
String get bodySmallFamily => typography.bodySmallFamily;
|
|
bool get bodySmallIsCustom => typography.bodySmallIsCustom;
|
|
TextStyle get bodySmall => typography.bodySmall;
|
|
|
|
Typography get typography => ThemeTypography(this);
|
|
}
|
|
|
|
class LightModeTheme extends AppTheme {
|
|
@Deprecated('Use primary instead')
|
|
Color get primaryColor => primary;
|
|
@Deprecated('Use secondary instead')
|
|
Color get secondaryColor => secondary;
|
|
@Deprecated('Use tertiary instead')
|
|
Color get tertiaryColor => tertiary;
|
|
|
|
late Color primary = const Color(0xFF3D6BB2);
|
|
late Color secondary = const Color(0xFFF9A434);
|
|
late Color tertiary = const Color(0xFFEE8B60);
|
|
late Color alternate = const Color(0xFFE0E3E7);
|
|
late Color primaryText = const Color(0xFF14181B);
|
|
late Color secondaryText = const Color(0xFF919191);
|
|
late Color primaryBackground = const Color(0xFFFFFFFF);
|
|
late Color secondaryBackground = const Color(0xFFF1F4F8);
|
|
late Color accent1 = const Color(0xFF003EA2);
|
|
late Color accent2 = const Color(0xFFB36600);
|
|
late Color accent3 = const Color(0x4DEE8B60);
|
|
late Color accent4 = const Color(0xCCFFFFFF);
|
|
late Color success = const Color(0xFF249689);
|
|
late Color warning = const Color(0xFFF9CF58);
|
|
late Color error = const Color(0xFFFF5963);
|
|
late Color info = const Color(0xFFFFFFFF);
|
|
|
|
late Color trueBlue = const Color(0xFF3D6BB2);
|
|
late Color orangePeel = const Color(0xFFF9A434);
|
|
late Color white = const Color(0xFFFFFFFF);
|
|
late Color columbiaBlue = const Color(0xFFC8D6E4);
|
|
late Color battleshipGray = const Color(0xFF919191);
|
|
late Color backgroundTransparent = const Color(0xB9FFFFFF);
|
|
}
|
|
|
|
abstract class Typography {
|
|
String get displayLargeFamily;
|
|
bool get displayLargeIsCustom;
|
|
TextStyle get displayLarge;
|
|
String get displayMediumFamily;
|
|
bool get displayMediumIsCustom;
|
|
TextStyle get displayMedium;
|
|
String get displaySmallFamily;
|
|
bool get displaySmallIsCustom;
|
|
TextStyle get displaySmall;
|
|
String get headlineLargeFamily;
|
|
bool get headlineLargeIsCustom;
|
|
TextStyle get headlineLarge;
|
|
String get headlineMediumFamily;
|
|
bool get headlineMediumIsCustom;
|
|
TextStyle get headlineMedium;
|
|
String get headlineSmallFamily;
|
|
bool get headlineSmallIsCustom;
|
|
TextStyle get headlineSmall;
|
|
String get titleLargeFamily;
|
|
bool get titleLargeIsCustom;
|
|
TextStyle get titleLarge;
|
|
String get titleMediumFamily;
|
|
bool get titleMediumIsCustom;
|
|
TextStyle get titleMedium;
|
|
String get titleSmallFamily;
|
|
bool get titleSmallIsCustom;
|
|
TextStyle get titleSmall;
|
|
String get labelLargeFamily;
|
|
bool get labelLargeIsCustom;
|
|
TextStyle get labelLarge;
|
|
String get labelMediumFamily;
|
|
bool get labelMediumIsCustom;
|
|
TextStyle get labelMedium;
|
|
String get labelSmallFamily;
|
|
bool get labelSmallIsCustom;
|
|
TextStyle get labelSmall;
|
|
String get bodyLargeFamily;
|
|
bool get bodyLargeIsCustom;
|
|
TextStyle get bodyLarge;
|
|
String get bodyMediumFamily;
|
|
bool get bodyMediumIsCustom;
|
|
TextStyle get bodyMedium;
|
|
String get bodySmallFamily;
|
|
bool get bodySmallIsCustom;
|
|
TextStyle get bodySmall;
|
|
}
|
|
|
|
class ThemeTypography extends Typography {
|
|
ThemeTypography(this.theme);
|
|
|
|
final AppTheme theme;
|
|
|
|
String get displayLargeFamily => 'Poppins';
|
|
bool get displayLargeIsCustom => false;
|
|
TextStyle get displayLarge => GoogleFonts.poppins(
|
|
color: theme.primaryText,
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 64.0,
|
|
);
|
|
String get displayMediumFamily => 'Poppins';
|
|
bool get displayMediumIsCustom => false;
|
|
TextStyle get displayMedium => GoogleFonts.poppins(
|
|
color: theme.primaryText,
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 44.0,
|
|
);
|
|
String get displaySmallFamily => 'Poppins';
|
|
bool get displaySmallIsCustom => false;
|
|
TextStyle get displaySmall => GoogleFonts.poppins(
|
|
color: theme.primaryText,
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 36.0,
|
|
);
|
|
String get headlineLargeFamily => 'Poppins';
|
|
bool get headlineLargeIsCustom => false;
|
|
TextStyle get headlineLarge => GoogleFonts.poppins(
|
|
color: theme.primaryText,
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 32.0,
|
|
);
|
|
String get headlineMediumFamily => 'Poppins';
|
|
bool get headlineMediumIsCustom => false;
|
|
TextStyle get headlineMedium => GoogleFonts.poppins(
|
|
color: theme.primaryText,
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 28.0,
|
|
);
|
|
String get headlineSmallFamily => 'Poppins';
|
|
bool get headlineSmallIsCustom => false;
|
|
TextStyle get headlineSmall => GoogleFonts.poppins(
|
|
color: theme.primaryText,
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 24.0,
|
|
);
|
|
String get titleLargeFamily => 'Poppins';
|
|
bool get titleLargeIsCustom => false;
|
|
TextStyle get titleLarge => GoogleFonts.poppins(
|
|
color: theme.primaryText,
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 20.0,
|
|
);
|
|
String get titleMediumFamily => 'Poppins';
|
|
bool get titleMediumIsCustom => false;
|
|
TextStyle get titleMedium => GoogleFonts.poppins(
|
|
color: theme.primaryText,
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 18.0,
|
|
);
|
|
String get titleSmallFamily => 'Poppins';
|
|
bool get titleSmallIsCustom => false;
|
|
TextStyle get titleSmall => GoogleFonts.poppins(
|
|
color: theme.primaryText,
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 16.0,
|
|
);
|
|
String get labelLargeFamily => 'Poppins';
|
|
bool get labelLargeIsCustom => false;
|
|
TextStyle get labelLarge => GoogleFonts.poppins(
|
|
color: theme.secondaryText,
|
|
fontWeight: FontWeight.normal,
|
|
fontSize: 16.0,
|
|
);
|
|
String get labelMediumFamily => 'Poppins';
|
|
bool get labelMediumIsCustom => false;
|
|
TextStyle get labelMedium => GoogleFonts.poppins(
|
|
color: theme.secondaryText,
|
|
fontWeight: FontWeight.normal,
|
|
fontSize: 14.0,
|
|
);
|
|
String get labelSmallFamily => 'Poppins';
|
|
bool get labelSmallIsCustom => false;
|
|
TextStyle get labelSmall => GoogleFonts.poppins(
|
|
color: theme.secondaryText,
|
|
fontWeight: FontWeight.normal,
|
|
fontSize: 12.0,
|
|
);
|
|
String get bodyLargeFamily => 'Poppins';
|
|
bool get bodyLargeIsCustom => false;
|
|
TextStyle get bodyLarge => GoogleFonts.poppins(
|
|
color: theme.primaryText,
|
|
fontWeight: FontWeight.normal,
|
|
fontSize: 16.0,
|
|
);
|
|
String get bodyMediumFamily => 'Poppins';
|
|
bool get bodyMediumIsCustom => false;
|
|
TextStyle get bodyMedium => GoogleFonts.poppins(
|
|
color: theme.primaryText,
|
|
fontWeight: FontWeight.normal,
|
|
fontSize: 14.0,
|
|
);
|
|
String get bodySmallFamily => 'Poppins';
|
|
bool get bodySmallIsCustom => false;
|
|
TextStyle get bodySmall => GoogleFonts.poppins(
|
|
color: theme.primaryText,
|
|
fontWeight: FontWeight.normal,
|
|
fontSize: 12.0,
|
|
);
|
|
}
|
|
|
|
class DarkModeTheme extends AppTheme {
|
|
@Deprecated('Use primary instead')
|
|
Color get primaryColor => primary;
|
|
@Deprecated('Use secondary instead')
|
|
Color get secondaryColor => secondary;
|
|
@Deprecated('Use tertiary instead')
|
|
Color get tertiaryColor => tertiary;
|
|
|
|
late Color primary = const Color(0xFF3D6BB2);
|
|
late Color secondary = const Color(0xFFB36600);
|
|
late Color tertiary = const Color(0xFFEE8B60);
|
|
late Color alternate = const Color(0xFF262D34);
|
|
late Color primaryText = const Color(0xFFFFFFFF);
|
|
late Color secondaryText = const Color(0xFF919191);
|
|
late Color primaryBackground = const Color(0xFF14181B);
|
|
late Color secondaryBackground = const Color(0xFF1D2428);
|
|
late Color accent1 = const Color(0xFF003EA2);
|
|
late Color accent2 = const Color(0xFFB36600);
|
|
late Color accent3 = const Color(0x4DEE8B60);
|
|
late Color accent4 = const Color(0xB2262D34);
|
|
late Color success = const Color(0xFF249689);
|
|
late Color warning = const Color(0xFFF9CF58);
|
|
late Color error = const Color(0xFFFF5963);
|
|
late Color info = const Color(0xFFFFFFFF);
|
|
|
|
late Color trueBlue = const Color(0xFF3D6BB2);
|
|
late Color orangePeel = const Color(0xFFF9A434);
|
|
late Color white = const Color(0xFFFFFFFF);
|
|
late Color columbiaBlue = const Color(0xFFC8D6E4);
|
|
late Color battleshipGray = const Color(0xFF919191);
|
|
late Color backgroundTransparent = const Color(0x91000000);
|
|
}
|
|
|
|
extension TextStyleHelper on TextStyle {
|
|
TextStyle override({
|
|
TextStyle? font,
|
|
String? fontFamily,
|
|
Color? color,
|
|
double? fontSize,
|
|
FontWeight? fontWeight,
|
|
double? letterSpacing,
|
|
FontStyle? fontStyle,
|
|
bool useGoogleFonts = false,
|
|
TextDecoration? decoration,
|
|
double? lineHeight,
|
|
List<Shadow>? shadows,
|
|
String? package,
|
|
}) {
|
|
if (useGoogleFonts && fontFamily != null) {
|
|
font = GoogleFonts.getFont(
|
|
fontFamily,
|
|
fontWeight: fontWeight ?? this.fontWeight,
|
|
fontStyle: fontStyle ?? this.fontStyle,
|
|
);
|
|
}
|
|
|
|
return font != null
|
|
? font.copyWith(
|
|
color: color ?? this.color,
|
|
fontSize: fontSize ?? this.fontSize,
|
|
letterSpacing: letterSpacing ?? this.letterSpacing,
|
|
fontWeight: fontWeight ?? this.fontWeight,
|
|
fontStyle: fontStyle ?? this.fontStyle,
|
|
decoration: decoration,
|
|
height: lineHeight,
|
|
shadows: shadows,
|
|
)
|
|
: copyWith(
|
|
fontFamily: fontFamily,
|
|
package: package,
|
|
color: color,
|
|
fontSize: fontSize,
|
|
letterSpacing: letterSpacing,
|
|
fontWeight: fontWeight,
|
|
fontStyle: fontStyle,
|
|
decoration: decoration,
|
|
height: lineHeight,
|
|
shadows: shadows,
|
|
);
|
|
}
|
|
}
|