From 5488a8ea828aed0a4ae7365eefea96418020d859 Mon Sep 17 00:00:00 2001 From: jialin Date: Wed, 14 May 2025 20:12:14 +0800 Subject: [PATCH] fix: system theme --- src/atoms/settings.ts | 4 +- src/hooks/use-user-settings.ts | 46 ++++++++------ src/locales/en-US/common.ts | 3 +- src/locales/en-US/models.ts | 5 +- src/locales/ja-JP/common.ts | 4 +- src/locales/ja-JP/models.ts | 13 ++-- src/locales/ru-RU/common.ts | 8 ++- src/locales/ru-RU/models.ts | 7 ++- src/locales/zh-CN/common.ts | 3 +- src/locales/zh-CN/models.ts | 5 +- src/pages/llmodels/components/ollama-tips.tsx | 29 +-------- .../components/multiple-chat/message-body.tsx | 2 - src/pages/profile/components/appearance.tsx | 61 +++++++++++-------- 13 files changed, 97 insertions(+), 93 deletions(-) diff --git a/src/atoms/settings.ts b/src/atoms/settings.ts index e80f0759..3e0e581a 100644 --- a/src/atoms/settings.ts +++ b/src/atoms/settings.ts @@ -3,13 +3,15 @@ import { atom } from 'jotai'; import { atomWithStorage } from 'jotai/utils'; type UserSettings = { - theme: 'light' | 'realDark' | 'auto'; + theme: 'light' | 'realDark'; + mode: 'light' | 'realDark' | 'auto'; colorPrimary: string; isDarkTheme: boolean; }; export const userSettingsAtom = atomWithStorage('userSettings', { theme: 'light', + mode: 'auto', isDarkTheme: false, colorPrimary: colorPrimary }); diff --git a/src/hooks/use-user-settings.ts b/src/hooks/use-user-settings.ts index 09384fe1..f9c6b842 100644 --- a/src/hooks/use-user-settings.ts +++ b/src/hooks/use-user-settings.ts @@ -9,6 +9,15 @@ export default function useUserSettings() { const { light, dark, colorPrimary } = themeConfig; const [userSettings, setUserSettings] = useAtom(userSettingsHelperAtom); + const getCurrentTheme = (mode: Theme): 'light' | 'realDark' => { + if (mode === 'auto') { + return window.matchMedia('(prefers-color-scheme: dark)').matches + ? 'realDark' + : 'light'; + } + return mode; + }; + const setHtmlThemeAttr = (theme: string) => { const html = document.querySelector('html'); if (html) { @@ -17,39 +26,42 @@ export default function useUserSettings() { }; const themeData = useMemo(() => { - const themeTokens = userSettings.theme === 'realDark' ? dark : light; - themeTokens.token.colorPrimary = userSettings.colorPrimary || colorPrimary; + const baseTokens = userSettings.theme === 'realDark' ? dark : light; return { - ...themeTokens + ...baseTokens, + token: { + ...baseTokens.token, + colorPrimary: userSettings.colorPrimary || colorPrimary + } }; }, [userSettings.theme, userSettings.colorPrimary]); - const setTheme = (theme: Theme) => { - setHtmlThemeAttr(theme); + const setTheme = (mode: Theme) => { + const currentTheme = getCurrentTheme(mode); + setHtmlThemeAttr(currentTheme); setUserSettings({ - theme: theme, - isDarkTheme: theme === 'realDark' + theme: currentTheme, + mode: mode, + isDarkTheme: currentTheme === 'realDark' }); }; useEffect(() => { - setHtmlThemeAttr(userSettings.theme); - }, [userSettings.theme]); + setTheme(userSettings.mode); + }, []); useEffect(() => { - const handleChange = (e: MediaQueryListEvent) => { - setTheme(e.matches ? 'realDark' : 'light'); - }; + if (userSettings.mode !== 'auto') return; + const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); + const handleChange = () => { + setTheme('auto'); + }; mediaQuery.addEventListener('change', handleChange); - - if (userSettings.theme === 'auto') { - setTheme(mediaQuery.matches ? 'realDark' : 'light'); - } return () => { mediaQuery.removeEventListener('change', handleChange); }; - }, [userSettings.theme]); + }, [userSettings.mode]); return { userSettings, diff --git a/src/locales/en-US/common.ts b/src/locales/en-US/common.ts index a44226e1..da0efdb7 100644 --- a/src/locales/en-US/common.ts +++ b/src/locales/en-US/common.ts @@ -243,5 +243,6 @@ export default { 'common.appearance.darkmode': 'Dark Mode', 'common.appearance.lightmode': 'Light Mode', 'common.appearance.tips': 'Default follows system preference.', - 'common.button.forgotpassword': 'Forgot password?' + 'common.button.forgotpassword': 'Forgot password?', + 'common.appearance.theme': 'Theme' }; diff --git a/src/locales/en-US/models.ts b/src/locales/en-US/models.ts index 91b88e9b..669778e1 100644 --- a/src/locales/en-US/models.ts +++ b/src/locales/en-US/models.ts @@ -149,7 +149,7 @@ export default { 'models.table.apiAccessInfo.gotoCreate': 'Go to Create', 'models.search.parts': '{n} parts', 'models.search.evaluate.error': 'An error occurred during evaluation: ', - 'models.ollama.deprecated.title': 'Ollama Model Source Will Be Removed', + 'models.ollama.deprecated.title': 'Deprecation Notice', 'models.ollama.deprecated.current': 'Current Version (v0.6.1): Ollama models are currently available for use.', 'models.ollama.deprecated.upcoming': @@ -157,5 +157,6 @@ export default { 'models.ollama.deprecated.following': 'Following the v0.7.0 update, all previously deployed models will continue to work as expected.', 'models.ollama.deprecated.issue': - 'See the related issue: #1979 on GitHub.' + 'See the related issue: #1979 on GitHub.', + 'models.ollama.deprecated.notice': `The Ollama model source has been deprecated as of v0.6.1. For more information, see the related GitHub issue.` }; diff --git a/src/locales/ja-JP/common.ts b/src/locales/ja-JP/common.ts index b3b2a157..c7e1d9b5 100644 --- a/src/locales/ja-JP/common.ts +++ b/src/locales/ja-JP/common.ts @@ -243,7 +243,8 @@ export default { 'common.appearance.darkmode': 'Dark Mode', 'common.appearance.lightmode': 'Light Mode', 'common.appearance.tips': 'Default follows system preference.', - 'common.button.forgotpassword': 'Forgot password?' + 'common.button.forgotpassword': 'Forgot password?', + 'common.appearance.theme': 'Theme' }; // ========== To-Do: Translate Keys (Remove After Translation) ========== @@ -256,4 +257,5 @@ export default { // 7. 'common.appearance.lightmode': 'Light Mode', // 8. 'common.appearance.tips': 'Default follows system preference.' // 9. 'common.button.forgotpassword': 'Forgot Password?' +// 10. 'common.appearance.theme': 'Theme' // ========== End of To-Do List ========== diff --git a/src/locales/ja-JP/models.ts b/src/locales/ja-JP/models.ts index b2db9fc7..af65925c 100644 --- a/src/locales/ja-JP/models.ts +++ b/src/locales/ja-JP/models.ts @@ -149,7 +149,7 @@ export default { 'models.table.apiAccessInfo.gotoCreate': '作成に移動', 'models.search.parts': '{n} 部分', 'models.search.evaluate.error': '評価中にエラーが発生しました: ', - 'models.ollama.deprecated.title': 'Ollama Model Source Will Be Removed', + 'models.ollama.deprecated.title': 'Deprecation Notice', 'models.ollama.deprecated.current': 'Current Version (v0.6.1): Ollama models are currently available for use.', 'models.ollama.deprecated.upcoming': @@ -157,13 +157,12 @@ export default { 'models.ollama.deprecated.following': 'Following the v0.7.0 update, all previously deployed models will continue to work as expected.', 'models.ollama.deprecated.issue': - 'See the related issue: #1979 on GitHub.' + 'See the related issue: #1979 on GitHub.', + 'models.ollama.deprecated.notice': `The Ollama model source has been deprecated as of v0.6.1. For more information, see the related GitHub issue.` }; // ========== To-Do: Translate Keys (Remove After Translation) ========== -// 1. 'models.ollama.deprecated.title': 'Ollama Model Source Will Be Removed', -// 2. 'models.ollama.deprecated.current':'Current Version (v0.6.1): Ollama models are currently available for use.', -// 3. 'models.ollama.deprecated.upcoming': 'Upcoming Version (v0.7.0): The Ollama model source will be removed from the UI.', -// 4. 'models.ollama.deprecated.following': 'Following the v0.7.0 update, all previously deployed models will continue to work as expected.', -// 5. 'models.ollama.deprecated.issue': 'See the related issue: #1979 on GitHub.' +// 1. 'models.ollama.deprecated.title': 'Deprecation Notice', +// 2. 'models.ollama.deprecated.notice': `The Ollama model source has been deprecated as of v0.6.1. For more information, see the related GitHub issue.` + // ========== End of To-Do List ========== diff --git a/src/locales/ru-RU/common.ts b/src/locales/ru-RU/common.ts index b67e9926..35abc035 100644 --- a/src/locales/ru-RU/common.ts +++ b/src/locales/ru-RU/common.ts @@ -237,13 +237,15 @@ export default { 'common.appearance.dark': 'Темная', 'common.appearance.light': 'Светлая', 'common.appearance.system': 'Как в системе', - 'common.exception.404': 'Извините, страница, которую вы посетили, не существует.', + 'common.exception.404': + 'Извините, страница, которую вы посетили, не существует.', 'common.appearance.darkmode': 'Тёмная тема', 'common.appearance.lightmode': 'Светлая тема', 'common.appearance.tips': 'По умолчанию соответствует системным настройкам.', - 'common.button.forgotpassword': 'Забыли пароль?' + 'common.button.forgotpassword': 'Забыли пароль?', + 'common.appearance.theme': 'Theme' }; // ========== To-Do: Translate Keys (Remove After Translation) ========== - +// 1. 'common.appearance.theme': 'Theme' // ========== End of To-Do List ========== diff --git a/src/locales/ru-RU/models.ts b/src/locales/ru-RU/models.ts index 4020efc4..cd080e40 100644 --- a/src/locales/ru-RU/models.ts +++ b/src/locales/ru-RU/models.ts @@ -150,7 +150,7 @@ export default { 'models.table.apiAccessInfo.gotoCreate': 'Перейти к созданию', 'models.search.parts': '{n} частей', 'models.search.evaluate.error': 'Возникла ошибка при вычислении: ', - 'models.ollama.deprecated.title': 'Источник моделей Ollama будет удалён', + 'models.ollama.deprecated.title': 'Deprecation Notice', 'models.ollama.deprecated.current': 'Текущая версия (v0.6.1): Модели Ollama в настоящее время доступны для использования.', 'models.ollama.deprecated.upcoming': @@ -158,9 +158,12 @@ export default { 'models.ollama.deprecated.following': 'После обновления до версии (v0.7.0), все ранее развёрнутые модели продолжат работать в обычном режиме.', 'models.ollama.deprecated.issue': - 'См. связанную проблему: #1979 on GitHub.' + 'См. связанную проблему: #1979 on GitHub.', + 'models.ollama.deprecated.notice': `The Ollama model source has been deprecated as of v0.6.1. For more information, see the related GitHub issue.` }; // ========== To-Do: Translate Keys (Remove After Translation) ========== +// 1. 'models.ollama.deprecated.title': 'Deprecation Notice', +// 2. 'models.ollama.deprecated.notice': `The Ollama model source has been deprecated as of v0.6.1. For more information, see the related GitHub issue.` // ========== End of To-Do List ========== diff --git a/src/locales/zh-CN/common.ts b/src/locales/zh-CN/common.ts index 3311359f..76e3a98f 100644 --- a/src/locales/zh-CN/common.ts +++ b/src/locales/zh-CN/common.ts @@ -238,5 +238,6 @@ export default { 'common.appearance.darkmode': '深色模式', 'common.appearance.lightmode': '浅色模式', 'common.appearance.tips': '默认跟随系统设置', - 'common.button.forgotpassword': '忘记密码?' + 'common.button.forgotpassword': '忘记密码?', + 'common.appearance.theme': '主题' }; diff --git a/src/locales/zh-CN/models.ts b/src/locales/zh-CN/models.ts index c69ed60c..04f6d728 100644 --- a/src/locales/zh-CN/models.ts +++ b/src/locales/zh-CN/models.ts @@ -142,7 +142,7 @@ export default { 'models.table.apiAccessInfo.gotoCreate': '去创建', 'models.search.parts': '{n} 个文件', 'models.search.evaluate.error': '评估过程中发生了错误:', - 'models.ollama.deprecated.title': 'Ollama 模型源即将被移除', + 'models.ollama.deprecated.title': '弃用通知', 'models.ollama.deprecated.current': '当前版本(v0.6.1):Ollama 模型目前仍可使用。', 'models.ollama.deprecated.upcoming': @@ -150,5 +150,6 @@ export default { 'models.ollama.deprecated.following': '在 v0.7.0 更新后: 所有先前部署的模型仍将正常运行。', 'models.ollama.deprecated.issue': - '参见 GitHub 上的问题 #1979。' + '参见 GitHub 上的问题 #1979。', + 'models.ollama.deprecated.notice': `Ollama 模型来源自 v0.6.1 起已被弃用。更多信息请参见相关的 GitHub 问题。` }; diff --git a/src/pages/llmodels/components/ollama-tips.tsx b/src/pages/llmodels/components/ollama-tips.tsx index 588a632e..ef24958f 100644 --- a/src/pages/llmodels/components/ollama-tips.tsx +++ b/src/pages/llmodels/components/ollama-tips.tsx @@ -55,38 +55,13 @@ const RenderMessage = () => { const intl = useIntl(); return ( -
    -
  • - -
  • -
  • - -
  • -
- -
diff --git a/src/pages/playground/components/multiple-chat/message-body.tsx b/src/pages/playground/components/multiple-chat/message-body.tsx index d9f9560b..24628c89 100644 --- a/src/pages/playground/components/multiple-chat/message-body.tsx +++ b/src/pages/playground/components/multiple-chat/message-body.tsx @@ -217,7 +217,6 @@ const MessageBody: React.FC = forwardRef( autoSize={{ minRows: 1 }} style={{ borderRadius: 'var(--border-radius-mini)' }} readOnly={loading} - onKeyDown={handleKeyDown} onChange={handleMessageChange} onPaste={handleOnPaste} /> @@ -244,7 +243,6 @@ const MessageBody: React.FC = forwardRef( variant="filled" autoSize={{ minRows: 1 }} style={{ borderRadius: 'var(--border-radius-mini)' }} - onKeyDown={handleKeyDown} onChange={handleEdit} onPaste={handleOnPaste} /> diff --git a/src/pages/profile/components/appearance.tsx b/src/pages/profile/components/appearance.tsx index 280f3592..21b65a51 100644 --- a/src/pages/profile/components/appearance.tsx +++ b/src/pages/profile/components/appearance.tsx @@ -1,7 +1,7 @@ import useUserSettings from '@/hooks/use-user-settings'; import { MoonOutlined, SunOutlined } from '@ant-design/icons'; import { useIntl } from '@umijs/max'; -import { Switch } from 'antd'; +import { Select } from 'antd'; import React, { useMemo } from 'react'; import styled from 'styled-components'; @@ -14,9 +14,11 @@ const Wrapper = styled.div` display: flex; align-items: center; justify-content: space-between; - max-width: 220px; + max-width: 300px; } .theme-label { + display: flex; + align-items: center; font-size: 16px; font-weight: var(--font-weight-500); } @@ -25,46 +27,51 @@ const Wrapper = styled.div` } `; -const ThemeOptions = [ - { - key: 'realDark', - label: 'common.appearance.dark', - icon: - }, - { - key: 'light', - label: 'common.appearance.light', - icon: - } -]; const Appearance: React.FC = () => { const { setTheme, userSettings } = useUserSettings(); + console.log('userSettings', userSettings); + const intl = useIntl(); - const handleOnChange = (checked: boolean) => { - if (checked) { - setTheme('realDark'); - } else { - setTheme('light'); + const ThemeOptions = [ + { + value: 'light', + label: intl.formatMessage({ id: 'common.appearance.light' }), + icon: + }, + { + value: 'realDark', + label: intl.formatMessage({ id: 'common.appearance.dark' }), + icon: + }, + { + value: 'auto', + label: intl.formatMessage({ id: 'common.appearance.system' }), + icon: } + ]; + + const handleOnChange = (value: 'light' | 'realDark' | 'auto') => { + setTheme(value); }; - const isDarkMode = useMemo(() => { - const darkMode = userSettings?.theme === 'realDark'; - return darkMode; + const theme = useMemo(() => { + return userSettings?.theme || 'auto'; }, [userSettings?.theme]); return (
- {intl.formatMessage({ id: 'common.appearance.darkmode' })} + {intl.formatMessage({ id: 'common.appearance.theme' })} - -
-
- {intl.formatMessage({ id: 'common.appearance.tips' })} +
);