Browse Source

refactor: appflowy themes (#1567)

* refactor: appflowy themes

* refactor: store ThemeData directly in cubit

* refactor: remove textStyles

* refactor: move AppTheme back into cubit
Richard Shiue 2 năm trước cách đây
mục cha
commit
60d9a6b3ab

+ 2 - 2
frontend/app_flowy/lib/startup/tasks/app_widget.dart

@@ -82,8 +82,8 @@ class ApplicationWidget extends StatelessWidget {
         builder: (context, state) => MaterialApp(
           builder: overlayManagerBuilder(),
           debugShowCheckedModeBanner: false,
-          theme: state.theme.getThemeData(state.locale),
-          darkTheme: state.darkTheme.getThemeData(state.locale),
+          theme: state.lightTheme,
+          darkTheme: state.darkTheme,
           themeMode: state.themeMode,
           localizationsDelegates: context.localizationDelegates +
               [AppFlowyEditorLocalizations.delegate],

+ 205 - 49
frontend/app_flowy/lib/workspace/application/appearance.dart

@@ -1,7 +1,9 @@
 import 'dart:async';
 
 import 'package:app_flowy/user/application/user_settings_service.dart';
+import 'package:flowy_infra/size.dart';
 import 'package:flowy_infra/theme.dart';
+import 'package:flowy_infra/theme_extension.dart';
 import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/protobuf/flowy-user/user_setting.pb.dart';
 import 'package:flutter/material.dart';
@@ -11,7 +13,10 @@ import 'package:freezed_annotation/freezed_annotation.dart';
 
 part 'appearance.freezed.dart';
 
-/// [AppearanceSettingsCubit] is used to modify the appear setting of AppFlowy application. Includes the [Locale] and [AppTheme].
+const _white = Color(0xFFFFFFFF);
+
+/// [AppearanceSettingsCubit] is used to modify the appearance of AppFlowy.
+/// It includes the [AppTheme], [ThemeMode], [TextStyles] and [Locale].
 class AppearanceSettingsCubit extends Cubit<AppearanceSettingsState> {
   final AppearanceSettingsPB _setting;
 
@@ -25,40 +30,23 @@ class AppearanceSettingsCubit extends Cubit<AppearanceSettingsState> {
           setting.locale,
         ));
 
-  /// Updates the current theme and notify the listeners the theme was changed.
-  /// Do nothing if the passed in themeType equal to the current theme type.
-  // void setTheme(Brightness brightness) {
-  //   if (state.theme.brightness == brightness) {
-  //     return;
-  //   }
-
-  //   _setting.theme = themeTypeToString(brightness);
-  //   _saveAppearanceSettings();
-
-  //   emit(state.copyWith(
-  //     theme: AppTheme.fromBrightness(
-  //       brightness: _setting.themeMode,
-  //       font: state.theme.font,
-  //       monospaceFont: state.theme.monospaceFont,
-  //     ),
-  //   ));
-  // }
-
-  /// Updates the current theme and notify the listeners the theme was changed.
-  /// Do nothing if the passed in themeType equal to the current theme type.
-  void setThemeMode(ThemeMode themeMode) {
-    if (state.themeMode == themeMode) {
-      return;
-    }
+  /// Update selected theme in the user's settings and emit an updated state
+  /// with the AppTheme named [themeName].
+  void setTheme(String themeName) {
+    _setting.theme = themeName;
+    _saveAppearanceSettings();
+    emit(state.copyWith(appTheme: AppTheme.fromName(themeName: themeName)));
+  }
 
+  /// Update the theme mode in the user's settings and emit an updated state.
+  void setThemeMode(ThemeMode themeMode) {
     _setting.themeMode = _themeModeToPB(themeMode);
     _saveAppearanceSettings();
-
     emit(state.copyWith(themeMode: themeMode));
   }
 
-  /// Updates the current locale and notify the listeners the locale was changed
-  /// Fallback to [en] locale If the newLocale is not supported.
+  /// Updates the current locale and notify the listeners the locale was
+  /// changed. Fallback to [en] locale if [newLocale] is not supported.
   void setLocale(BuildContext context, Locale newLocale) {
     if (!context.supportedLocales.contains(newLocale)) {
       Log.warn("Unsupported locale: $newLocale, Fallback to locale: en");
@@ -106,8 +94,8 @@ class AppearanceSettingsCubit extends Cubit<AppearanceSettingsState> {
     return _setting.settingKeyValue[key];
   }
 
-  /// Called when the application launch.
-  /// Uses the device locale when open the application for the first time
+  /// Called when the application launches.
+  /// Uses the device locale when the application is opened for the first time.
   void readLocaleWhenAppLaunch(BuildContext context) {
     if (_setting.resetToDefault) {
       _setting.resetToDefault = false;
@@ -155,32 +143,200 @@ ThemeModePB _themeModeToPB(ThemeMode themeMode) {
 
 @freezed
 class AppearanceSettingsState with _$AppearanceSettingsState {
+  const AppearanceSettingsState._();
+
   const factory AppearanceSettingsState({
-    required AppTheme theme,
-    required AppTheme darkTheme,
+    required AppTheme appTheme,
     required ThemeMode themeMode,
+    required String font,
+    required String monospaceFont,
     required Locale locale,
   }) = _AppearanceSettingsState;
 
   factory AppearanceSettingsState.initial(
     String themeName,
-    ThemeModePB themeMode,
+    ThemeModePB themeModePB,
     String font,
     String monospaceFont,
-    LocaleSettingsPB locale,
-  ) =>
-      AppearanceSettingsState(
-        theme: AppTheme.fromBrightness(
-          brightness: Brightness.light,
-          font: font,
-          monospaceFont: monospaceFont,
-        ),
-        darkTheme: AppTheme.fromBrightness(
-          brightness: Brightness.dark,
-          font: font,
-          monospaceFont: monospaceFont,
-        ),
-        themeMode: _themeModeFromPB(themeMode),
-        locale: Locale(locale.languageCode, locale.countryCode),
+    LocaleSettingsPB localePB,
+  ) {
+    return AppearanceSettingsState(
+      appTheme: AppTheme.fromName(themeName: themeName),
+      font: font,
+      monospaceFont: monospaceFont,
+      themeMode: _themeModeFromPB(themeModePB),
+      locale: Locale(localePB.languageCode, localePB.countryCode),
+    );
+  }
+
+  ThemeData get lightTheme => _getThemeData(Brightness.light);
+  ThemeData get darkTheme => _getThemeData(Brightness.dark);
+
+  ThemeData _getThemeData(Brightness brightness) {
+    // Poppins and SF Mono are not well supported in some languages, so use the
+    // built-in font for the following languages.
+    final useBuiltInFontLanguages = [
+      const Locale('zh', 'CN'),
+      const Locale('zh', 'TW'),
+    ];
+    String fontFamily = font;
+    String monospaceFontFamily = monospaceFont;
+    if (useBuiltInFontLanguages.contains(locale)) {
+      fontFamily = '';
+      monospaceFontFamily = '';
+    }
+
+    final theme = brightness == Brightness.light
+        ? appTheme.lightTheme
+        : appTheme.darkTheme;
+
+    return ThemeData(
+      brightness: brightness,
+      textTheme:
+          _getTextTheme(fontFamily: fontFamily, fontColor: theme.shader1),
+      textSelectionTheme: TextSelectionThemeData(
+        cursorColor: theme.main2,
+        selectionHandleColor: theme.main2,
+      ),
+      primaryIconTheme: IconThemeData(color: theme.hover),
+      iconTheme: IconThemeData(color: theme.shader1),
+      scrollbarTheme: ScrollbarThemeData(
+        thumbColor: MaterialStateProperty.all(Colors.transparent),
+      ),
+      materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
+      canvasColor: theme.shader6,
+      dividerColor: theme.shader6,
+      hintColor: theme.shader3,
+      disabledColor: theme.shader4,
+      highlightColor: theme.main1,
+      indicatorColor: theme.main1,
+      toggleableActiveColor: theme.main1,
+      colorScheme: ColorScheme(
+        brightness: brightness,
+        primary: theme.main1,
+        onPrimary: _white,
+        primaryContainer: theme.main2,
+        onPrimaryContainer: _white,
+        secondary: theme.hover,
+        onSecondary: theme.shader1,
+        secondaryContainer: theme.selector,
+        onSecondaryContainer: theme.shader1,
+        background: theme.surface,
+        onBackground: theme.shader1,
+        surface: theme.surface,
+        onSurface: theme.shader1,
+        onError: theme.shader7,
+        error: theme.red,
+        outline: theme.shader4,
+        surfaceVariant: theme.bg1,
+        shadow: theme.shadow,
+      ),
+      extensions: [
+        AFThemeExtension(
+          warning: theme.yellow,
+          success: theme.green,
+          tint1: theme.tint1,
+          tint2: theme.tint2,
+          tint3: theme.tint3,
+          tint4: theme.tint4,
+          tint5: theme.tint5,
+          tint6: theme.tint6,
+          tint7: theme.tint7,
+          tint8: theme.tint8,
+          tint9: theme.tint9,
+          greyHover: theme.bg2,
+          greySelect: theme.bg3,
+          lightGreyHover: theme.shader6,
+          toggleOffFill: theme.shader5,
+          code: _getFontStyle(
+            fontFamily: monospaceFontFamily,
+            fontColor: theme.shader3,
+          ),
+          callout: _getFontStyle(
+            fontFamily: fontFamily,
+            fontSize: FontSizes.s11,
+            fontColor: theme.shader3,
+          ),
+          caption: _getFontStyle(
+            fontFamily: fontFamily,
+            fontSize: FontSizes.s11,
+            fontWeight: FontWeight.w400,
+            fontColor: theme.shader3,
+          ),
+        )
+      ],
+    );
+  }
+
+  TextStyle _getFontStyle({
+    String? fontFamily,
+    double? fontSize,
+    FontWeight? fontWeight,
+    Color? fontColor,
+    double? letterSpacing,
+    double? lineHeight,
+  }) =>
+      TextStyle(
+        fontFamily: fontFamily,
+        fontSize: fontSize ?? FontSizes.s12,
+        color: fontColor,
+        fontWeight: fontWeight ?? FontWeight.w500,
+        fontFamilyFallback: const ["Noto Color Emoji"],
+        letterSpacing: (fontSize ?? FontSizes.s12) * (letterSpacing ?? 0.005),
+        height: lineHeight,
       );
+
+  TextTheme _getTextTheme(
+      {required String fontFamily, required Color fontColor}) {
+    return TextTheme(
+      displayLarge: _getFontStyle(
+        fontFamily: fontFamily,
+        fontSize: FontSizes.s32,
+        fontColor: fontColor,
+        fontWeight: FontWeight.w600,
+        lineHeight: 42.0,
+      ), // h2
+      displayMedium: _getFontStyle(
+        fontFamily: fontFamily,
+        fontSize: FontSizes.s24,
+        fontColor: fontColor,
+        fontWeight: FontWeight.w600,
+        lineHeight: 34.0,
+      ), // h3
+      displaySmall: _getFontStyle(
+        fontFamily: fontFamily,
+        fontSize: FontSizes.s20,
+        fontColor: fontColor,
+        fontWeight: FontWeight.w600,
+        lineHeight: 28.0,
+      ), // h4
+      titleLarge: _getFontStyle(
+        fontFamily: fontFamily,
+        fontSize: FontSizes.s18,
+        fontColor: fontColor,
+        fontWeight: FontWeight.w600,
+      ), // title
+      titleMedium: _getFontStyle(
+        fontFamily: fontFamily,
+        fontSize: FontSizes.s16,
+        fontColor: fontColor,
+        fontWeight: FontWeight.w600,
+      ), // heading
+      titleSmall: _getFontStyle(
+        fontFamily: fontFamily,
+        fontSize: FontSizes.s14,
+        fontColor: fontColor,
+        fontWeight: FontWeight.w600,
+      ), // subheading
+      bodyMedium: _getFontStyle(
+        fontFamily: fontFamily,
+        fontColor: fontColor,
+      ), // body-regular
+      bodySmall: _getFontStyle(
+        fontFamily: fontFamily,
+        fontColor: fontColor,
+        fontWeight: FontWeight.w400,
+      ), // body-thin
+    );
+  }
 }

+ 83 - 0
frontend/app_flowy/packages/flowy_infra/lib/colorscheme/colorscheme.dart

@@ -0,0 +1,83 @@
+import 'package:flutter/material.dart';
+
+import 'default_colorscheme.dart';
+
+@immutable
+abstract class FlowyColorScheme {
+  final Color surface;
+  final Color hover;
+  final Color selector;
+  final Color red;
+  final Color yellow;
+  final Color green;
+  final Color shader1;
+  final Color shader2;
+  final Color shader3;
+  final Color shader4;
+  final Color shader5;
+  final Color shader6;
+  final Color shader7;
+  final Color bg1;
+  final Color bg2;
+  final Color bg3;
+  final Color bg4;
+  final Color tint1;
+  final Color tint2;
+  final Color tint3;
+  final Color tint4;
+  final Color tint5;
+  final Color tint6;
+  final Color tint7;
+  final Color tint8;
+  final Color tint9;
+  final Color main1;
+  final Color main2;
+  final Color shadow;
+
+  const FlowyColorScheme({
+    required this.surface,
+    required this.hover,
+    required this.selector,
+    required this.red,
+    required this.yellow,
+    required this.green,
+    required this.shader1,
+    required this.shader2,
+    required this.shader3,
+    required this.shader4,
+    required this.shader5,
+    required this.shader6,
+    required this.shader7,
+    required this.bg1,
+    required this.bg2,
+    required this.bg3,
+    required this.bg4,
+    required this.tint1,
+    required this.tint2,
+    required this.tint3,
+    required this.tint4,
+    required this.tint5,
+    required this.tint6,
+    required this.tint7,
+    required this.tint8,
+    required this.tint9,
+    required this.main1,
+    required this.main2,
+    required this.shadow,
+  });
+
+  factory FlowyColorScheme.builtIn(String themeName, Brightness brightness) {
+    switch (brightness) {
+      case Brightness.light:
+        return const DefaultColorScheme.light();
+      case Brightness.dark:
+        return const DefaultColorScheme.dark();
+    }
+  }
+
+  // factory FlowyColorScheme.fromJson(Map<String, dynamic> json, Brightness brightness) {
+  //   // load Json
+
+  //   return FlowyColorScheme(brightness...);
+  // }
+}

+ 74 - 0
frontend/app_flowy/packages/flowy_infra/lib/colorscheme/default_colorscheme.dart

@@ -0,0 +1,74 @@
+import 'package:flutter/material.dart';
+
+import 'colorscheme.dart';
+
+const _black = Color(0xff000000);
+const _white = Color(0xFFFFFFFF);
+
+class DefaultColorScheme extends FlowyColorScheme {
+  const DefaultColorScheme.light()
+      : super(
+          surface: Colors.white,
+          hover: const Color(0xFFe0f8ff),
+          selector: const Color(0xfff2fcff),
+          red: const Color(0xfffb006d),
+          yellow: const Color(0xffffd667),
+          green: const Color(0xff66cf80),
+          shader1: const Color(0xff333333),
+          shader2: const Color(0xff4f4f4f),
+          shader3: const Color(0xff828282),
+          shader4: const Color(0xffbdbdbd),
+          shader5: const Color(0xffe0e0e0),
+          shader6: const Color(0xfff2f2f2),
+          shader7: const Color(0xffffffff),
+          bg1: const Color(0xfff7f8fc),
+          bg2: const Color(0xffedeef2),
+          bg3: const Color(0xffe2e4eb),
+          bg4: const Color(0xff2c144b),
+          tint1: const Color(0xffe8e0ff),
+          tint2: const Color(0xffffe7fd),
+          tint3: const Color(0xffffe7ee),
+          tint4: const Color(0xffffefe3),
+          tint5: const Color(0xfffff2cd),
+          tint6: const Color(0xfff5ffdc),
+          tint7: const Color(0xffddffd6),
+          tint8: const Color(0xffdefff1),
+          tint9: const Color(0xffe1fbff),
+          main1: const Color(0xff00bcf0),
+          main2: const Color(0xff00b7ea),
+          shadow: _black,
+        );
+
+  const DefaultColorScheme.dark()
+      : super(
+          surface: const Color(0xff292929),
+          hover: const Color(0xff1f1f1f),
+          selector: const Color(0xff333333),
+          red: const Color(0xfffb006d),
+          yellow: const Color(0xffffd667),
+          green: const Color(0xff66cf80),
+          shader1: _white,
+          shader2: const Color(0xffffffff),
+          shader3: const Color(0xff828282),
+          shader4: const Color(0xffbdbdbd),
+          shader5: _white,
+          shader6: _black,
+          shader7: _black,
+          bg1: _black,
+          bg2: _black,
+          bg3: const Color(0xff4f4f4f),
+          bg4: const Color(0xff2c144b),
+          tint1: const Color(0xffc3adff),
+          tint2: const Color(0xffffadf9),
+          tint3: const Color(0xffffadad),
+          tint4: const Color(0xffffcfad),
+          tint5: const Color(0xfffffead),
+          tint6: const Color(0xffe6ffa3),
+          tint7: const Color(0xffbcffad),
+          tint8: const Color(0xffadffe2),
+          tint9: const Color(0xffade4ff),
+          main1: const Color(0xff00bcf0),
+          main2: const Color(0xff009cc7),
+          shadow: _black,
+        );
+}

+ 0 - 64
frontend/app_flowy/packages/flowy_infra/lib/text_style.dart

@@ -1,64 +0,0 @@
-import 'package:flowy_infra/size.dart';
-import 'package:flutter/material.dart';
-
-class TextStyles {
-  final String font;
-  final Color color;
-
-  TextStyles({
-    required this.font,
-    required this.color,
-  });
-
-  TextStyle getFontStyle({
-    String? fontFamily,
-    double? fontSize,
-    FontWeight? fontWeight,
-    Color? fontColor,
-    double? letterSpacing,
-    double? lineHeight,
-  }) =>
-      TextStyle(
-        fontFamily: fontFamily ?? font,
-        fontSize: fontSize ?? FontSizes.s12,
-        color: fontColor ?? color,
-        fontWeight: fontWeight ?? FontWeight.w500,
-        fontFamilyFallback: const ["Noto Color Emoji"],
-        letterSpacing: (fontSize ?? FontSizes.s12) * (letterSpacing ?? 0.005),
-        height: lineHeight,
-      );
-
-  TextTheme generateTextTheme() {
-    return TextTheme(
-      displayLarge: getFontStyle(
-        fontSize: FontSizes.s32,
-        fontWeight: FontWeight.w600,
-        lineHeight: 42.0,
-      ), // h2
-      displayMedium: getFontStyle(
-        fontSize: FontSizes.s24,
-        fontWeight: FontWeight.w600,
-        lineHeight: 34.0,
-      ), // h3
-      displaySmall: getFontStyle(
-        fontSize: FontSizes.s20,
-        fontWeight: FontWeight.w600,
-        lineHeight: 28.0,
-      ), // h4
-      titleLarge: getFontStyle(
-        fontSize: FontSizes.s18,
-        fontWeight: FontWeight.w600,
-      ), // title
-      titleMedium: getFontStyle(
-        fontSize: FontSizes.s16,
-        fontWeight: FontWeight.w600,
-      ), // heading
-      titleSmall: getFontStyle(
-        fontSize: FontSizes.s14,
-        fontWeight: FontWeight.w600,
-      ), // subheading
-      bodyMedium: getFontStyle(), // body-regular
-      bodySmall: getFontStyle(fontWeight: FontWeight.w400), // body-thin
-    );
-  }
-}

+ 30 - 260
frontend/app_flowy/packages/flowy_infra/lib/theme.dart

@@ -1,267 +1,37 @@
-import 'package:flowy_infra/size.dart';
-import 'package:flowy_infra/text_style.dart';
+import 'package:flowy_infra/colorscheme/colorscheme.dart';
 import 'package:flutter/material.dart';
 
-import 'theme_extension.dart';
-
-Brightness themeTypeFromString(String name) {
-  Brightness themeType = Brightness.light;
-  if (name == "dark") {
-    themeType = Brightness.dark;
-  }
-  return themeType;
-}
-
-String themeTypeToString(Brightness brightness) {
-  switch (brightness) {
-    case Brightness.light:
-      return "light";
-    case Brightness.dark:
-      return "dark";
-  }
-}
-
-// Color Palettes
-const _black = Color(0xff000000);
-const _white = Color(0xFFFFFFFF);
+const List<String> builtInThemes = [
+  'light',
+];
 
 class AppTheme {
-  Brightness brightness;
-
-  late Color surface;
-  late Color hover;
-  late Color selector;
-  late Color red;
-  late Color yellow;
-  late Color green;
-
-  late Color shader1;
-  late Color shader2;
-  late Color shader3;
-  late Color shader4;
-  late Color shader5;
-  late Color shader6;
-  late Color shader7;
-
-  late Color bg1;
-  late Color bg2;
-  late Color bg3;
-  late Color bg4;
-
-  late Color tint1;
-  late Color tint2;
-  late Color tint3;
-  late Color tint4;
-  late Color tint5;
-  late Color tint6;
-  late Color tint7;
-  late Color tint8;
-  late Color tint9;
-
-  late Color textColor;
-  late Color iconColor;
-  late Color disableIconColor;
-
-  late Color main1;
-  late Color main2;
-
-  late Color shadow;
-
-  late String font;
-  late String monospaceFont;
-
-  /// Default constructor
-  AppTheme({this.brightness = Brightness.light});
-
-  factory AppTheme.fromBrightness({
-    required Brightness brightness,
-    required String font,
-    required String monospaceFont,
-  }) {
-    switch (brightness) {
-      case Brightness.light:
-        return AppTheme(brightness: Brightness.light)
-          ..surface = Colors.white
-          ..hover = const Color(0xFFe0f8ff)
-          ..selector = const Color(0xfff2fcff)
-          ..red = const Color(0xfffb006d)
-          ..yellow = const Color(0xffffd667)
-          ..green = const Color(0xff66cf80)
-          ..shader1 = const Color(0xff333333)
-          ..shader2 = const Color(0xff4f4f4f)
-          ..shader3 = const Color(0xff828282)
-          ..shader4 = const Color(0xffbdbdbd)
-          ..shader5 = const Color(0xffe0e0e0)
-          ..shader6 = const Color(0xfff2f2f2)
-          ..shader7 = const Color(0xffffffff)
-          ..bg1 = const Color(0xfff7f8fc)
-          ..bg2 = const Color(0xffedeef2)
-          ..bg3 = const Color(0xffe2e4eb)
-          ..bg4 = const Color(0xff2c144b)
-          ..tint1 = const Color(0xffe8e0ff)
-          ..tint2 = const Color(0xffffe7fd)
-          ..tint3 = const Color(0xffffe7ee)
-          ..tint4 = const Color(0xffffefe3)
-          ..tint5 = const Color(0xfffff2cd)
-          ..tint6 = const Color(0xfff5ffdc)
-          ..tint7 = const Color(0xffddffd6)
-          ..tint8 = const Color(0xffdefff1)
-          ..tint9 = const Color(0xffe1fbff)
-          ..main1 = const Color(0xff00bcf0)
-          ..main2 = const Color(0xff00b7ea)
-          ..textColor = _black
-          ..iconColor = _black
-          ..shadow = _black
-          ..disableIconColor = const Color(0xffbdbdbd)
-          ..font = font
-          ..monospaceFont = monospaceFont;
-
-      case Brightness.dark:
-        return AppTheme(brightness: Brightness.dark)
-          ..surface = const Color(0xff292929)
-          ..hover = const Color(0xff1f1f1f)
-          ..selector = const Color(0xff333333)
-          ..red = const Color(0xfffb006d)
-          ..yellow = const Color(0xffffd667)
-          ..green = const Color(0xff66cf80)
-          ..shader1 = _white
-          ..shader2 = const Color(0xffffffff)
-          ..shader3 = const Color(0xff828282)
-          ..shader4 = const Color(0xffbdbdbd)
-          ..shader5 = _white
-          ..shader6 = _black
-          ..shader7 = _black
-          ..bg1 = _black
-          ..bg2 = _black
-          ..bg3 = const Color(0xff4f4f4f)
-          ..bg4 = const Color(0xff2c144b)
-          ..tint1 = const Color(0xffc3adff)
-          ..tint2 = const Color(0xffffadf9)
-          ..tint3 = const Color(0xffffadad)
-          ..tint4 = const Color(0xffffcfad)
-          ..tint5 = const Color(0xfffffead)
-          ..tint6 = const Color(0xffe6ffa3)
-          ..tint7 = const Color(0xffbcffad)
-          ..tint8 = const Color(0xffadffe2)
-          ..tint9 = const Color(0xffade4ff)
-          ..main1 = const Color(0xff00bcf0)
-          ..main2 = const Color(0xff009cc7)
-          ..textColor = _white
-          ..iconColor = _white
-          ..shadow = _black
-          ..disableIconColor = const Color(0xff333333)
-          ..font = font
-          ..monospaceFont = monospaceFont;
-    }
-  }
-
-  ThemeData getThemeData(Locale locale) {
-    // Poppins and SF Mono are not well supported in some languages, so use the
-    // built-in font for the following languages.
-    final useBuiltInFontLanguages = [
-      const Locale('zh', 'CN'),
-      const Locale('zh', 'TW'),
-    ];
-    TextStyles textTheme;
-    if (useBuiltInFontLanguages.contains(locale)) {
-      textTheme = TextStyles(font: '', color: shader1);
-    } else {
-      textTheme = TextStyles(font: font, color: shader1);
-    }
-    return ThemeData(
-      brightness: brightness,
-      textTheme: textTheme.generateTextTheme(),
-      textSelectionTheme: TextSelectionThemeData(
-        cursorColor: main2,
-        selectionHandleColor: main2,
-      ),
-      primaryIconTheme: IconThemeData(color: hover),
-      iconTheme: IconThemeData(color: shader1),
-      scrollbarTheme: ScrollbarThemeData(
-        thumbColor: MaterialStateProperty.all(Colors.transparent),
-      ),
-      materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
-      canvasColor: shader6,
-      dividerColor: shader6,
-      hintColor: shader3,
-      disabledColor: shader4,
-      highlightColor: main1,
-      indicatorColor: main1,
-      toggleableActiveColor: main1,
-      colorScheme: ColorScheme(
-        brightness: brightness,
-        primary: main1,
-        onPrimary: _white,
-        primaryContainer: main2,
-        onPrimaryContainer: _white,
-        secondary: hover,
-        onSecondary: shader1,
-        secondaryContainer: selector,
-        onSecondaryContainer: shader1,
-        background: surface,
-        onBackground: shader1,
-        surface: surface,
-        onSurface: shader1,
-        onError: shader7,
-        error: red,
-        outline: shader4,
-        surfaceVariant: bg1,
-        shadow: shadow,
-      ),
-      extensions: [
-        AFThemeExtension(
-          warning: yellow,
-          success: green,
-          tint1: tint1,
-          tint2: tint2,
-          tint3: tint3,
-          tint4: tint4,
-          tint5: tint5,
-          tint6: tint6,
-          tint7: tint7,
-          tint8: tint8,
-          tint9: tint9,
-          greyHover: bg2,
-          greySelect: bg3,
-          lightGreyHover: shader6,
-          toggleOffFill: shader5,
-          code: textTheme.getFontStyle(fontFamily: monospaceFont),
-          callout: textTheme.getFontStyle(
-            fontSize: FontSizes.s11,
-            fontColor: shader3,
-          ),
-          caption: textTheme.getFontStyle(
-            fontSize: FontSizes.s11,
-            fontWeight: FontWeight.w400,
-            fontColor: shader3,
-          ),
-        )
-      ],
-    );
-  }
-
-  Color shift(Color c, double d) =>
-      ColorUtils.shiftHsl(c, d * (brightness == Brightness.dark ? -1 : 1));
-}
-
-class ColorUtils {
-  static Color shiftHsl(Color c, [double amt = 0]) {
-    var hslc = HSLColor.fromColor(c);
-    return hslc.withLightness((hslc.lightness + amt).clamp(0.0, 1.0)).toColor();
-  }
-
-  static Color parseHex(String value) =>
-      Color(int.parse(value.substring(1, 7), radix: 16) + 0xFF000000);
-
-  static Color blend(Color dst, Color src, double opacity) {
-    return Color.fromARGB(
-      255,
-      (dst.red.toDouble() * (1.0 - opacity) + src.red.toDouble() * opacity)
-          .toInt(),
-      (dst.green.toDouble() * (1.0 - opacity) + src.green.toDouble() * opacity)
-          .toInt(),
-      (dst.blue.toDouble() * (1.0 - opacity) + src.blue.toDouble() * opacity)
-          .toInt(),
+  // metadata member
+  final FlowyColorScheme lightTheme;
+  final FlowyColorScheme darkTheme;
+  // static final Map<String, dynamic> _cachedJsonData = {};
+
+  const AppTheme({
+    required this.lightTheme,
+    required this.darkTheme,
+  });
+
+  factory AppTheme.fromName({required String themeName}) {
+    // if (builtInThemes.contains(themeName)) {
+    //   return AppTheme(
+    //     lightTheme: FlowyColorScheme.builtIn(themeName, Brightness.light),
+    //     darkTheme: FlowyColorScheme.builtIn(themeName, Brightness.dark),
+    //   );
+    // } else {
+    //   // load from Json
+    //   return AppTheme(
+    //     lightTheme: FlowyColorScheme.fromJson(_jsonData, Brightness.light),
+    //     darkTheme: FlowyColorScheme.fromJson(_jsonData, Brightness.dark),
+    //   );
+    // }
+    return AppTheme(
+      lightTheme: FlowyColorScheme.builtIn(themeName, Brightness.light),
+      darkTheme: FlowyColorScheme.builtIn(themeName, Brightness.dark),
     );
   }
 }

+ 4 - 1
frontend/app_flowy/test/bloc_test/app_setting_test/appearance_test.dart

@@ -25,7 +25,10 @@ void main() {
       'default theme',
       build: () => AppearanceSettingsCubit(appearanceSetting),
       verify: (bloc) {
-        expect(bloc.state.theme.brightness, Brightness.light);
+        // expect(bloc.state.appTheme.info.name, "light");
+        expect(bloc.state.font, 'Poppins');
+        expect(bloc.state.monospaceFont, 'SF Mono');
+        expect(bloc.state.themeMode, ThemeMode.system);
       },
     );