break everything

This commit is contained in:
Christien Rioux 2023-12-26 20:26:54 -05:00
parent e898074387
commit 29210c89d2
121 changed files with 2892 additions and 2608 deletions

View file

@ -0,0 +1,552 @@
import 'package:flutter/material.dart';
import 'package:flutter_chat_ui/flutter_chat_ui.dart';
import 'package:radix_colors/radix_colors.dart';
import 'scale_color.dart';
import 'scale_scheme.dart';
enum RadixThemeColor {
scarlet, // tomato + red + violet
babydoll, // crimson + purple + pink
vapor, // pink + cyan + plum
gold, // yellow + amber + orange
garden, // grass + orange + brown
forest, // green + brown + amber
arctic, // sky + teal + violet
lapis, // blue + indigo + mint
eggplant, // violet + purple + indigo
lime, // lime + yellow + orange
grim, // mauve + slate + sage
}
enum _RadixBaseColor {
tomato,
red,
crimson,
pink,
plum,
purple,
violet,
indigo,
blue,
sky,
cyan,
teal,
mint,
green,
grass,
lime,
yellow,
amber,
orange,
brown,
}
RadixColor _radixGraySteps(
Brightness brightness, bool alpha, _RadixBaseColor baseColor) {
switch (baseColor) {
case _RadixBaseColor.tomato:
case _RadixBaseColor.red:
case _RadixBaseColor.crimson:
case _RadixBaseColor.pink:
case _RadixBaseColor.plum:
case _RadixBaseColor.purple:
case _RadixBaseColor.violet:
return alpha
? (brightness == Brightness.dark
? RadixColors.dark.mauveA
: RadixColors.mauveA)
: (brightness == Brightness.dark
? RadixColors.dark.mauve
: RadixColors.mauve);
case _RadixBaseColor.indigo:
case _RadixBaseColor.blue:
case _RadixBaseColor.sky:
case _RadixBaseColor.cyan:
return alpha
? (brightness == Brightness.dark
? RadixColors.dark.slateA
: RadixColors.slateA)
: (brightness == Brightness.dark
? RadixColors.dark.slate
: RadixColors.slate);
case _RadixBaseColor.teal:
case _RadixBaseColor.mint:
case _RadixBaseColor.green:
return alpha
? (brightness == Brightness.dark
? RadixColors.dark.sageA
: RadixColors.sageA)
: (brightness == Brightness.dark
? RadixColors.dark.sage
: RadixColors.sage);
case _RadixBaseColor.lime:
case _RadixBaseColor.grass:
return alpha
? (brightness == Brightness.dark
? RadixColors.dark.oliveA
: RadixColors.oliveA)
: (brightness == Brightness.dark
? RadixColors.dark.olive
: RadixColors.olive);
case _RadixBaseColor.yellow:
case _RadixBaseColor.amber:
case _RadixBaseColor.orange:
case _RadixBaseColor.brown:
return alpha
? (brightness == Brightness.dark
? RadixColors.dark.sandA
: RadixColors.sandA)
: (brightness == Brightness.dark
? RadixColors.dark.sand
: RadixColors.sand);
}
}
RadixColor _radixColorSteps(
Brightness brightness, bool alpha, _RadixBaseColor baseColor) {
switch (baseColor) {
case _RadixBaseColor.tomato:
return alpha
? (brightness == Brightness.dark
? RadixColors.dark.tomatoA
: RadixColors.tomatoA)
: (brightness == Brightness.dark
? RadixColors.dark.tomato
: RadixColors.tomato);
case _RadixBaseColor.red:
return alpha
? (brightness == Brightness.dark
? RadixColors.dark.redA
: RadixColors.redA)
: (brightness == Brightness.dark
? RadixColors.dark.red
: RadixColors.red);
case _RadixBaseColor.crimson:
return alpha
? (brightness == Brightness.dark
? RadixColors.dark.crimsonA
: RadixColors.crimsonA)
: (brightness == Brightness.dark
? RadixColors.dark.crimson
: RadixColors.crimson);
case _RadixBaseColor.pink:
return alpha
? (brightness == Brightness.dark
? RadixColors.dark.pinkA
: RadixColors.pinkA)
: (brightness == Brightness.dark
? RadixColors.dark.pink
: RadixColors.pink);
case _RadixBaseColor.plum:
return alpha
? (brightness == Brightness.dark
? RadixColors.dark.plumA
: RadixColors.plumA)
: (brightness == Brightness.dark
? RadixColors.dark.plum
: RadixColors.plum);
case _RadixBaseColor.purple:
return alpha
? (brightness == Brightness.dark
? RadixColors.dark.purpleA
: RadixColors.purpleA)
: (brightness == Brightness.dark
? RadixColors.dark.purple
: RadixColors.purple);
case _RadixBaseColor.violet:
return alpha
? (brightness == Brightness.dark
? RadixColors.dark.violetA
: RadixColors.violetA)
: (brightness == Brightness.dark
? RadixColors.dark.violet
: RadixColors.violet);
case _RadixBaseColor.indigo:
return alpha
? (brightness == Brightness.dark
? RadixColors.dark.indigoA
: RadixColors.indigoA)
: (brightness == Brightness.dark
? RadixColors.dark.indigo
: RadixColors.indigo);
case _RadixBaseColor.blue:
return alpha
? (brightness == Brightness.dark
? RadixColors.dark.blueA
: RadixColors.blueA)
: (brightness == Brightness.dark
? RadixColors.dark.blue
: RadixColors.blue);
case _RadixBaseColor.sky:
return alpha
? (brightness == Brightness.dark
? RadixColors.dark.skyA
: RadixColors.skyA)
: (brightness == Brightness.dark
? RadixColors.dark.sky
: RadixColors.sky);
case _RadixBaseColor.cyan:
return alpha
? (brightness == Brightness.dark
? RadixColors.dark.cyanA
: RadixColors.cyanA)
: (brightness == Brightness.dark
? RadixColors.dark.cyan
: RadixColors.cyan);
case _RadixBaseColor.teal:
return alpha
? (brightness == Brightness.dark
? RadixColors.dark.tealA
: RadixColors.tealA)
: (brightness == Brightness.dark
? RadixColors.dark.teal
: RadixColors.teal);
case _RadixBaseColor.mint:
return alpha
? (brightness == Brightness.dark
? RadixColors.dark.mintA
: RadixColors.mintA)
: (brightness == Brightness.dark
? RadixColors.dark.mint
: RadixColors.mint);
case _RadixBaseColor.green:
return alpha
? (brightness == Brightness.dark
? RadixColors.dark.greenA
: RadixColors.greenA)
: (brightness == Brightness.dark
? RadixColors.dark.green
: RadixColors.green);
case _RadixBaseColor.grass:
return alpha
? (brightness == Brightness.dark
? RadixColors.dark.grassA
: RadixColors.grassA)
: (brightness == Brightness.dark
? RadixColors.dark.grass
: RadixColors.grass);
case _RadixBaseColor.lime:
return alpha
? (brightness == Brightness.dark
? RadixColors.dark.limeA
: RadixColors.limeA)
: (brightness == Brightness.dark
? RadixColors.dark.lime
: RadixColors.lime);
case _RadixBaseColor.yellow:
return alpha
? (brightness == Brightness.dark
? RadixColors.dark.yellowA
: RadixColors.yellowA)
: (brightness == Brightness.dark
? RadixColors.dark.yellow
: RadixColors.yellow);
case _RadixBaseColor.amber:
return alpha
? (brightness == Brightness.dark
? RadixColors.dark.amberA
: RadixColors.amberA)
: (brightness == Brightness.dark
? RadixColors.dark.amber
: RadixColors.amber);
case _RadixBaseColor.orange:
return alpha
? (brightness == Brightness.dark
? RadixColors.dark.orangeA
: RadixColors.orangeA)
: (brightness == Brightness.dark
? RadixColors.dark.orange
: RadixColors.orange);
case _RadixBaseColor.brown:
return alpha
? (brightness == Brightness.dark
? RadixColors.dark.brownA
: RadixColors.brownA)
: (brightness == Brightness.dark
? RadixColors.dark.brown
: RadixColors.brown);
}
}
extension ToScaleColor on RadixColor {
ScaleColor toScale() => ScaleColor(
appBackground: step1,
subtleBackground: step2,
elementBackground: step3,
hoverElementBackground: step4,
activeElementBackground: step5,
subtleBorder: step6,
border: step7,
hoverBorder: step8,
background: step9,
hoverBackground: step10,
subtleText: step11,
text: step12,
);
}
class RadixScheme {
RadixScheme(
{required this.primaryScale,
required this.primaryAlphaScale,
required this.secondaryScale,
required this.tertiaryScale,
required this.grayScale,
required this.errorScale});
RadixColor primaryScale;
RadixColor primaryAlphaScale;
RadixColor secondaryScale;
RadixColor tertiaryScale;
RadixColor grayScale;
RadixColor errorScale;
ScaleScheme toScale() => ScaleScheme(
primaryScale: primaryScale.toScale(),
primaryAlphaScale: primaryAlphaScale.toScale(),
secondaryScale: secondaryScale.toScale(),
tertiaryScale: tertiaryScale.toScale(),
grayScale: grayScale.toScale(),
errorScale: errorScale.toScale(),
);
}
RadixScheme _radixScheme(Brightness brightness, RadixThemeColor themeColor) {
late RadixScheme radixScheme;
switch (themeColor) {
// tomato + red + violet
case RadixThemeColor.scarlet:
radixScheme = RadixScheme(
primaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.tomato),
primaryAlphaScale:
_radixColorSteps(brightness, true, _RadixBaseColor.tomato),
secondaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.red),
tertiaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.violet),
grayScale: _radixGraySteps(brightness, false, _RadixBaseColor.tomato),
errorScale:
_radixColorSteps(brightness, false, _RadixBaseColor.yellow));
// crimson + purple + pink
case RadixThemeColor.babydoll:
radixScheme = RadixScheme(
primaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.crimson),
primaryAlphaScale:
_radixColorSteps(brightness, true, _RadixBaseColor.crimson),
secondaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.purple),
tertiaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.pink),
grayScale:
_radixGraySteps(brightness, false, _RadixBaseColor.crimson),
errorScale:
_radixColorSteps(brightness, false, _RadixBaseColor.orange));
// pink + cyan + plum
case RadixThemeColor.vapor:
radixScheme = RadixScheme(
primaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.pink),
primaryAlphaScale:
_radixColorSteps(brightness, true, _RadixBaseColor.pink),
secondaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.cyan),
tertiaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.plum),
grayScale: _radixGraySteps(brightness, false, _RadixBaseColor.pink),
errorScale: _radixColorSteps(brightness, false, _RadixBaseColor.red));
// yellow + amber + orange
case RadixThemeColor.gold:
radixScheme = RadixScheme(
primaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.yellow),
primaryAlphaScale:
_radixColorSteps(brightness, true, _RadixBaseColor.yellow),
secondaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.amber),
tertiaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.orange),
grayScale: _radixGraySteps(brightness, false, _RadixBaseColor.yellow),
errorScale: _radixColorSteps(brightness, false, _RadixBaseColor.red));
// grass + orange + brown
case RadixThemeColor.garden:
radixScheme = RadixScheme(
primaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.grass),
primaryAlphaScale:
_radixColorSteps(brightness, true, _RadixBaseColor.grass),
secondaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.orange),
tertiaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.brown),
grayScale: _radixGraySteps(brightness, false, _RadixBaseColor.grass),
errorScale:
_radixColorSteps(brightness, false, _RadixBaseColor.tomato));
// green + brown + amber
case RadixThemeColor.forest:
radixScheme = RadixScheme(
primaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.green),
primaryAlphaScale:
_radixColorSteps(brightness, true, _RadixBaseColor.green),
secondaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.brown),
tertiaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.amber),
grayScale: _radixGraySteps(brightness, false, _RadixBaseColor.green),
errorScale:
_radixColorSteps(brightness, false, _RadixBaseColor.tomato));
// sky + teal + violet
case RadixThemeColor.arctic:
radixScheme = RadixScheme(
primaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.sky),
primaryAlphaScale:
_radixColorSteps(brightness, true, _RadixBaseColor.sky),
secondaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.teal),
tertiaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.violet),
grayScale: _radixGraySteps(brightness, false, _RadixBaseColor.sky),
errorScale:
_radixColorSteps(brightness, false, _RadixBaseColor.crimson));
// blue + indigo + mint
case RadixThemeColor.lapis:
radixScheme = RadixScheme(
primaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.blue),
primaryAlphaScale:
_radixColorSteps(brightness, true, _RadixBaseColor.blue),
secondaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.indigo),
tertiaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.mint),
grayScale: _radixGraySteps(brightness, false, _RadixBaseColor.blue),
errorScale:
_radixColorSteps(brightness, false, _RadixBaseColor.crimson));
// violet + purple + indigo
case RadixThemeColor.eggplant:
radixScheme = RadixScheme(
primaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.violet),
primaryAlphaScale:
_radixColorSteps(brightness, true, _RadixBaseColor.violet),
secondaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.purple),
tertiaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.indigo),
grayScale: _radixGraySteps(brightness, false, _RadixBaseColor.violet),
errorScale:
_radixColorSteps(brightness, false, _RadixBaseColor.crimson));
// lime + yellow + orange
case RadixThemeColor.lime:
radixScheme = RadixScheme(
primaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.lime),
primaryAlphaScale:
_radixColorSteps(brightness, true, _RadixBaseColor.lime),
secondaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.yellow),
tertiaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.orange),
grayScale: _radixGraySteps(brightness, false, _RadixBaseColor.lime),
errorScale: _radixColorSteps(brightness, false, _RadixBaseColor.red));
// mauve + slate + sage
case RadixThemeColor.grim:
radixScheme = RadixScheme(
primaryScale:
_radixGraySteps(brightness, false, _RadixBaseColor.tomato),
primaryAlphaScale:
_radixColorSteps(brightness, true, _RadixBaseColor.tomato),
secondaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.indigo),
tertiaryScale:
_radixColorSteps(brightness, false, _RadixBaseColor.teal),
grayScale: brightness == Brightness.dark
? RadixColors.dark.gray
: RadixColors.gray,
errorScale: _radixColorSteps(brightness, false, _RadixBaseColor.red));
}
return radixScheme;
}
ColorScheme _radixColorScheme(Brightness brightness, RadixScheme radix) =>
ColorScheme(
brightness: brightness,
primary: radix.primaryScale.step9,
onPrimary: radix.primaryScale.step12,
primaryContainer: radix.primaryScale.step4,
onPrimaryContainer: radix.primaryScale.step11,
secondary: radix.secondaryScale.step9,
onSecondary: radix.secondaryScale.step12,
secondaryContainer: radix.secondaryScale.step3,
onSecondaryContainer: radix.secondaryScale.step11,
tertiary: radix.tertiaryScale.step9,
onTertiary: radix.tertiaryScale.step12,
tertiaryContainer: radix.tertiaryScale.step3,
onTertiaryContainer: radix.tertiaryScale.step11,
error: radix.errorScale.step9,
onError: radix.errorScale.step12,
errorContainer: radix.errorScale.step3,
onErrorContainer: radix.errorScale.step11,
background: radix.grayScale.step1,
onBackground: radix.grayScale.step11,
surface: radix.primaryScale.step1,
onSurface: radix.primaryScale.step12,
surfaceVariant: radix.secondaryScale.step2,
onSurfaceVariant: radix.secondaryScale.step11,
outline: radix.primaryScale.step7,
outlineVariant: radix.primaryScale.step6,
shadow: RadixColors.dark.gray.step1,
scrim: radix.primaryScale.step9,
inverseSurface: radix.primaryScale.step11,
onInverseSurface: radix.primaryScale.step2,
inversePrimary: radix.primaryScale.step10,
surfaceTint: radix.primaryAlphaScale.step4,
);
ChatTheme makeChatTheme(ScaleScheme scale, TextTheme textTheme) =>
DefaultChatTheme(
primaryColor: scale.primaryScale.background,
secondaryColor: scale.secondaryScale.background,
backgroundColor: scale.grayScale.subtleBackground,
inputBackgroundColor: Colors.blue,
inputBorderRadius: BorderRadius.zero,
inputTextDecoration: InputDecoration(
filled: true,
fillColor: scale.primaryScale.elementBackground,
isDense: true,
contentPadding: const EdgeInsets.fromLTRB(8, 12, 8, 12),
border: const OutlineInputBorder(
borderSide: BorderSide.none,
borderRadius: BorderRadius.all(Radius.circular(16))),
),
inputContainerDecoration: BoxDecoration(color: scale.primaryScale.border),
inputPadding: const EdgeInsets.all(9),
inputTextColor: scale.primaryScale.text,
attachmentButtonIcon: const Icon(Icons.attach_file),
);
ThemeData radixGenerator(Brightness brightness, RadixThemeColor themeColor) {
final textTheme = (brightness == Brightness.light)
? Typography.blackCupertino
: Typography.whiteCupertino;
final radix = _radixScheme(brightness, themeColor);
final colorScheme = _radixColorScheme(brightness, radix);
final scaleScheme = radix.toScale();
final themeData = ThemeData.from(
colorScheme: colorScheme, textTheme: textTheme, useMaterial3: true);
return themeData.copyWith(
bottomSheetTheme: themeData.bottomSheetTheme.copyWith(
elevation: 0,
modalElevation: 0,
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(16))),
extensions: <ThemeExtension<dynamic>>[
scaleScheme,
]);
}

View file

@ -0,0 +1,91 @@
import 'dart:ui';
class ScaleColor {
ScaleColor({
required this.appBackground,
required this.subtleBackground,
required this.elementBackground,
required this.hoverElementBackground,
required this.activeElementBackground,
required this.subtleBorder,
required this.border,
required this.hoverBorder,
required this.background,
required this.hoverBackground,
required this.subtleText,
required this.text,
});
Color appBackground;
Color subtleBackground;
Color elementBackground;
Color hoverElementBackground;
Color activeElementBackground;
Color subtleBorder;
Color border;
Color hoverBorder;
Color background;
Color hoverBackground;
Color subtleText;
Color text;
ScaleColor copyWith(
{Color? appBackground,
Color? subtleBackground,
Color? elementBackground,
Color? hoverElementBackground,
Color? activeElementBackground,
Color? subtleBorder,
Color? border,
Color? hoverBorder,
Color? background,
Color? hoverBackground,
Color? subtleText,
Color? text}) =>
ScaleColor(
appBackground: appBackground ?? this.appBackground,
subtleBackground: subtleBackground ?? this.subtleBackground,
elementBackground: elementBackground ?? this.elementBackground,
hoverElementBackground:
hoverElementBackground ?? this.hoverElementBackground,
activeElementBackground:
activeElementBackground ?? this.activeElementBackground,
subtleBorder: subtleBorder ?? this.subtleBorder,
border: border ?? this.border,
hoverBorder: hoverBorder ?? this.hoverBorder,
background: background ?? this.background,
hoverBackground: hoverBackground ?? this.hoverBackground,
subtleText: subtleText ?? this.subtleText,
text: text ?? this.text,
);
// ignore: prefer_constructors_over_static_methods
static ScaleColor lerp(ScaleColor a, ScaleColor b, double t) => ScaleColor(
appBackground: Color.lerp(a.appBackground, b.appBackground, t) ??
const Color(0x00000000),
subtleBackground:
Color.lerp(a.subtleBackground, b.subtleBackground, t) ??
const Color(0x00000000),
elementBackground:
Color.lerp(a.elementBackground, b.elementBackground, t) ??
const Color(0x00000000),
hoverElementBackground:
Color.lerp(a.hoverElementBackground, b.hoverElementBackground, t) ??
const Color(0x00000000),
activeElementBackground: Color.lerp(
a.activeElementBackground, b.activeElementBackground, t) ??
const Color(0x00000000),
subtleBorder: Color.lerp(a.subtleBorder, b.subtleBorder, t) ??
const Color(0x00000000),
border: Color.lerp(a.border, b.border, t) ?? const Color(0x00000000),
hoverBorder: Color.lerp(a.hoverBorder, b.hoverBorder, t) ??
const Color(0x00000000),
background: Color.lerp(a.background, b.background, t) ??
const Color(0x00000000),
hoverBackground: Color.lerp(a.hoverBackground, b.hoverBackground, t) ??
const Color(0x00000000),
subtleText: Color.lerp(a.subtleText, b.subtleText, t) ??
const Color(0x00000000),
text: Color.lerp(a.text, b.text, t) ?? const Color(0x00000000),
);
}

View file

@ -0,0 +1,53 @@
import 'package:flutter/material.dart';
import 'scale_color.dart';
class ScaleScheme extends ThemeExtension<ScaleScheme> {
ScaleScheme(
{required this.primaryScale,
required this.primaryAlphaScale,
required this.secondaryScale,
required this.tertiaryScale,
required this.grayScale,
required this.errorScale});
final ScaleColor primaryScale;
final ScaleColor primaryAlphaScale;
final ScaleColor secondaryScale;
final ScaleColor tertiaryScale;
final ScaleColor grayScale;
final ScaleColor errorScale;
@override
ScaleScheme copyWith(
{ScaleColor? primaryScale,
ScaleColor? primaryAlphaScale,
ScaleColor? secondaryScale,
ScaleColor? tertiaryScale,
ScaleColor? grayScale,
ScaleColor? errorScale}) =>
ScaleScheme(
primaryScale: primaryScale ?? this.primaryScale,
primaryAlphaScale: primaryAlphaScale ?? this.primaryAlphaScale,
secondaryScale: secondaryScale ?? this.secondaryScale,
tertiaryScale: tertiaryScale ?? this.tertiaryScale,
grayScale: grayScale ?? this.grayScale,
errorScale: errorScale ?? this.errorScale,
);
@override
ScaleScheme lerp(ScaleScheme? other, double t) {
if (other is! ScaleScheme) {
return this;
}
return ScaleScheme(
primaryScale: ScaleColor.lerp(primaryScale, other.primaryScale, t),
primaryAlphaScale:
ScaleColor.lerp(primaryAlphaScale, other.primaryAlphaScale, t),
secondaryScale: ScaleColor.lerp(secondaryScale, other.secondaryScale, t),
tertiaryScale: ScaleColor.lerp(tertiaryScale, other.tertiaryScale, t),
grayScale: ScaleColor.lerp(grayScale, other.grayScale, t),
errorScale: ScaleColor.lerp(errorScale, other.errorScale, t),
);
}
}

3
lib/theme/theme.dart Normal file
View file

@ -0,0 +1,3 @@
export 'scale_scheme.dart';
export 'theme_preference.dart';
export 'theme_repository.dart';

View file

@ -0,0 +1,52 @@
import 'package:change_case/change_case.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'theme_preference.freezed.dart';
part 'theme_preference.g.dart';
// Theme supports light and dark mode, optionally selected by the
// operating system
enum BrightnessPreference {
system,
light,
dark;
factory BrightnessPreference.fromJson(dynamic j) =>
BrightnessPreference.values.byName((j as String).toCamelCase());
String toJson() => name.toPascalCase();
}
// Theme supports multiple color variants based on 'Radix'
enum ColorPreference {
// Radix Colors
scarlet,
babydoll,
vapor,
gold,
garden,
forest,
arctic,
lapis,
eggplant,
lime,
grim,
// Accessible Colors
contrast;
factory ColorPreference.fromJson(dynamic j) =>
ColorPreference.values.byName((j as String).toCamelCase());
String toJson() => name.toPascalCase();
}
@freezed
class ThemePreferences with _$ThemePreferences {
const factory ThemePreferences({
required BrightnessPreference brightnessPreference,
required ColorPreference colorPreference,
required double displayScale,
}) = _ThemePreferences;
factory ThemePreferences.fromJson(dynamic json) =>
_$ThemePreferencesFromJson(json as Map<String, dynamic>);
}

View file

@ -0,0 +1,201 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'theme_preference.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
ThemePreferences _$ThemePreferencesFromJson(Map<String, dynamic> json) {
return _ThemePreferences.fromJson(json);
}
/// @nodoc
mixin _$ThemePreferences {
BrightnessPreference get brightnessPreference =>
throw _privateConstructorUsedError;
ColorPreference get colorPreference => throw _privateConstructorUsedError;
double get displayScale => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$ThemePreferencesCopyWith<ThemePreferences> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $ThemePreferencesCopyWith<$Res> {
factory $ThemePreferencesCopyWith(
ThemePreferences value, $Res Function(ThemePreferences) then) =
_$ThemePreferencesCopyWithImpl<$Res, ThemePreferences>;
@useResult
$Res call(
{BrightnessPreference brightnessPreference,
ColorPreference colorPreference,
double displayScale});
}
/// @nodoc
class _$ThemePreferencesCopyWithImpl<$Res, $Val extends ThemePreferences>
implements $ThemePreferencesCopyWith<$Res> {
_$ThemePreferencesCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
@pragma('vm:prefer-inline')
@override
$Res call({
Object? brightnessPreference = null,
Object? colorPreference = null,
Object? displayScale = null,
}) {
return _then(_value.copyWith(
brightnessPreference: null == brightnessPreference
? _value.brightnessPreference
: brightnessPreference // ignore: cast_nullable_to_non_nullable
as BrightnessPreference,
colorPreference: null == colorPreference
? _value.colorPreference
: colorPreference // ignore: cast_nullable_to_non_nullable
as ColorPreference,
displayScale: null == displayScale
? _value.displayScale
: displayScale // ignore: cast_nullable_to_non_nullable
as double,
) as $Val);
}
}
/// @nodoc
abstract class _$$ThemePreferencesImplCopyWith<$Res>
implements $ThemePreferencesCopyWith<$Res> {
factory _$$ThemePreferencesImplCopyWith(_$ThemePreferencesImpl value,
$Res Function(_$ThemePreferencesImpl) then) =
__$$ThemePreferencesImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{BrightnessPreference brightnessPreference,
ColorPreference colorPreference,
double displayScale});
}
/// @nodoc
class __$$ThemePreferencesImplCopyWithImpl<$Res>
extends _$ThemePreferencesCopyWithImpl<$Res, _$ThemePreferencesImpl>
implements _$$ThemePreferencesImplCopyWith<$Res> {
__$$ThemePreferencesImplCopyWithImpl(_$ThemePreferencesImpl _value,
$Res Function(_$ThemePreferencesImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? brightnessPreference = null,
Object? colorPreference = null,
Object? displayScale = null,
}) {
return _then(_$ThemePreferencesImpl(
brightnessPreference: null == brightnessPreference
? _value.brightnessPreference
: brightnessPreference // ignore: cast_nullable_to_non_nullable
as BrightnessPreference,
colorPreference: null == colorPreference
? _value.colorPreference
: colorPreference // ignore: cast_nullable_to_non_nullable
as ColorPreference,
displayScale: null == displayScale
? _value.displayScale
: displayScale // ignore: cast_nullable_to_non_nullable
as double,
));
}
}
/// @nodoc
@JsonSerializable()
class _$ThemePreferencesImpl implements _ThemePreferences {
const _$ThemePreferencesImpl(
{required this.brightnessPreference,
required this.colorPreference,
required this.displayScale});
factory _$ThemePreferencesImpl.fromJson(Map<String, dynamic> json) =>
_$$ThemePreferencesImplFromJson(json);
@override
final BrightnessPreference brightnessPreference;
@override
final ColorPreference colorPreference;
@override
final double displayScale;
@override
String toString() {
return 'ThemePreferences(brightnessPreference: $brightnessPreference, colorPreference: $colorPreference, displayScale: $displayScale)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ThemePreferencesImpl &&
(identical(other.brightnessPreference, brightnessPreference) ||
other.brightnessPreference == brightnessPreference) &&
(identical(other.colorPreference, colorPreference) ||
other.colorPreference == colorPreference) &&
(identical(other.displayScale, displayScale) ||
other.displayScale == displayScale));
}
@JsonKey(ignore: true)
@override
int get hashCode => Object.hash(
runtimeType, brightnessPreference, colorPreference, displayScale);
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$ThemePreferencesImplCopyWith<_$ThemePreferencesImpl> get copyWith =>
__$$ThemePreferencesImplCopyWithImpl<_$ThemePreferencesImpl>(
this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$ThemePreferencesImplToJson(
this,
);
}
}
abstract class _ThemePreferences implements ThemePreferences {
const factory _ThemePreferences(
{required final BrightnessPreference brightnessPreference,
required final ColorPreference colorPreference,
required final double displayScale}) = _$ThemePreferencesImpl;
factory _ThemePreferences.fromJson(Map<String, dynamic> json) =
_$ThemePreferencesImpl.fromJson;
@override
BrightnessPreference get brightnessPreference;
@override
ColorPreference get colorPreference;
@override
double get displayScale;
@override
@JsonKey(ignore: true)
_$$ThemePreferencesImplCopyWith<_$ThemePreferencesImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View file

@ -0,0 +1,24 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'theme_preference.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$ThemePreferencesImpl _$$ThemePreferencesImplFromJson(
Map<String, dynamic> json) =>
_$ThemePreferencesImpl(
brightnessPreference:
BrightnessPreference.fromJson(json['brightness_preference']),
colorPreference: ColorPreference.fromJson(json['color_preference']),
displayScale: (json['display_scale'] as num).toDouble(),
);
Map<String, dynamic> _$$ThemePreferencesImplToJson(
_$ThemePreferencesImpl instance) =>
<String, dynamic>{
'brightness_preference': instance.brightnessPreference.toJson(),
'color_preference': instance.colorPreference.toJson(),
'display_scale': instance.displayScale,
};

View file

@ -0,0 +1,132 @@
// ignore_for_file: always_put_required_named_parameters_first
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'radix_generator.dart';
import 'theme_preference.dart';
////////////////////////////////////////////////////////////////////////
class ThemeRepository {
ThemeRepository._({required SharedPreferences sharedPreferences})
: _sharedPreferences = sharedPreferences,
_themePreferences = defaultThemePreferences;
final SharedPreferences _sharedPreferences;
ThemePreferences _themePreferences;
ThemeData? _cachedThemeData;
/// Singleton instance of ThemeRepository
static ThemeRepository? _instance;
static Future<ThemeRepository> get instance async {
if (_instance == null) {
final sharedPreferences = await SharedPreferences.getInstance();
final instance = ThemeRepository._(sharedPreferences: sharedPreferences);
await instance.load();
_instance = instance;
}
return _instance!;
}
static bool get isPlatformDark =>
WidgetsBinding.instance.platformDispatcher.platformBrightness ==
Brightness.dark;
/// Defaults
static ThemePreferences get defaultThemePreferences => const ThemePreferences(
colorPreference: ColorPreference.vapor,
brightnessPreference: BrightnessPreference.system,
displayScale: 1,
);
/// Get theme preferences
ThemePreferences get themePreferences => _themePreferences;
/// Set theme preferences
void setThemePreferences(ThemePreferences themePreferences) {
_themePreferences = themePreferences;
_cachedThemeData = null;
}
/// Load theme preferences from storage
Future<void> load() async {
final themePreferencesJson =
_sharedPreferences.getString('themePreferences');
ThemePreferences? newThemePreferences;
if (themePreferencesJson != null) {
try {
newThemePreferences =
ThemePreferences.fromJson(jsonDecode(themePreferencesJson));
// ignore: avoid_catches_without_on_clauses
} catch (_) {
// ignore
}
}
setThemePreferences(newThemePreferences ?? defaultThemePreferences);
}
/// Save theme preferences to storage
Future<void> save() async {
await _sharedPreferences.setString(
'themePreferences', jsonEncode(_themePreferences.toJson()));
}
/// Get material 'ThemeData' for existinb
ThemeData themeData() {
final cachedThemeData = _cachedThemeData;
if (cachedThemeData != null) {
return cachedThemeData;
}
late final Brightness brightness;
switch (_themePreferences.brightnessPreference) {
case BrightnessPreference.system:
if (isPlatformDark) {
brightness = Brightness.dark;
} else {
brightness = Brightness.light;
}
case BrightnessPreference.light:
brightness = Brightness.light;
case BrightnessPreference.dark:
brightness = Brightness.dark;
}
late final ThemeData themeData;
switch (_themePreferences.colorPreference) {
// Special cases
case ColorPreference.contrast:
// xxx do contrastGenerator
themeData = radixGenerator(brightness, RadixThemeColor.grim);
// Generate from Radix
case ColorPreference.scarlet:
themeData = radixGenerator(brightness, RadixThemeColor.scarlet);
case ColorPreference.babydoll:
themeData = radixGenerator(brightness, RadixThemeColor.babydoll);
case ColorPreference.vapor:
themeData = radixGenerator(brightness, RadixThemeColor.vapor);
case ColorPreference.gold:
themeData = radixGenerator(brightness, RadixThemeColor.gold);
case ColorPreference.garden:
themeData = radixGenerator(brightness, RadixThemeColor.garden);
case ColorPreference.forest:
themeData = radixGenerator(brightness, RadixThemeColor.forest);
case ColorPreference.arctic:
themeData = radixGenerator(brightness, RadixThemeColor.arctic);
case ColorPreference.lapis:
themeData = radixGenerator(brightness, RadixThemeColor.lapis);
case ColorPreference.eggplant:
themeData = radixGenerator(brightness, RadixThemeColor.eggplant);
case ColorPreference.lime:
themeData = radixGenerator(brightness, RadixThemeColor.lime);
case ColorPreference.grim:
themeData = radixGenerator(brightness, RadixThemeColor.grim);
}
_cachedThemeData = themeData;
return themeData;
}
}

View file

@ -0,0 +1,108 @@
// ignore_for_file: always_put_required_named_parameters_first
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../entities/preferences.dart';
import 'radix_generator.dart';
////////////////////////////////////////////////////////////////////////
class ThemeService {
ThemeService._();
static late SharedPreferences prefs;
static ThemeService? _instance;
static Future<ThemeService> get instance async {
if (_instance == null) {
prefs = await SharedPreferences.getInstance();
_instance = ThemeService._();
}
return _instance!;
}
static bool get isPlatformDark =>
WidgetsBinding.instance.platformDispatcher.platformBrightness ==
Brightness.dark;
ThemeData get initial {
final themePreferences = load();
return get(themePreferences);
}
ThemePreferences load() {
final themePreferencesJson = prefs.getString('themePreferences');
ThemePreferences? themePreferences;
if (themePreferencesJson != null) {
try {
themePreferences =
ThemePreferences.fromJson(jsonDecode(themePreferencesJson));
// ignore: avoid_catches_without_on_clauses
} catch (_) {
// ignore
}
}
return themePreferences ??
const ThemePreferences(
colorPreference: ColorPreference.vapor,
brightnessPreference: BrightnessPreference.system,
displayScale: 1,
);
}
Future<void> save(ThemePreferences themePreferences) async {
await prefs.setString(
'themePreferences', jsonEncode(themePreferences.toJson()));
}
ThemeData get(ThemePreferences themePreferences) {
late final Brightness brightness;
switch (themePreferences.brightnessPreference) {
case BrightnessPreference.system:
if (isPlatformDark) {
brightness = Brightness.dark;
} else {
brightness = Brightness.light;
}
case BrightnessPreference.light:
brightness = Brightness.light;
case BrightnessPreference.dark:
brightness = Brightness.dark;
}
late final ThemeData themeData;
switch (themePreferences.colorPreference) {
// Special cases
case ColorPreference.contrast:
// xxx do contrastGenerator
themeData = radixGenerator(brightness, RadixThemeColor.grim);
// Generate from Radix
case ColorPreference.scarlet:
themeData = radixGenerator(brightness, RadixThemeColor.scarlet);
case ColorPreference.babydoll:
themeData = radixGenerator(brightness, RadixThemeColor.babydoll);
case ColorPreference.vapor:
themeData = radixGenerator(brightness, RadixThemeColor.vapor);
case ColorPreference.gold:
themeData = radixGenerator(brightness, RadixThemeColor.gold);
case ColorPreference.garden:
themeData = radixGenerator(brightness, RadixThemeColor.garden);
case ColorPreference.forest:
themeData = radixGenerator(brightness, RadixThemeColor.forest);
case ColorPreference.arctic:
themeData = radixGenerator(brightness, RadixThemeColor.arctic);
case ColorPreference.lapis:
themeData = radixGenerator(brightness, RadixThemeColor.lapis);
case ColorPreference.eggplant:
themeData = radixGenerator(brightness, RadixThemeColor.eggplant);
case ColorPreference.lime:
themeData = radixGenerator(brightness, RadixThemeColor.lime);
case ColorPreference.grim:
themeData = radixGenerator(brightness, RadixThemeColor.grim);
}
return themeData;
}
}