@lobehub/lobehub 2.0.0-next.213 → 2.0.0-next.215

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 (87) hide show
  1. package/.github/workflows/e2e.yml +1 -1
  2. package/.github/workflows/pr-build-desktop.yml +2 -2
  3. package/.github/workflows/release-desktop-beta.yml +2 -2
  4. package/.github/workflows/release.yml +1 -1
  5. package/.github/workflows/test.yml +2 -2
  6. package/CHANGELOG.md +51 -0
  7. package/apps/desktop/package.json +3 -2
  8. package/apps/desktop/src/main/const/store.ts +1 -1
  9. package/apps/desktop/src/main/controllers/SystemCtr.ts +2 -3
  10. package/apps/desktop/src/main/core/App.ts +10 -3
  11. package/apps/desktop/src/main/types/store.ts +1 -1
  12. package/changelog/v1.json +14 -0
  13. package/package.json +4 -3
  14. package/packages/builtin-tool-knowledge-base/src/client/Render/SearchKnowledgeBase/Item/index.tsx +4 -2
  15. package/packages/builtin-tool-local-system/src/client/Intervention/EditLocalFile/index.tsx +3 -2
  16. package/packages/builtin-tool-local-system/src/client/Render/EditLocalFile/index.tsx +3 -2
  17. package/packages/const/src/theme.ts +0 -2
  18. package/packages/desktop-bridge/src/routeVariants.ts +2 -9
  19. package/packages/electron-client-ipc/src/types/system.ts +1 -1
  20. package/scripts/electronWorkflow/modifiers/nextConfig.mts +41 -13
  21. package/src/app/[variants]/(auth)/_layout/index.tsx +3 -2
  22. package/src/app/[variants]/(auth)/_layout/style.ts +8 -18
  23. package/src/app/[variants]/(auth)/layout.tsx +7 -3
  24. package/src/app/[variants]/(desktop)/desktop-onboarding/_layout/index.tsx +4 -2
  25. package/src/app/[variants]/(desktop)/desktop-onboarding/_layout/style.ts +3 -0
  26. package/src/app/[variants]/(main)/_layout/DesktopLayoutContainer.tsx +3 -2
  27. package/src/app/[variants]/(main)/chat/profile/features/ProfileEditor/PluginTag.tsx +3 -2
  28. package/src/app/[variants]/(main)/community/(list)/_layout/Footer.tsx +3 -2
  29. package/src/app/[variants]/(main)/group/features/Conversation/ChatItem/Thread.tsx +3 -2
  30. package/src/app/[variants]/(main)/group/profile/features/AgentBuilder/index.tsx +0 -1
  31. package/src/app/[variants]/(main)/group/profile/features/ProfileEditor/PluginTag.tsx +3 -2
  32. package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/AgentItem/Editing.tsx +2 -2
  33. package/src/app/[variants]/(main)/home/_layout/Footer/index.tsx +1 -1
  34. package/src/app/[variants]/(main)/home/_layout/index.tsx +3 -2
  35. package/src/app/[variants]/(main)/home/features/CommunityAgents/Item.tsx +3 -2
  36. package/src/app/[variants]/(main)/image/_layout/ConfigPanel/components/AspectRatioSelect/index.tsx +4 -2
  37. package/src/app/[variants]/(main)/image/_layout/ConfigPanel/components/ModelSelect/ImageModelItem.tsx +3 -2
  38. package/src/app/[variants]/(main)/image/_layout/ConfigPanel/components/Select/index.tsx +4 -2
  39. package/src/app/[variants]/(main)/image/features/PromptInput/index.tsx +3 -2
  40. package/src/app/[variants]/(main)/memory/features/TimeLineView/index.tsx +9 -4
  41. package/src/app/[variants]/(main)/page/_layout/Body/List/Item/Editing.tsx +2 -2
  42. package/src/app/[variants]/(main)/settings/common/features/Common/Common.tsx +11 -11
  43. package/src/app/[variants]/(main)/settings/provider/(list)/ProviderGrid/Card.tsx +3 -2
  44. package/src/app/[variants]/(main)/settings/stats/features/overview/ShareButton/TotalCard.tsx +4 -2
  45. package/src/app/[variants]/(mobile)/me/(home)/features/Header.tsx +6 -8
  46. package/src/app/[variants]/layout.tsx +10 -15
  47. package/src/app/[variants]/onboarding/_layout/index.tsx +3 -2
  48. package/src/app/[variants]/onboarding/features/ModeSelectionStep.tsx +3 -2
  49. package/src/app/[variants]/router/index.tsx +12 -8
  50. package/src/components/Cell/Divider.tsx +4 -2
  51. package/src/components/DataStyleModal/index.tsx +4 -2
  52. package/src/components/FeatureList/index.tsx +4 -2
  53. package/src/components/FileParsingStatus/EmbeddingStatus.tsx +3 -2
  54. package/src/components/FileParsingStatus/index.tsx +3 -2
  55. package/src/components/Notification/index.tsx +4 -2
  56. package/src/components/client/ClientOnly.tsx +17 -0
  57. package/src/features/AlertBanner/CloudBanner.tsx +4 -3
  58. package/src/features/CommandMenu/ThemeMenu.tsx +1 -1
  59. package/src/features/CommandMenu/types.ts +5 -2
  60. package/src/features/CommandMenu/useCommandMenu.ts +3 -2
  61. package/src/features/Conversation/Markdown/plugins/LobeArtifact/Render/index.tsx +3 -2
  62. package/src/features/Conversation/Messages/components/FileChunks/ChunkItem.tsx +3 -2
  63. package/src/features/Conversation/Messages/components/FileChunks/index.tsx +4 -2
  64. package/src/features/Conversation/Messages/components/SearchGrounding.tsx +3 -2
  65. package/src/features/ElectronTitlebar/hooks/useWatchThemeUpdate.ts +21 -38
  66. package/src/features/GroupChatSettings/AgentCard.tsx +3 -2
  67. package/src/features/GroupChatSettings/HostMemberCard.tsx +3 -2
  68. package/src/features/PageEditor/DiffAllToolbar.tsx +4 -2
  69. package/src/features/Portal/Document/Header.tsx +11 -9
  70. package/src/features/User/UserPanel/ThemeButton.tsx +18 -29
  71. package/src/hooks/useIsDark.ts +11 -0
  72. package/src/layout/AuthProvider/Clerk/useAppearance.ts +4 -2
  73. package/src/layout/AuthProvider/MarketAuth/MarketAuthConfirmModal.tsx +3 -2
  74. package/src/layout/GlobalProvider/AppTheme.tsx +15 -19
  75. package/src/layout/GlobalProvider/NextThemeProvider.tsx +22 -0
  76. package/src/layout/GlobalProvider/StyleRegistry.tsx +18 -13
  77. package/src/layout/GlobalProvider/index.tsx +38 -36
  78. package/src/libs/next/proxy/define-config.ts +2 -11
  79. package/src/store/global/action.test.ts +0 -15
  80. package/src/store/global/actions/__tests__/general.test.ts +0 -37
  81. package/src/store/global/actions/general.ts +0 -21
  82. package/src/store/global/initialState.ts +0 -6
  83. package/src/store/global/selectors/systemStatus.test.ts +0 -20
  84. package/src/store/global/selectors/systemStatus.ts +0 -2
  85. package/src/styles/global.ts +0 -2
  86. package/src/utils/server/routeVariants.test.ts +17 -51
  87. package/src/utils/server/routeVariants.ts +0 -1
@@ -8,7 +8,7 @@ import {
8
8
  ThemeProvider,
9
9
  } from '@lobehub/ui';
10
10
  import { message as antdMessage } from 'antd';
11
- import { type ThemeAppearance, createStaticStyles, cx, useTheme } from 'antd-style';
11
+ import { createStaticStyles, cx, useTheme } from 'antd-style';
12
12
  import 'antd/dist/reset.css';
13
13
  import { AppConfigContext } from 'antd/es/app/context';
14
14
  import * as motion from 'motion/react-m';
@@ -17,13 +17,10 @@ import Link from 'next/link';
17
17
  import { type ReactNode, memo, useEffect, useMemo, useState } from 'react';
18
18
 
19
19
  import AntdStaticMethods from '@/components/AntdStaticMethods';
20
- import {
21
- LOBE_THEME_APPEARANCE,
22
- LOBE_THEME_NEUTRAL_COLOR,
23
- LOBE_THEME_PRIMARY_COLOR,
24
- } from '@/const/theme';
20
+ import { LOBE_THEME_NEUTRAL_COLOR, LOBE_THEME_PRIMARY_COLOR } from '@/const/theme';
25
21
  import { isDesktop } from '@/const/version';
26
22
  import { TITLE_BAR_HEIGHT } from '@/features/ElectronTitlebar';
23
+ import { useIsDark } from '@/hooks/useIsDark';
27
24
  import { getUILocaleAndResources } from '@/libs/getUILocaleAndResources';
28
25
  import { useGlobalStore } from '@/store/global';
29
26
  import { systemStatusSelectors } from '@/store/global/selectors';
@@ -92,7 +89,6 @@ export interface AppThemeProps {
92
89
  children?: ReactNode;
93
90
  customFontFamily?: string;
94
91
  customFontURL?: string;
95
- defaultAppearance?: ThemeAppearance;
96
92
  defaultNeutralColor?: NeutralColors;
97
93
  defaultPrimaryColor?: PrimaryColors;
98
94
  globalCDN?: boolean;
@@ -101,16 +97,16 @@ export interface AppThemeProps {
101
97
  const AppTheme = memo<AppThemeProps>(
102
98
  ({
103
99
  children,
104
- defaultAppearance,
105
100
  defaultPrimaryColor,
106
101
  defaultNeutralColor,
107
102
  globalCDN,
108
103
  customFontURL,
109
104
  customFontFamily,
110
105
  }) => {
111
- const themeMode = useGlobalStore(systemStatusSelectors.themeMode);
112
106
  const language = useGlobalStore(systemStatusSelectors.language);
113
- const theme = useTheme();
107
+ const antdTheme = useTheme();
108
+ const isDark = useIsDark();
109
+
114
110
  const [primaryColor, neutralColor, animationMode] = useUserStore((s) => [
115
111
  userGeneralSettingsSelectors.primaryColor(s),
116
112
  userGeneralSettingsSelectors.neutralColor(s),
@@ -154,29 +150,29 @@ const AppTheme = memo<AppThemeProps>(
154
150
  antdMessage.config({ top: messageTop });
155
151
  }, [messageTop]);
156
152
 
153
+ const currentAppearence = isDark ? 'dark' : 'light';
154
+
157
155
  return (
158
156
  <AppConfigContext.Provider value={appConfig}>
159
157
  <ThemeProvider
160
- appearance={themeMode !== 'auto' ? themeMode : undefined}
158
+ appearance={currentAppearence}
161
159
  className={cx(styles.app, styles.scrollbar, styles.scrollbarPolyfill)}
162
160
  customTheme={{
163
161
  neutralColor: neutralColor ?? defaultNeutralColor,
164
162
  primaryColor: primaryColor ?? defaultPrimaryColor,
165
163
  }}
166
- defaultAppearance={defaultAppearance}
167
- onAppearanceChange={(appearance) => {
168
- if (themeMode !== 'auto') return;
169
-
170
- setCookie(LOBE_THEME_APPEARANCE, appearance);
171
- }}
164
+ defaultAppearance={currentAppearence}
165
+ defaultThemeMode={currentAppearence}
172
166
  theme={{
167
+ cssVar: { key: 'lobe-vars' },
173
168
  token: {
174
- fontFamily: customFontFamily ? `${customFontFamily},${theme.fontFamily}` : undefined,
169
+ fontFamily: customFontFamily
170
+ ? `${customFontFamily},${antdTheme.fontFamily}`
171
+ : undefined,
175
172
  motion: animationMode !== 'disabled',
176
173
  motionUnit: animationMode === 'agile' ? 0.05 : 0.1,
177
174
  },
178
175
  }}
179
- themeMode={themeMode}
180
176
  >
181
177
  {!!customFontURL && <FontLoader url={customFontURL} />}
182
178
  <GlobalStyle />
@@ -0,0 +1,22 @@
1
+ 'use client';
2
+
3
+ import { ThemeProvider as NextThemesProvider } from 'next-themes';
4
+ import { type ReactNode } from 'react';
5
+
6
+ interface NextThemeProviderProps {
7
+ children: ReactNode;
8
+ }
9
+
10
+ export default function NextThemeProvider({ children }: NextThemeProviderProps) {
11
+ return (
12
+ <NextThemesProvider
13
+ attribute="data-theme"
14
+ defaultTheme="system"
15
+ disableTransitionOnChange
16
+ enableSystem
17
+ forcedTheme={undefined}
18
+ >
19
+ {children}
20
+ </NextThemesProvider>
21
+ );
22
+ }
@@ -1,24 +1,29 @@
1
1
  'use client';
2
2
 
3
- import { StyleProvider, extractStaticStyle } from 'antd-style';
3
+ import { StyleProvider } from 'antd-style';
4
4
  import { useServerInsertedHTML } from 'next/navigation';
5
- import { type PropsWithChildren, useRef } from 'react';
5
+ import { type PropsWithChildren } from 'react';
6
6
 
7
- const StyleRegistry = ({ children }: PropsWithChildren) => {
8
- const isInsert = useRef(false);
7
+ import { isDesktop } from '@/const/version';
9
8
 
9
+ const StyleRegistry = ({ children }: PropsWithChildren) => {
10
10
  useServerInsertedHTML(() => {
11
- // avoid duplicate css insert
12
- // refs: https://github.com/vercel/next.js/discussions/49354#discussioncomment-6279917
13
- if (isInsert.current) return;
14
-
15
- isInsert.current = true;
16
-
17
- // @ts-ignore
18
- return extractStaticStyle().map((item) => item.style);
11
+ return (
12
+ <style
13
+ dangerouslySetInnerHTML={{
14
+ __html: `
15
+ html body {background: #f8f8f8;}
16
+ html[data-theme="dark"] body { background-color: #000; }
17
+ ${isDesktop ? 'html body, html { background: none; }' : ''}
18
+ ${isDesktop ? 'html[data-theme="dark"] body { background: color-mix(in srgb, #000 86%, transparent); }' : ''}
19
+ ${isDesktop ? 'html[data-theme="light"] body { background: color-mix(in srgb, #f8f8f8 86%, transparent); }' : ''}
20
+ `,
21
+ }}
22
+ />
23
+ );
19
24
  });
20
25
 
21
- return <StyleProvider cache={extractStaticStyle.cache}>{children}</StyleProvider>;
26
+ return <StyleProvider>{children}</StyleProvider>;
22
27
  };
23
28
 
24
29
  export default StyleRegistry;
@@ -17,12 +17,12 @@ import AppTheme from './AppTheme';
17
17
  import { GroupWizardProvider } from './GroupWizardProvider';
18
18
  import ImportSettings from './ImportSettings';
19
19
  import Locale from './Locale';
20
+ import NextThemeProvider from './NextThemeProvider';
20
21
  import QueryProvider from './Query';
21
22
  import StoreInitialization from './StoreInitialization';
22
23
  import StyleRegistry from './StyleRegistry';
23
24
 
24
25
  interface GlobalLayoutProps {
25
- appearance: string;
26
26
  children: ReactNode;
27
27
  isMobile: boolean;
28
28
  locale: string;
@@ -36,7 +36,7 @@ const GlobalLayout = async ({
36
36
  neutralColor,
37
37
  primaryColor,
38
38
  locale: userLocale,
39
- appearance,
39
+
40
40
  isMobile,
41
41
  variants,
42
42
  }: GlobalLayoutProps) => {
@@ -45,44 +45,46 @@ const GlobalLayout = async ({
45
45
  // get default feature flags to use with ssr
46
46
  const serverFeatureFlags = getServerFeatureFlagsValue();
47
47
  const serverConfig = await getServerGlobalConfig();
48
+
48
49
  return (
49
50
  <StyleRegistry>
50
51
  <Locale antdLocale={antdLocale} defaultLang={userLocale}>
51
- <AppTheme
52
- customFontFamily={appEnv.CUSTOM_FONT_FAMILY}
53
- customFontURL={appEnv.CUSTOM_FONT_URL}
54
- defaultAppearance={appearance}
55
- defaultNeutralColor={neutralColor as any}
56
- defaultPrimaryColor={primaryColor as any}
57
- globalCDN={appEnv.CDN_USE_GLOBAL}
58
- >
59
- <ServerConfigStoreProvider
60
- featureFlags={serverFeatureFlags}
61
- isMobile={isMobile}
62
- segmentVariants={variants}
63
- serverConfig={serverConfig}
52
+ <NextThemeProvider>
53
+ <AppTheme
54
+ customFontFamily={appEnv.CUSTOM_FONT_FAMILY}
55
+ customFontURL={appEnv.CUSTOM_FONT_URL}
56
+ defaultNeutralColor={neutralColor as any}
57
+ defaultPrimaryColor={primaryColor as any}
58
+ globalCDN={appEnv.CDN_USE_GLOBAL}
64
59
  >
65
- <QueryProvider>
66
- <GroupWizardProvider>
67
- <DragUploadProvider>
68
- <LazyMotion features={domMax}>
69
- <TooltipGroup layoutAnimation={false}>
70
- <LobeAnalyticsProviderWrapper>{children}</LobeAnalyticsProviderWrapper>
71
- </TooltipGroup>
72
- <ModalHost />
73
- <ContextMenuHost />
74
- </LazyMotion>
75
- </DragUploadProvider>
76
- </GroupWizardProvider>
77
- </QueryProvider>
78
- <StoreInitialization />
79
- <Suspense>
80
- {ENABLE_BUSINESS_FEATURES ? <ReferralProvider /> : null}
81
- <ImportSettings />
82
- {process.env.NODE_ENV === 'development' && <DevPanel />}
83
- </Suspense>
84
- </ServerConfigStoreProvider>
85
- </AppTheme>
60
+ <ServerConfigStoreProvider
61
+ featureFlags={serverFeatureFlags}
62
+ isMobile={isMobile}
63
+ segmentVariants={variants}
64
+ serverConfig={serverConfig}
65
+ >
66
+ <QueryProvider>
67
+ <GroupWizardProvider>
68
+ <DragUploadProvider>
69
+ <LazyMotion features={domMax}>
70
+ <TooltipGroup layoutAnimation={false}>
71
+ <LobeAnalyticsProviderWrapper>{children}</LobeAnalyticsProviderWrapper>
72
+ </TooltipGroup>
73
+ <ModalHost />
74
+ <ContextMenuHost />
75
+ </LazyMotion>
76
+ </DragUploadProvider>
77
+ </GroupWizardProvider>
78
+ </QueryProvider>
79
+ <StoreInitialization />
80
+ <Suspense>
81
+ {ENABLE_BUSINESS_FEATURES ? <ReferralProvider /> : null}
82
+ <ImportSettings />
83
+ {process.env.NODE_ENV === 'development' && <DevPanel />}
84
+ </Suspense>
85
+ </ServerConfigStoreProvider>
86
+ </AppTheme>
87
+ </NextThemeProvider>
86
88
  </Locale>
87
89
  </StyleRegistry>
88
90
  );
@@ -1,5 +1,4 @@
1
1
  import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';
2
- import { parseDefaultThemeFromCountry } from '@lobechat/utils/server';
3
2
  import debug from 'debug';
4
3
  import { type NextRequest, NextResponse } from 'next/server';
5
4
  import { UAParser } from 'ua-parser-js';
@@ -8,7 +7,6 @@ import urlJoin from 'url-join';
8
7
  import { auth } from '@/auth';
9
8
  import { OAUTH_AUTHORIZED } from '@/const/auth';
10
9
  import { LOBE_LOCALE_COOKIE } from '@/const/locale';
11
- import { LOBE_THEME_APPEARANCE } from '@/const/theme';
12
10
  import { isDesktop } from '@/const/version';
13
11
  import { appEnv } from '@/envs/app';
14
12
  import { authEnv } from '@/envs/auth';
@@ -39,10 +37,6 @@ export function defineConfig() {
39
37
  return NextResponse.next();
40
38
  }
41
39
 
42
- // 1. Read user preferences from cookies
43
- const theme = (request.cookies.get(LOBE_THEME_APPEARANCE)?.value ||
44
- parseDefaultThemeFromCountry(request)) as 'dark' | 'light';
45
-
46
40
  // locale has three levels
47
41
  // 1. search params
48
42
  // 2. cookie
@@ -67,17 +61,14 @@ export function defineConfig() {
67
61
  deviceType: device.type,
68
62
  hasCookies: {
69
63
  locale: !!request.cookies.get(LOBE_LOCALE_COOKIE)?.value,
70
- theme: !!request.cookies.get(LOBE_THEME_APPEARANCE)?.value,
71
64
  },
72
65
  locale,
73
- theme,
74
66
  });
75
67
 
76
68
  // 2. Create normalized preference values
77
69
  const route = RouteVariants.serializeVariants({
78
70
  isMobile: device.type === 'mobile',
79
71
  locale,
80
- theme,
81
72
  });
82
73
 
83
74
  logDefault('Serialized route variant: %s', route);
@@ -99,8 +90,8 @@ export function defineConfig() {
99
90
 
100
91
  // refs: https://github.com/lobehub/lobe-chat/pull/5866
101
92
  // new handle segment rewrite: /${route}${originalPathname}
102
- // / -> /zh-CN__0__dark
103
- // /discover -> /zh-CN__0__dark/discover
93
+ // / -> /zh-CN__0
94
+ // /discover -> /zh-CN__0/discover
104
95
  // All SPA routes that use react-router-dom should be rewritten to just /${route}
105
96
  const spaRoutes = [
106
97
  '/chat',
@@ -408,19 +408,4 @@ describe('createPreferenceSlice', () => {
408
408
  expect(result.current.status.noWideScreen).toEqual(false);
409
409
  });
410
410
  });
411
-
412
- describe('switchThemeMode', () => {
413
- it('should switch theme mode', async () => {
414
- const { result } = renderHook(() => useGlobalStore());
415
-
416
- // Perform the action
417
- act(() => {
418
- useGlobalStore.setState({ isStatusInit: true });
419
- result.current.switchThemeMode('light');
420
- });
421
-
422
- // Assert that updateUserSettings was called with the correct theme mode
423
- expect(result.current.status.themeMode).toEqual('light');
424
- });
425
- });
426
411
  });
@@ -1,5 +1,4 @@
1
1
  import { act, renderHook } from '@testing-library/react';
2
- import { ThemeMode } from 'antd-style';
3
2
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
4
3
  import { withSWR } from '~test-utils';
5
4
 
@@ -117,42 +116,6 @@ describe('generalActionSlice', () => {
117
116
  });
118
117
  });
119
118
 
120
- describe('switchThemeMode', () => {
121
- it('should update theme mode in system status', () => {
122
- const { result } = renderHook(() => useGlobalStore());
123
- const themeMode: ThemeMode = 'dark';
124
-
125
- act(() => {
126
- useGlobalStore.setState({ isStatusInit: true });
127
- result.current.switchThemeMode(themeMode);
128
- });
129
-
130
- expect(result.current.status.themeMode).toBe(themeMode);
131
- });
132
-
133
- it('should not update theme mode if status is not initialized', () => {
134
- const { result } = renderHook(() => useGlobalStore());
135
- const themeMode: ThemeMode = 'dark';
136
-
137
- act(() => {
138
- result.current.switchThemeMode(themeMode);
139
- });
140
-
141
- expect(result.current.status.themeMode).toBe(initialState.status.themeMode);
142
- });
143
-
144
- it('should handle light theme mode', () => {
145
- const { result } = renderHook(() => useGlobalStore());
146
-
147
- act(() => {
148
- useGlobalStore.setState({ isStatusInit: true });
149
- result.current.switchThemeMode('light');
150
- });
151
-
152
- expect(result.current.status.themeMode).toBe('light');
153
- });
154
- });
155
-
156
119
  describe('useInitSystemStatus', () => {
157
120
  it('should reset transient UI states when loading from localStorage', async () => {
158
121
  const mockStatus = {
@@ -1,16 +1,13 @@
1
- import { type ThemeMode } from 'antd-style';
2
1
  import isEqual from 'fast-deep-equal';
3
2
  import { gt, parse, valid } from 'semver';
4
3
  import { type SWRResponse } from 'swr';
5
4
  import type { StateCreator } from 'zustand/vanilla';
6
5
 
7
- import { LOBE_THEME_APPEARANCE } from '@/const/theme';
8
6
  import { CURRENT_VERSION, isDesktop } from '@/const/version';
9
7
  import { useOnlyFetchOnceSWR } from '@/libs/swr';
10
8
  import { globalService } from '@/services/global';
11
9
  import type { SystemStatus } from '@/store/global/initialState';
12
10
  import { type LocaleMode } from '@/types/locale';
13
- import { setCookie } from '@/utils/client/cookie';
14
11
  import { switchLang } from '@/utils/client/switchLang';
15
12
  import { merge } from '@/utils/merge';
16
13
  import { setNamespace } from '@/utils/storeDebug';
@@ -23,7 +20,6 @@ export interface GlobalGeneralAction {
23
20
  openAgentInNewWindow: (agentId: string) => Promise<void>;
24
21
  openTopicInNewWindow: (agentId: string, topicId: string) => Promise<void>;
25
22
  switchLocale: (locale: LocaleMode, params?: { skipBroadcast?: boolean }) => void;
26
- switchThemeMode: (themeMode: ThemeMode, params?: { skipBroadcast?: boolean }) => void;
27
23
  updateSystemStatus: (status: Partial<SystemStatus>, action?: any) => void;
28
24
  useCheckLatestVersion: (enabledCheck?: boolean) => SWRResponse<string>;
29
25
  useInitSystemStatus: () => SWRResponse;
@@ -114,23 +110,6 @@ export const generalActionSlice: StateCreator<
114
110
  })();
115
111
  }
116
112
  },
117
- switchThemeMode: (themeMode, { skipBroadcast } = {}) => {
118
- get().updateSystemStatus({ themeMode });
119
-
120
- setCookie(LOBE_THEME_APPEARANCE, themeMode === 'auto' ? undefined : themeMode);
121
-
122
- if (isDesktop && !skipBroadcast) {
123
- (async () => {
124
- try {
125
- const { ensureElectronIpc } = await import('@/utils/electron/ipc');
126
-
127
- await ensureElectronIpc().system.updateThemeModeHandler(themeMode);
128
- } catch (error) {
129
- console.error('Failed to update theme in main process:', error);
130
- }
131
- })();
132
- }
133
- },
134
113
  updateSystemStatus: (status, action) => {
135
114
  if (!get().isStatusInit) return;
136
115
 
@@ -1,4 +1,3 @@
1
- import type { ThemeMode } from 'antd-style';
2
1
  import type { NavigateFunction } from 'react-router-dom';
3
2
 
4
3
  import { DatabaseLoadingState, type MigrationSQL, type MigrationTableItem } from '@/types/clientDB';
@@ -129,10 +128,6 @@ export interface SystemStatus {
129
128
  showRightPanel?: boolean;
130
129
  showSystemRole?: boolean;
131
130
  systemRoleExpandedMap: Record<string, boolean>;
132
- /**
133
- * theme mode
134
- */
135
- themeMode?: ThemeMode;
136
131
  /**
137
132
  * 是否使用短格式显示 token
138
133
  */
@@ -196,7 +191,6 @@ export const INITIAL_STATUS = {
196
191
  showRightPanel: true,
197
192
  showSystemRole: false,
198
193
  systemRoleExpandedMap: {},
199
- themeMode: 'auto',
200
194
  tokenDisplayFormatShort: true,
201
195
  topicPageSize: 20,
202
196
  zenMode: false,
@@ -87,24 +87,4 @@ describe('systemStatusSelectors', () => {
87
87
  expect(systemStatusSelectors.portalWidth(noPortalWidth)).toBe(400);
88
88
  });
89
89
  });
90
-
91
- describe('theme mode', () => {
92
- it('should return the correct theme', () => {
93
- const s: GlobalState = merge(initialState, {
94
- status: {
95
- themeMode: 'light',
96
- },
97
- });
98
- expect(systemStatusSelectors.themeMode(s)).toBe('light');
99
- });
100
-
101
- it('should return auto if not set', () => {
102
- const s: GlobalState = merge(initialState, {
103
- status: {
104
- themeMode: undefined,
105
- },
106
- });
107
- expect(systemStatusSelectors.themeMode(s)).toBe('auto');
108
- });
109
- });
110
90
  });
@@ -23,7 +23,6 @@ const showImagePanel = (s: GlobalState) => s.status.showImagePanel;
23
23
  const showImageTopicPanel = (s: GlobalState) => s.status.showImageTopicPanel;
24
24
  const hidePWAInstaller = (s: GlobalState) => s.status.hidePWAInstaller;
25
25
  const isShowCredit = (s: GlobalState) => s.status.isShowCredit;
26
- const themeMode = (s: GlobalState) => s.status.themeMode || 'auto';
27
26
  const language = (s: GlobalState) => s.status.language || 'auto';
28
27
 
29
28
  const showChatHeader = (s: GlobalState) => !s.status.zenMode;
@@ -80,7 +79,6 @@ export const systemStatusSelectors = {
80
79
  showRightPanel,
81
80
  showSystemRole,
82
81
  systemStatus,
83
- themeMode,
84
82
  tokenDisplayFormatShort,
85
83
  topicGroupKeys,
86
84
  topicPageSize,
@@ -16,8 +16,6 @@ export default ({ token }: { prefixCls: string; token: Theme }) => css`
16
16
  min-height: 100dvh;
17
17
  max-height: 100dvh;
18
18
 
19
- background: ${token.colorBgLayout};
20
-
21
19
  @media (min-device-width: 576px) {
22
20
  overflow: hidden;
23
21
  }