瀏覽代碼

[FR] Create a new yellow theme for AppFlowy (#1539)

* feat: add dandelion color scheme

* feat: add dandelion to colorsheme

* feat: add setting for choosing theme

* refactor: make theme selection ui consistent

* refactor: remove duplicate  themeTypeLabel

* refactor: translate theme type setting

* refactor: use an extension method for themename

* refactor: change community theme name

* refactor: add theme name in app theme

* refactor: remove theme type from cubit

* refactor: allow theme change with themename

* test: getThemeNameForDisplaying method

* chore: refactor the theme name to const string

* refactor: remove theme translation logic

* fix: add translation for theme label

Co-authored-by: Lucas.Xu <[email protected]>
Mayur Mahajan 2 年之前
父節點
當前提交
b09f37e025

+ 3 - 2
frontend/app_flowy/assets/translations/en.json

@@ -165,7 +165,8 @@
         "light": "Light Mode",
         "dark": "Dark Mode",
         "system": "Adapt to System"
-      }
+      },
+      "theme":"Theme"
     },
     "files": {
       "defaultLocation": "Where your data is stored now",
@@ -173,7 +174,7 @@
       "restoreLocation": "Restore to AppFlowy default path",
       "customizeLocation": "Open another folder",
       "restartApp": "Please restart app for the changes to take effect.",
-      "exportDatabase": "Export databae",
+      "exportDatabase": "Export database",
       "selectFiles": "Select the files that need to be export",
       "createNewFolder": "Create a new folder",
       "createNewFolderDesc": "Tell us where you want to store your data ...",

+ 2 - 2
frontend/app_flowy/lib/workspace/application/appearance.dart

@@ -35,7 +35,7 @@ class AppearanceSettingsCubit extends Cubit<AppearanceSettingsState> {
   void setTheme(String themeName) {
     _setting.theme = themeName;
     _saveAppearanceSettings();
-    emit(state.copyWith(appTheme: AppTheme.fromName(themeName: themeName)));
+    emit(state.copyWith(appTheme: AppTheme.fromName(themeName)));
   }
 
   /// Update the theme mode in the user's settings and emit an updated state.
@@ -161,7 +161,7 @@ class AppearanceSettingsState with _$AppearanceSettingsState {
     LocaleSettingsPB localePB,
   ) {
     return AppearanceSettingsState(
-      appTheme: AppTheme.fromName(themeName: themeName),
+      appTheme: AppTheme.fromName(themeName),
       font: font,
       monospaceFont: monospaceFont,
       themeMode: _themeModeFromPB(themeModePB),

+ 61 - 0
frontend/app_flowy/lib/workspace/presentation/settings/widgets/settings_appearance_view.dart

@@ -3,6 +3,7 @@ import 'package:app_flowy/workspace/application/appearance.dart';
 import 'package:appflowy_popover/appflowy_popover.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/image.dart';
+import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flutter/material.dart';
@@ -20,6 +21,7 @@ class SettingsAppearanceView extends StatelessWidget {
             crossAxisAlignment: CrossAxisAlignment.start,
             children: [
               ThemeModeSetting(currentThemeMode: state.themeMode),
+              ThemeSetting(currentTheme: state.appTheme.themeName),
             ],
           );
         },
@@ -28,6 +30,65 @@ class SettingsAppearanceView extends StatelessWidget {
   }
 }
 
+class ThemeSetting extends StatelessWidget {
+  final String currentTheme;
+  const ThemeSetting({
+    super.key,
+    required this.currentTheme,
+  });
+
+  @override
+  Widget build(BuildContext context) {
+    return Row(
+      children: [
+        Expanded(
+          child: FlowyText.medium(
+            LocaleKeys.settings_appearance_theme.tr(),
+            overflow: TextOverflow.ellipsis,
+          ),
+        ),
+        AppFlowyPopover(
+          direction: PopoverDirection.bottomWithRightAligned,
+          child: FlowyTextButton(
+            currentTheme,
+            fillColor: Colors.transparent,
+            hoverColor: Theme.of(context).colorScheme.secondary,
+            onPressed: () {},
+          ),
+          popupBuilder: (BuildContext context) {
+            return IntrinsicWidth(
+              child: Column(
+                mainAxisSize: MainAxisSize.min,
+                children: [
+                  _themeItemButton(context, BuiltInTheme.light),
+                  _themeItemButton(context, BuiltInTheme.dandelion),
+                ],
+              ),
+            );
+          },
+        ),
+      ],
+    );
+  }
+
+  Widget _themeItemButton(BuildContext context, String theme) {
+    return SizedBox(
+      height: 32,
+      child: FlowyButton(
+        text: FlowyText.medium(theme),
+        rightIcon: currentTheme == theme
+            ? svgWidget("grid/checkmark")
+            : const SizedBox(),
+        onTap: () {
+          if (currentTheme != theme) {
+            context.read<AppearanceSettingsCubit>().setTheme(theme);
+          }
+        },
+      ),
+    );
+  }
+}
+
 class ThemeModeSetting extends StatelessWidget {
   final ThemeMode currentThemeMode;
   const ThemeModeSetting({required this.currentThemeMode, super.key});

+ 19 - 8
frontend/app_flowy/packages/flowy_infra/lib/colorscheme/colorscheme.dart

@@ -1,6 +1,23 @@
 import 'package:flutter/material.dart';
 
+import 'package:flowy_infra/theme.dart';
 import 'default_colorscheme.dart';
+import 'dandelion.dart';
+
+/// A map of all the built-in themes.
+///
+/// The key is the theme name, and the value is a list of two color schemes:
+/// the first is for light mode, and the second is for dark mode.
+const Map<String, List<FlowyColorScheme>> themeMap = {
+  BuiltInTheme.light: [
+    DefaultColorScheme.light(),
+    DefaultColorScheme.dark(),
+  ],
+  BuiltInTheme.dandelion: [
+    DandelionColorScheme.light(),
+    DandelionColorScheme.dark(),
+  ],
+};
 
 @immutable
 abstract class FlowyColorScheme {
@@ -69,15 +86,9 @@ abstract class FlowyColorScheme {
   factory FlowyColorScheme.builtIn(String themeName, Brightness brightness) {
     switch (brightness) {
       case Brightness.light:
-        return const DefaultColorScheme.light();
+        return themeMap[themeName]?[0] ?? const DefaultColorScheme.light();
       case Brightness.dark:
-        return const DefaultColorScheme.dark();
+        return themeMap[themeName]?[1] ?? 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/dandelion.dart

@@ -0,0 +1,74 @@
+import 'package:flutter/material.dart';
+
+import 'colorscheme.dart';
+
+const _black = Color(0xff000000);
+const _white = Color(0xFFFFFFFF);
+
+class DandelionColorScheme extends FlowyColorScheme {
+  const DandelionColorScheme.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(0xFFFFD13E),
+          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(0xffe21f74),
+          main2: const Color.fromARGB(255, 224, 25, 111),
+          shadow: _black,
+        );
+
+  const DandelionColorScheme.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: const Color(0xFFD5A200),
+          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(0xffe21f74),
+          main2: const Color.fromARGB(255, 224, 25, 111),
+          shadow: _black,
+        );
+}

+ 8 - 16
frontend/app_flowy/packages/flowy_infra/lib/theme.dart

@@ -1,35 +1,27 @@
 import 'package:flowy_infra/colorscheme/colorscheme.dart';
 import 'package:flutter/material.dart';
 
-const List<String> builtInThemes = [
-  'light',
-];
+class BuiltInTheme {
+  static const String light = 'light';
+  static const String dandelion = 'dandelion';
+}
 
 class AppTheme {
   // metadata member
+  final String themeName;
   final FlowyColorScheme lightTheme;
   final FlowyColorScheme darkTheme;
   // static final Map<String, dynamic> _cachedJsonData = {};
 
   const AppTheme({
+    required this.themeName,
     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),
-    //   );
-    // }
+  factory AppTheme.fromName(String themeName) {
     return AppTheme(
+      themeName: themeName,
       lightTheme: FlowyColorScheme.builtIn(themeName, Brightness.light),
       darkTheme: FlowyColorScheme.builtIn(themeName, Brightness.dark),
     );