@lobehub/chat 1.86.1 → 1.87.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/Dockerfile +1 -1
  3. package/Dockerfile.database +1 -1
  4. package/Dockerfile.pglite +1 -1
  5. package/changelog/v1.json +21 -0
  6. package/locales/ar/setting.json +43 -31
  7. package/locales/bg-BG/setting.json +43 -31
  8. package/locales/de-DE/setting.json +43 -31
  9. package/locales/en-US/setting.json +43 -31
  10. package/locales/es-ES/setting.json +43 -31
  11. package/locales/fa-IR/setting.json +43 -31
  12. package/locales/fr-FR/setting.json +43 -31
  13. package/locales/it-IT/setting.json +43 -31
  14. package/locales/ja-JP/setting.json +43 -31
  15. package/locales/ko-KR/setting.json +43 -31
  16. package/locales/nl-NL/setting.json +43 -31
  17. package/locales/pl-PL/setting.json +43 -31
  18. package/locales/pt-BR/setting.json +43 -31
  19. package/locales/ru-RU/setting.json +43 -31
  20. package/locales/tr-TR/setting.json +43 -31
  21. package/locales/vi-VN/setting.json +43 -31
  22. package/locales/zh-CN/setting.json +43 -31
  23. package/locales/zh-TW/setting.json +43 -31
  24. package/package.json +3 -3
  25. package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatList/WelcomeChatItem/WelcomeMessage.tsx +1 -1
  26. package/src/app/[variants]/(main)/settings/agent/index.tsx +8 -2
  27. package/src/app/[variants]/(main)/settings/common/features/Appearance/Preview.tsx +298 -0
  28. package/src/app/[variants]/(main)/settings/common/features/{Theme → Appearance}/ThemeSwatches/ThemeSwatchesNeutral.tsx +6 -11
  29. package/src/app/[variants]/(main)/settings/common/features/{Theme → Appearance}/ThemeSwatches/ThemeSwatchesPrimary.tsx +6 -10
  30. package/src/app/[variants]/(main)/settings/common/features/Appearance/index.tsx +67 -0
  31. package/src/app/[variants]/(main)/settings/common/features/ChatAppearance/ChatPreview.tsx +35 -0
  32. package/src/app/[variants]/(main)/settings/common/features/ChatAppearance/HighlighterPreview.tsx +55 -0
  33. package/src/app/[variants]/(main)/settings/common/features/ChatAppearance/MermaidPreview.tsx +51 -0
  34. package/src/app/[variants]/(main)/settings/common/features/ChatAppearance/index.tsx +128 -0
  35. package/src/app/[variants]/(main)/settings/common/features/Common.tsx +74 -42
  36. package/src/app/[variants]/(main)/settings/common/index.tsx +4 -2
  37. package/src/app/[variants]/(main)/settings/hotkey/features/{HotkeySetting.tsx → Conversation.tsx} +19 -18
  38. package/src/app/[variants]/(main)/settings/hotkey/features/Essential.tsx +88 -0
  39. package/src/app/[variants]/(main)/settings/hotkey/page.tsx +8 -2
  40. package/src/app/[variants]/(main)/settings/llm/components/ProviderModelList/ModelConfigModal/index.tsx +1 -1
  41. package/src/app/[variants]/(main)/settings/storage/Advanced.tsx +26 -0
  42. package/src/app/[variants]/(main)/settings/system-agent/features/createForm.tsx +37 -22
  43. package/src/app/[variants]/(main)/settings/tts/features/OpenAI.tsx +20 -10
  44. package/src/app/[variants]/(main)/settings/tts/features/STT.tsx +20 -11
  45. package/src/config/aiModels/internlm.ts +21 -5
  46. package/src/config/aiModels/spark.ts +16 -14
  47. package/src/config/modelProviders/spark.ts +4 -0
  48. package/src/const/settings/common.ts +2 -0
  49. package/src/features/AgentSetting/AgentTTS/index.tsx +1 -1
  50. package/src/features/ChatItem/index.tsx +35 -0
  51. package/src/features/Conversation/components/ChatItem/index.tsx +2 -6
  52. package/src/features/User/UserPanel/LangButton.tsx +1 -1
  53. package/src/features/User/UserPanel/ThemeButton.tsx +3 -3
  54. package/src/libs/model-runtime/{AgentRuntime.test.ts → ModelRuntime.test.ts} +1 -1
  55. package/src/libs/model-runtime/{AgentRuntime.ts → ModelRuntime.ts} +3 -3
  56. package/src/libs/model-runtime/index.ts +1 -1
  57. package/src/libs/model-runtime/internlm/index.ts +15 -3
  58. package/src/libs/model-runtime/spark/index.test.ts +3 -0
  59. package/src/libs/model-runtime/spark/index.ts +23 -1
  60. package/src/libs/model-runtime/utils/streams/spark.test.ts +66 -0
  61. package/src/libs/model-runtime/utils/streams/spark.ts +31 -2
  62. package/src/libs/oidc-provider/config.ts +1 -1
  63. package/src/locales/default/setting.ts +45 -31
  64. package/src/store/electron/initialState.ts +1 -1
  65. package/src/store/electron/selectors/__tests__/desktopState.test.ts +55 -0
  66. package/src/store/global/selectors/systemStatus.ts +2 -0
  67. package/src/store/user/slices/settings/selectors/general.test.ts +29 -1
  68. package/src/store/user/slices/settings/selectors/general.ts +4 -0
  69. package/src/types/user/settings/general.ts +3 -1
  70. package/src/app/[variants]/(main)/settings/common/features/Theme/index.tsx +0 -146
  71. /package/src/app/[variants]/(main)/settings/common/features/{Theme → Appearance}/ThemeSwatches/index.ts +0 -0
@@ -0,0 +1,55 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { ElectronState } from '@/store/electron/initialState';
4
+
5
+ import { desktopStateSelectors } from '../desktopState';
6
+
7
+ describe('desktopStateSelectors', () => {
8
+ describe('usePath', () => {
9
+ it('should return userPath from appState', () => {
10
+ const state: ElectronState = {
11
+ isAppStateInit: false,
12
+ appState: {
13
+ userPath: {
14
+ desktop: '/test/desktop',
15
+ documents: '/test/documents',
16
+ downloads: '/test/downloads',
17
+ home: '/test/home',
18
+ music: '/test/music',
19
+ pictures: '/test/pictures',
20
+ userData: '/test/userdata',
21
+ videos: '/test/videos',
22
+ },
23
+ },
24
+ dataSyncConfig: {
25
+ storageMode: 'local',
26
+ },
27
+ isInitRemoteServerConfig: false,
28
+ };
29
+
30
+ expect(desktopStateSelectors.usePath(state)).toEqual({
31
+ desktop: '/test/desktop',
32
+ documents: '/test/documents',
33
+ downloads: '/test/downloads',
34
+ home: '/test/home',
35
+ music: '/test/music',
36
+ pictures: '/test/pictures',
37
+ userData: '/test/userdata',
38
+ videos: '/test/videos',
39
+ });
40
+ });
41
+
42
+ it('should handle undefined userPath', () => {
43
+ const state: ElectronState = {
44
+ appState: {},
45
+ isAppStateInit: false,
46
+ dataSyncConfig: {
47
+ storageMode: 'local',
48
+ },
49
+ isInitRemoteServerConfig: false,
50
+ };
51
+
52
+ expect(desktopStateSelectors.usePath(state)).toBeUndefined();
53
+ });
54
+ });
55
+ });
@@ -17,6 +17,7 @@ const showFilePanel = (s: GlobalState) => s.status.showFilePanel;
17
17
  const hidePWAInstaller = (s: GlobalState) => s.status.hidePWAInstaller;
18
18
  const isShowCredit = (s: GlobalState) => s.status.isShowCredit;
19
19
  const themeMode = (s: GlobalState) => s.status.themeMode || 'auto';
20
+ const language = (s: GlobalState) => s.status.language || 'auto';
20
21
 
21
22
  const showChatHeader = (s: GlobalState) => !s.status.zenMode;
22
23
  const inZenMode = (s: GlobalState) => s.status.zenMode;
@@ -68,6 +69,7 @@ export const systemStatusSelectors = {
68
69
  isPgliteNotEnabled,
69
70
  isPgliteNotInited,
70
71
  isShowCredit,
72
+ language,
71
73
  mobileShowPortal,
72
74
  mobileShowTopic,
73
75
  portalWidth,
@@ -15,7 +15,11 @@ describe('settingsSelectors', () => {
15
15
 
16
16
  const result = userGeneralSettingsSelectors.config(s as UserStore);
17
17
 
18
- expect(result).toEqual({ fontSize: 12 });
18
+ expect(result).toEqual({
19
+ fontSize: 12,
20
+ highlighterTheme: 'lobe-theme',
21
+ mermaidTheme: 'lobe-theme',
22
+ });
19
23
  });
20
24
  });
21
25
 
@@ -108,4 +112,28 @@ describe('settingsSelectors', () => {
108
112
  expect(result).toBe('#ffffff');
109
113
  });
110
114
  });
115
+
116
+ it('should return the highlighterTheme', () => {
117
+ const s: UserState = merge(initialState, {
118
+ settings: {
119
+ general: { highlighterTheme: 'lobe-theme' },
120
+ },
121
+ });
122
+
123
+ const result = userGeneralSettingsSelectors.highlighterTheme(s as UserStore);
124
+
125
+ expect(result).toBe('lobe-theme');
126
+ });
127
+
128
+ it('should return the mermaidTheme', () => {
129
+ const s: UserState = merge(initialState, {
130
+ settings: {
131
+ general: { mermaidTheme: 'lobe-theme' },
132
+ },
133
+ });
134
+
135
+ const result = userGeneralSettingsSelectors.mermaidTheme(s as UserStore);
136
+
137
+ expect(result).toBe('lobe-theme');
138
+ });
111
139
  });
@@ -6,10 +6,14 @@ const generalConfig = (s: UserStore) => currentSettings(s).general || {};
6
6
  const neutralColor = (s: UserStore) => generalConfig(s).neutralColor;
7
7
  const primaryColor = (s: UserStore) => generalConfig(s).primaryColor;
8
8
  const fontSize = (s: UserStore) => generalConfig(s).fontSize;
9
+ const highlighterTheme = (s: UserStore) => generalConfig(s).highlighterTheme;
10
+ const mermaidTheme = (s: UserStore) => generalConfig(s).mermaidTheme;
9
11
 
10
12
  export const userGeneralSettingsSelectors = {
11
13
  config: generalConfig,
12
14
  fontSize,
15
+ highlighterTheme,
16
+ mermaidTheme,
13
17
  neutralColor,
14
18
  primaryColor,
15
19
  };
@@ -1,7 +1,9 @@
1
- import type { NeutralColors, PrimaryColors } from '@lobehub/ui';
1
+ import type { HighlighterProps, MermaidProps, NeutralColors, PrimaryColors } from '@lobehub/ui';
2
2
 
3
3
  export interface UserGeneralConfig {
4
4
  fontSize: number;
5
+ highlighterTheme?: HighlighterProps['theme'];
6
+ mermaidTheme?: MermaidProps['theme'];
5
7
  neutralColor?: NeutralColors;
6
8
  primaryColor?: PrimaryColors;
7
9
  }
@@ -1,146 +0,0 @@
1
- 'use client';
2
-
3
- import { Form, type FormGroupItemType, ImageSelect, SliderWithInput } from '@lobehub/ui';
4
- import { Select } from '@lobehub/ui';
5
- import isEqual from 'fast-deep-equal';
6
- import { Monitor, Moon, Sun } from 'lucide-react';
7
- import { memo } from 'react';
8
- import { useTranslation } from 'react-i18next';
9
-
10
- import { useSyncSettings } from '@/app/[variants]/(main)/settings/hooks/useSyncSettings';
11
- import { FORM_STYLE } from '@/const/layoutTokens';
12
- import { imageUrl } from '@/const/url';
13
- import { Locales, localeOptions } from '@/locales/resources';
14
- import { useGlobalStore } from '@/store/global';
15
- import { systemStatusSelectors } from '@/store/global/selectors';
16
- import { useUserStore } from '@/store/user';
17
- import { settingsSelectors } from '@/store/user/selectors';
18
-
19
- import { ThemeSwatchesNeutral, ThemeSwatchesPrimary } from './ThemeSwatches';
20
-
21
- const Theme = memo(() => {
22
- const { t } = useTranslation('setting');
23
-
24
- const [form] = Form.useForm();
25
- const settings = useUserStore(settingsSelectors.currentSettings, isEqual);
26
- const themeMode = useGlobalStore(systemStatusSelectors.themeMode);
27
- const [setSettings] = useUserStore((s) => [s.setSettings]);
28
- const [setThemeMode] = useGlobalStore((s) => [s.switchThemeMode]);
29
-
30
- useSyncSettings(form);
31
- const [switchLocale] = useGlobalStore((s) => [s.switchLocale]);
32
-
33
- const handleLangChange = (value: Locales) => {
34
- switchLocale(value);
35
- };
36
-
37
- const theme: FormGroupItemType = {
38
- children: [
39
- {
40
- children: (
41
- <ImageSelect
42
- height={60}
43
- onChange={setThemeMode}
44
- options={[
45
- {
46
- icon: Sun,
47
- img: imageUrl('theme_light.webp'),
48
- label: t('settingTheme.themeMode.light'),
49
- value: 'light',
50
- },
51
- {
52
- icon: Moon,
53
- img: imageUrl('theme_dark.webp'),
54
- label: t('settingTheme.themeMode.dark'),
55
- value: 'dark',
56
- },
57
- {
58
- icon: Monitor,
59
- img: imageUrl('theme_auto.webp'),
60
- label: t('settingTheme.themeMode.auto'),
61
- value: 'auto',
62
- },
63
- ]}
64
- unoptimized={false}
65
- value={themeMode}
66
- width={100}
67
- />
68
- ),
69
- label: t('settingTheme.themeMode.title'),
70
- minWidth: undefined,
71
- },
72
- {
73
- children: (
74
- <Select
75
- onChange={handleLangChange}
76
- options={[{ label: t('settingTheme.lang.autoMode'), value: 'auto' }, ...localeOptions]}
77
- />
78
- ),
79
- label: t('settingTheme.lang.title'),
80
- name: ['general', 'language'],
81
- },
82
- {
83
- children: (
84
- <SliderWithInput
85
- marks={{
86
- 12: {
87
- label: 'A',
88
- style: {
89
- fontSize: 12,
90
- marginTop: 4,
91
- },
92
- },
93
- 14: {
94
- label: t('settingTheme.fontSize.marks.normal'),
95
- style: {
96
- fontSize: 14,
97
- marginTop: 4,
98
- },
99
- },
100
- 18: {
101
- label: 'A',
102
- style: {
103
- fontSize: 18,
104
- marginTop: 4,
105
- },
106
- },
107
- }}
108
- max={18}
109
- min={12}
110
- step={1}
111
- />
112
- ),
113
- desc: t('settingTheme.fontSize.desc'),
114
- label: t('settingTheme.fontSize.title'),
115
- name: ['general', 'fontSize'],
116
- },
117
- {
118
- children: <ThemeSwatchesPrimary />,
119
- desc: t('settingTheme.primaryColor.desc'),
120
- label: t('settingTheme.primaryColor.title'),
121
- minWidth: undefined,
122
- },
123
- {
124
- children: <ThemeSwatchesNeutral />,
125
- desc: t('settingTheme.neutralColor.desc'),
126
- label: t('settingTheme.neutralColor.title'),
127
- minWidth: undefined,
128
- },
129
- ],
130
- title: t('settingTheme.title'),
131
- };
132
-
133
- return (
134
- <Form
135
- form={form}
136
- initialValues={settings}
137
- items={[theme]}
138
- itemsType={'group'}
139
- onValuesChange={setSettings}
140
- variant={'borderless'}
141
- {...FORM_STYLE}
142
- />
143
- );
144
- });
145
-
146
- export default Theme;