mirror of
https://github.com/GopeedLab/gopeed.git
synced 2026-11-04 15:49:49 +00:00
364 lines
14 KiB
Dart
364 lines
14 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:shadcn_flutter/shadcn_flutter.dart' as shad;
|
|
|
|
import 'app_theme_color.dart';
|
|
|
|
class AppPalette extends ThemeExtension<AppPalette> {
|
|
const AppPalette({
|
|
required this.bg,
|
|
required this.railBg,
|
|
required this.sideBg,
|
|
required this.cardBg,
|
|
required this.cardHoverBg,
|
|
required this.surfaceSoft,
|
|
required this.inputBg,
|
|
required this.footerBg,
|
|
required this.border,
|
|
required this.textPrimary,
|
|
required this.textSecondary,
|
|
required this.textMuted,
|
|
required this.primaryActionBg,
|
|
required this.primaryActionForeground,
|
|
required this.primaryActionHoverBg,
|
|
required this.brand,
|
|
required this.brandForeground,
|
|
required this.brandSoft,
|
|
required this.brandTrack,
|
|
required this.brandProgress,
|
|
required this.accent,
|
|
required this.accentOn,
|
|
required this.error,
|
|
required this.success,
|
|
required this.toggleBg,
|
|
required this.toggleIcon,
|
|
required this.itemActiveBg,
|
|
required this.filterActiveBg,
|
|
required this.progressTrack,
|
|
required this.taskCardSelectedBorder,
|
|
required this.taskCardHoverBg,
|
|
required this.taskCardAction,
|
|
required this.taskCardProgressFill,
|
|
required this.taskCardIconBg,
|
|
required this.taskCardFailedIconBg,
|
|
required this.taskMeta,
|
|
required this.taskMetaSubtle,
|
|
required this.taskErrorMeta,
|
|
required this.searchHint,
|
|
required this.headerDivider,
|
|
required this.captionButtonHover,
|
|
required this.captionButtonCloseHover,
|
|
});
|
|
|
|
static const Color lightAccent = Color(0xFF79C476);
|
|
|
|
static const light = AppPalette(
|
|
bg: Color(0xFFF6F8F7),
|
|
railBg: Color(0xFFE8EEEA),
|
|
sideBg: Color(0xFFF0F4F1),
|
|
cardBg: Color(0xFFFFFFFF),
|
|
cardHoverBg: Color(0xFFF5F7F5),
|
|
surfaceSoft: Color(0xFFEDF0EE),
|
|
inputBg: Color(0xFFE7E8E9),
|
|
footerBg: Color(0xFFF3F4F5),
|
|
border: Color(0x66C0C9BA),
|
|
textPrimary: Color(0xFF191C1D),
|
|
textSecondary: Color(0xFF5F6368),
|
|
textMuted: Color(0xFF707A6D),
|
|
primaryActionBg: Color(0xFF191C1D),
|
|
primaryActionForeground: Color(0xFFFFFFFF),
|
|
primaryActionHoverBg: Color(0xFF303435),
|
|
brand: lightAccent,
|
|
brandForeground: Color(0xFFFFFFFF),
|
|
brandSoft: Color(0x1479C476),
|
|
brandTrack: Color(0x2679C476),
|
|
brandProgress: Color(0xFF79C476),
|
|
accent: Color(0xFFE7E8E9),
|
|
accentOn: Color(0xFFF4F7F6),
|
|
error: Color(0xFFBA1A1A),
|
|
success: Color(0xFF2E7D32),
|
|
toggleBg: Color(0xFFFFFFFF),
|
|
toggleIcon: Color(0xFF5F6368),
|
|
itemActiveBg: Color(0x0F191C1D),
|
|
filterActiveBg: Color(0x3379C476),
|
|
progressTrack: Color(0x33C0C9BA),
|
|
taskCardSelectedBorder: Color(0x24191C1D),
|
|
taskCardHoverBg: Color(0xFFEAF0EC),
|
|
taskCardAction: Color(0xFF5F6368),
|
|
taskCardProgressFill: Color(0xFF79C476),
|
|
taskCardIconBg: Color(0xFFF5F7F5),
|
|
taskCardFailedIconBg: Color(0x14BA1A1A),
|
|
taskMeta: Color(0xFF5F6368),
|
|
taskMetaSubtle: Color(0xFF707A6D),
|
|
taskErrorMeta: Color(0xCCBA1A1A),
|
|
searchHint: Color(0xFF707A6D),
|
|
headerDivider: Color(0xA3C0C9BA),
|
|
captionButtonHover: Color(0x0F191C1D),
|
|
captionButtonCloseHover: Color(0xFFE81123),
|
|
);
|
|
|
|
static final dark = AppPalette(
|
|
bg: const Color(0xFF09090B),
|
|
railBg: Colors.black,
|
|
sideBg: const Color(0xFF111111),
|
|
cardBg: const Color(0xFF0F0F11),
|
|
cardHoverBg: const Color(0xFF121215),
|
|
surfaceSoft: const Color(0xFF1F1F24),
|
|
inputBg: const Color(0xFF111111),
|
|
footerBg: Colors.black.withValues(alpha: 0.2),
|
|
border: const Color(0xFF1B1B1D),
|
|
textPrimary: const Color(0xFFFFFFFF),
|
|
textSecondary: const Color(0xFFA1A1AA),
|
|
textMuted: const Color(0xFF71717A),
|
|
primaryActionBg: const Color(0xFFFAFAFA),
|
|
primaryActionForeground: const Color(0xFF18181B),
|
|
primaryActionHoverBg: const Color(0xFFE4E4E7),
|
|
brand: const Color(0xFFA7F5A2),
|
|
brandForeground: const Color(0xFF07310B),
|
|
brandSoft: const Color(0x1AA7F5A2),
|
|
brandTrack: const Color(0x2CA7F5A2),
|
|
brandProgress: const Color(0xFFA7F5A2),
|
|
accent: const Color(0xFF111111),
|
|
accentOn: const Color(0xFF09090B),
|
|
error: const Color(0xFFFFB4AB),
|
|
success: const Color(0xFF81C784),
|
|
toggleBg: Colors.white.withValues(alpha: 0.08),
|
|
toggleIcon: const Color(0xFFA1A1AA),
|
|
itemActiveBg: Colors.white.withValues(alpha: 0.08),
|
|
filterActiveBg: const Color(0x3DA7F5A2),
|
|
progressTrack: const Color(0xFF272729),
|
|
taskCardSelectedBorder: const Color(0xFF3F3F41),
|
|
taskCardHoverBg: const Color(0xFF171719),
|
|
taskCardAction: const Color(0xFFC6C6C6),
|
|
taskCardProgressFill: const Color(0xFFA7F5A2),
|
|
taskCardIconBg: const Color(0xFF1B1B1E),
|
|
taskCardFailedIconBg: const Color(0xFF272020),
|
|
taskMeta: const Color(0xFF8F8F90),
|
|
taskMetaSubtle: const Color(0xFF6B6B6C),
|
|
taskErrorMeta: const Color(0xFFCF938C),
|
|
searchHint: const Color(0xFF52525B),
|
|
headerDivider: const Color(0x1AFFFFFF),
|
|
captionButtonHover: const Color(0x0DFFFFFF),
|
|
captionButtonCloseHover: const Color(0xFFE81123),
|
|
);
|
|
|
|
static AppPalette lightFor(AppThemeColor themeColor) {
|
|
if (themeColor == AppThemeColor.green) return light;
|
|
return _withThemeColor(light, color: themeColor.light, foreground: themeColor.lightForeground, dark: false);
|
|
}
|
|
|
|
static AppPalette darkFor(AppThemeColor themeColor) {
|
|
if (themeColor == AppThemeColor.green) return dark;
|
|
return _withThemeColor(dark, color: themeColor.dark, foreground: themeColor.darkForeground, dark: true);
|
|
}
|
|
|
|
static AppPalette _withThemeColor(
|
|
AppPalette palette, {
|
|
required Color color,
|
|
required Color foreground,
|
|
required bool dark,
|
|
}) {
|
|
return palette.copyWith(
|
|
brand: color,
|
|
brandForeground: foreground,
|
|
brandSoft: color.withValues(alpha: dark ? 0.10 : 0.08),
|
|
brandTrack: color.withValues(alpha: dark ? 0.17 : 0.15),
|
|
brandProgress: color,
|
|
filterActiveBg: color.withValues(alpha: dark ? 0.24 : 0.20),
|
|
taskCardProgressFill: color,
|
|
);
|
|
}
|
|
|
|
final Color bg;
|
|
final Color railBg;
|
|
final Color sideBg;
|
|
final Color cardBg;
|
|
final Color cardHoverBg;
|
|
final Color surfaceSoft;
|
|
final Color inputBg;
|
|
final Color footerBg;
|
|
final Color border;
|
|
final Color textPrimary;
|
|
final Color textSecondary;
|
|
final Color textMuted;
|
|
final Color primaryActionBg;
|
|
final Color primaryActionForeground;
|
|
final Color primaryActionHoverBg;
|
|
final Color brand;
|
|
final Color brandForeground;
|
|
final Color brandSoft;
|
|
final Color brandTrack;
|
|
final Color brandProgress;
|
|
final Color accent;
|
|
final Color accentOn;
|
|
final Color error;
|
|
final Color success;
|
|
final Color toggleBg;
|
|
final Color toggleIcon;
|
|
final Color itemActiveBg;
|
|
final Color filterActiveBg;
|
|
final Color progressTrack;
|
|
final Color taskCardSelectedBorder;
|
|
final Color taskCardHoverBg;
|
|
final Color taskCardAction;
|
|
final Color taskCardProgressFill;
|
|
final Color taskCardIconBg;
|
|
final Color taskCardFailedIconBg;
|
|
final Color taskMeta;
|
|
final Color taskMetaSubtle;
|
|
final Color taskErrorMeta;
|
|
final Color searchHint;
|
|
final Color headerDivider;
|
|
final Color captionButtonHover;
|
|
final Color captionButtonCloseHover;
|
|
|
|
static AppPalette of(BuildContext context) {
|
|
final extension = Theme.of(context).extension<AppPalette>();
|
|
if (extension != null) {
|
|
return extension;
|
|
}
|
|
return shad.Theme.of(context).brightness == Brightness.light ? light : dark;
|
|
}
|
|
|
|
@override
|
|
AppPalette copyWith({
|
|
Color? bg,
|
|
Color? railBg,
|
|
Color? sideBg,
|
|
Color? cardBg,
|
|
Color? cardHoverBg,
|
|
Color? surfaceSoft,
|
|
Color? inputBg,
|
|
Color? footerBg,
|
|
Color? border,
|
|
Color? textPrimary,
|
|
Color? textSecondary,
|
|
Color? textMuted,
|
|
Color? primaryActionBg,
|
|
Color? primaryActionForeground,
|
|
Color? primaryActionHoverBg,
|
|
Color? brand,
|
|
Color? brandForeground,
|
|
Color? brandSoft,
|
|
Color? brandTrack,
|
|
Color? brandProgress,
|
|
Color? accent,
|
|
Color? accentOn,
|
|
Color? error,
|
|
Color? success,
|
|
Color? toggleBg,
|
|
Color? toggleIcon,
|
|
Color? itemActiveBg,
|
|
Color? filterActiveBg,
|
|
Color? progressTrack,
|
|
Color? taskCardSelectedBorder,
|
|
Color? taskCardHoverBg,
|
|
Color? taskCardAction,
|
|
Color? taskCardProgressFill,
|
|
Color? taskCardIconBg,
|
|
Color? taskCardFailedIconBg,
|
|
Color? taskMeta,
|
|
Color? taskMetaSubtle,
|
|
Color? taskErrorMeta,
|
|
Color? searchHint,
|
|
Color? headerDivider,
|
|
Color? captionButtonHover,
|
|
Color? captionButtonCloseHover,
|
|
}) {
|
|
return AppPalette(
|
|
bg: bg ?? this.bg,
|
|
railBg: railBg ?? this.railBg,
|
|
sideBg: sideBg ?? this.sideBg,
|
|
cardBg: cardBg ?? this.cardBg,
|
|
cardHoverBg: cardHoverBg ?? this.cardHoverBg,
|
|
surfaceSoft: surfaceSoft ?? this.surfaceSoft,
|
|
inputBg: inputBg ?? this.inputBg,
|
|
footerBg: footerBg ?? this.footerBg,
|
|
border: border ?? this.border,
|
|
textPrimary: textPrimary ?? this.textPrimary,
|
|
textSecondary: textSecondary ?? this.textSecondary,
|
|
textMuted: textMuted ?? this.textMuted,
|
|
primaryActionBg: primaryActionBg ?? this.primaryActionBg,
|
|
primaryActionForeground: primaryActionForeground ?? this.primaryActionForeground,
|
|
primaryActionHoverBg: primaryActionHoverBg ?? this.primaryActionHoverBg,
|
|
brand: brand ?? this.brand,
|
|
brandForeground: brandForeground ?? this.brandForeground,
|
|
brandSoft: brandSoft ?? this.brandSoft,
|
|
brandTrack: brandTrack ?? this.brandTrack,
|
|
brandProgress: brandProgress ?? this.brandProgress,
|
|
accent: accent ?? this.accent,
|
|
accentOn: accentOn ?? this.accentOn,
|
|
error: error ?? this.error,
|
|
success: success ?? this.success,
|
|
toggleBg: toggleBg ?? this.toggleBg,
|
|
toggleIcon: toggleIcon ?? this.toggleIcon,
|
|
itemActiveBg: itemActiveBg ?? this.itemActiveBg,
|
|
filterActiveBg: filterActiveBg ?? this.filterActiveBg,
|
|
progressTrack: progressTrack ?? this.progressTrack,
|
|
taskCardSelectedBorder: taskCardSelectedBorder ?? this.taskCardSelectedBorder,
|
|
taskCardHoverBg: taskCardHoverBg ?? this.taskCardHoverBg,
|
|
taskCardAction: taskCardAction ?? this.taskCardAction,
|
|
taskCardProgressFill: taskCardProgressFill ?? this.taskCardProgressFill,
|
|
taskCardIconBg: taskCardIconBg ?? this.taskCardIconBg,
|
|
taskCardFailedIconBg: taskCardFailedIconBg ?? this.taskCardFailedIconBg,
|
|
taskMeta: taskMeta ?? this.taskMeta,
|
|
taskMetaSubtle: taskMetaSubtle ?? this.taskMetaSubtle,
|
|
taskErrorMeta: taskErrorMeta ?? this.taskErrorMeta,
|
|
searchHint: searchHint ?? this.searchHint,
|
|
headerDivider: headerDivider ?? this.headerDivider,
|
|
captionButtonHover: captionButtonHover ?? this.captionButtonHover,
|
|
captionButtonCloseHover: captionButtonCloseHover ?? this.captionButtonCloseHover,
|
|
);
|
|
}
|
|
|
|
@override
|
|
AppPalette lerp(ThemeExtension<AppPalette>? other, double t) {
|
|
if (other is! AppPalette) {
|
|
return this;
|
|
}
|
|
return AppPalette(
|
|
bg: Color.lerp(bg, other.bg, t)!,
|
|
railBg: Color.lerp(railBg, other.railBg, t)!,
|
|
sideBg: Color.lerp(sideBg, other.sideBg, t)!,
|
|
cardBg: Color.lerp(cardBg, other.cardBg, t)!,
|
|
cardHoverBg: Color.lerp(cardHoverBg, other.cardHoverBg, t)!,
|
|
surfaceSoft: Color.lerp(surfaceSoft, other.surfaceSoft, t)!,
|
|
inputBg: Color.lerp(inputBg, other.inputBg, t)!,
|
|
footerBg: Color.lerp(footerBg, other.footerBg, t)!,
|
|
border: Color.lerp(border, other.border, t)!,
|
|
textPrimary: Color.lerp(textPrimary, other.textPrimary, t)!,
|
|
textSecondary: Color.lerp(textSecondary, other.textSecondary, t)!,
|
|
textMuted: Color.lerp(textMuted, other.textMuted, t)!,
|
|
primaryActionBg: Color.lerp(primaryActionBg, other.primaryActionBg, t)!,
|
|
primaryActionForeground: Color.lerp(primaryActionForeground, other.primaryActionForeground, t)!,
|
|
primaryActionHoverBg: Color.lerp(primaryActionHoverBg, other.primaryActionHoverBg, t)!,
|
|
brand: Color.lerp(brand, other.brand, t)!,
|
|
brandForeground: Color.lerp(brandForeground, other.brandForeground, t)!,
|
|
brandSoft: Color.lerp(brandSoft, other.brandSoft, t)!,
|
|
brandTrack: Color.lerp(brandTrack, other.brandTrack, t)!,
|
|
brandProgress: Color.lerp(brandProgress, other.brandProgress, t)!,
|
|
accent: Color.lerp(accent, other.accent, t)!,
|
|
accentOn: Color.lerp(accentOn, other.accentOn, t)!,
|
|
error: Color.lerp(error, other.error, t)!,
|
|
success: Color.lerp(success, other.success, t)!,
|
|
toggleBg: Color.lerp(toggleBg, other.toggleBg, t)!,
|
|
toggleIcon: Color.lerp(toggleIcon, other.toggleIcon, t)!,
|
|
itemActiveBg: Color.lerp(itemActiveBg, other.itemActiveBg, t)!,
|
|
filterActiveBg: Color.lerp(filterActiveBg, other.filterActiveBg, t)!,
|
|
progressTrack: Color.lerp(progressTrack, other.progressTrack, t)!,
|
|
taskCardSelectedBorder: Color.lerp(taskCardSelectedBorder, other.taskCardSelectedBorder, t)!,
|
|
taskCardHoverBg: Color.lerp(taskCardHoverBg, other.taskCardHoverBg, t)!,
|
|
taskCardAction: Color.lerp(taskCardAction, other.taskCardAction, t)!,
|
|
taskCardProgressFill: Color.lerp(taskCardProgressFill, other.taskCardProgressFill, t)!,
|
|
taskCardIconBg: Color.lerp(taskCardIconBg, other.taskCardIconBg, t)!,
|
|
taskCardFailedIconBg: Color.lerp(taskCardFailedIconBg, other.taskCardFailedIconBg, t)!,
|
|
taskMeta: Color.lerp(taskMeta, other.taskMeta, t)!,
|
|
taskMetaSubtle: Color.lerp(taskMetaSubtle, other.taskMetaSubtle, t)!,
|
|
taskErrorMeta: Color.lerp(taskErrorMeta, other.taskErrorMeta, t)!,
|
|
searchHint: Color.lerp(searchHint, other.searchHint, t)!,
|
|
headerDivider: Color.lerp(headerDivider, other.headerDivider, t)!,
|
|
captionButtonHover: Color.lerp(captionButtonHover, other.captionButtonHover, t)!,
|
|
captionButtonCloseHover: Color.lerp(captionButtonCloseHover, other.captionButtonCloseHover, t)!,
|
|
);
|
|
}
|
|
}
|