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

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 (81) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/apps/desktop/package.json +3 -2
  3. package/apps/desktop/src/main/const/store.ts +1 -1
  4. package/apps/desktop/src/main/controllers/SystemCtr.ts +2 -3
  5. package/apps/desktop/src/main/core/App.ts +10 -3
  6. package/apps/desktop/src/main/types/store.ts +1 -1
  7. package/changelog/v1.json +5 -0
  8. package/package.json +4 -3
  9. package/packages/builtin-tool-knowledge-base/src/client/Render/SearchKnowledgeBase/Item/index.tsx +4 -2
  10. package/packages/builtin-tool-local-system/src/client/Intervention/EditLocalFile/index.tsx +3 -2
  11. package/packages/builtin-tool-local-system/src/client/Render/EditLocalFile/index.tsx +3 -2
  12. package/packages/const/src/theme.ts +0 -2
  13. package/packages/desktop-bridge/src/routeVariants.ts +2 -9
  14. package/packages/electron-client-ipc/src/types/system.ts +1 -1
  15. package/scripts/electronWorkflow/modifiers/nextConfig.mts +41 -13
  16. package/src/app/[variants]/(auth)/_layout/index.tsx +3 -2
  17. package/src/app/[variants]/(auth)/_layout/style.ts +8 -18
  18. package/src/app/[variants]/(auth)/layout.tsx +7 -3
  19. package/src/app/[variants]/(desktop)/desktop-onboarding/_layout/index.tsx +4 -2
  20. package/src/app/[variants]/(desktop)/desktop-onboarding/_layout/style.ts +3 -0
  21. package/src/app/[variants]/(main)/_layout/DesktopLayoutContainer.tsx +3 -2
  22. package/src/app/[variants]/(main)/chat/profile/features/ProfileEditor/PluginTag.tsx +3 -2
  23. package/src/app/[variants]/(main)/community/(list)/_layout/Footer.tsx +3 -2
  24. package/src/app/[variants]/(main)/group/features/Conversation/ChatItem/Thread.tsx +3 -2
  25. package/src/app/[variants]/(main)/group/profile/features/AgentBuilder/index.tsx +0 -1
  26. package/src/app/[variants]/(main)/group/profile/features/ProfileEditor/PluginTag.tsx +3 -2
  27. package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/AgentItem/Editing.tsx +2 -2
  28. package/src/app/[variants]/(main)/home/_layout/Footer/index.tsx +1 -1
  29. package/src/app/[variants]/(main)/home/_layout/index.tsx +3 -2
  30. package/src/app/[variants]/(main)/home/features/CommunityAgents/Item.tsx +3 -2
  31. package/src/app/[variants]/(main)/image/_layout/ConfigPanel/components/AspectRatioSelect/index.tsx +4 -2
  32. package/src/app/[variants]/(main)/image/_layout/ConfigPanel/components/ModelSelect/ImageModelItem.tsx +3 -2
  33. package/src/app/[variants]/(main)/image/_layout/ConfigPanel/components/Select/index.tsx +4 -2
  34. package/src/app/[variants]/(main)/image/features/PromptInput/index.tsx +3 -2
  35. package/src/app/[variants]/(main)/memory/features/TimeLineView/index.tsx +9 -4
  36. package/src/app/[variants]/(main)/page/_layout/Body/List/Item/Editing.tsx +2 -2
  37. package/src/app/[variants]/(main)/settings/common/features/Common/Common.tsx +11 -11
  38. package/src/app/[variants]/(main)/settings/provider/(list)/ProviderGrid/Card.tsx +3 -2
  39. package/src/app/[variants]/(main)/settings/stats/features/overview/ShareButton/TotalCard.tsx +4 -2
  40. package/src/app/[variants]/(mobile)/me/(home)/features/Header.tsx +6 -8
  41. package/src/app/[variants]/layout.tsx +10 -15
  42. package/src/app/[variants]/onboarding/_layout/index.tsx +3 -2
  43. package/src/app/[variants]/onboarding/features/ModeSelectionStep.tsx +3 -2
  44. package/src/app/[variants]/router/index.tsx +12 -8
  45. package/src/components/Cell/Divider.tsx +4 -2
  46. package/src/components/DataStyleModal/index.tsx +4 -2
  47. package/src/components/FeatureList/index.tsx +4 -2
  48. package/src/components/FileParsingStatus/EmbeddingStatus.tsx +3 -2
  49. package/src/components/FileParsingStatus/index.tsx +3 -2
  50. package/src/components/Notification/index.tsx +4 -2
  51. package/src/components/client/ClientOnly.tsx +17 -0
  52. package/src/features/AlertBanner/CloudBanner.tsx +4 -3
  53. package/src/features/CommandMenu/ThemeMenu.tsx +1 -1
  54. package/src/features/CommandMenu/types.ts +5 -2
  55. package/src/features/CommandMenu/useCommandMenu.ts +3 -2
  56. package/src/features/Conversation/Markdown/plugins/LobeArtifact/Render/index.tsx +3 -2
  57. package/src/features/Conversation/Messages/components/FileChunks/ChunkItem.tsx +3 -2
  58. package/src/features/Conversation/Messages/components/FileChunks/index.tsx +4 -2
  59. package/src/features/Conversation/Messages/components/SearchGrounding.tsx +3 -2
  60. package/src/features/ElectronTitlebar/hooks/useWatchThemeUpdate.ts +21 -38
  61. package/src/features/GroupChatSettings/AgentCard.tsx +3 -2
  62. package/src/features/GroupChatSettings/HostMemberCard.tsx +3 -2
  63. package/src/features/PageEditor/DiffAllToolbar.tsx +4 -2
  64. package/src/features/User/UserPanel/ThemeButton.tsx +18 -29
  65. package/src/hooks/useIsDark.ts +11 -0
  66. package/src/layout/AuthProvider/Clerk/useAppearance.ts +4 -2
  67. package/src/layout/AuthProvider/MarketAuth/MarketAuthConfirmModal.tsx +3 -2
  68. package/src/layout/GlobalProvider/AppTheme.tsx +15 -19
  69. package/src/layout/GlobalProvider/NextThemeProvider.tsx +22 -0
  70. package/src/layout/GlobalProvider/StyleRegistry.tsx +18 -13
  71. package/src/layout/GlobalProvider/index.tsx +38 -36
  72. package/src/libs/next/proxy/define-config.ts +2 -11
  73. package/src/store/global/action.test.ts +0 -15
  74. package/src/store/global/actions/__tests__/general.test.ts +0 -37
  75. package/src/store/global/actions/general.ts +0 -21
  76. package/src/store/global/initialState.ts +0 -6
  77. package/src/store/global/selectors/systemStatus.test.ts +0 -20
  78. package/src/store/global/selectors/systemStatus.ts +0 -2
  79. package/src/styles/global.ts +0 -2
  80. package/src/utils/server/routeVariants.test.ts +17 -51
  81. package/src/utils/server/routeVariants.ts +0 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ## [Version 2.0.0-next.214](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.213...v2.0.0-next.214)
6
+
7
+ <sup>Released on **2026-01-05**</sup>
8
+
9
+ #### 🐛 Bug Fixes
10
+
11
+ - **electron**: Correct next config codemod pattern matching.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### What's fixed
19
+
20
+ - **electron**: Correct next config codemod pattern matching, closes [#11228](https://github.com/lobehub/lobe-chat/issues/11228) ([06cb019](https://github.com/lobehub/lobe-chat/commit/06cb019))
21
+
22
+ </details>
23
+
24
+ <div align="right">
25
+
26
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
27
+
28
+ </div>
29
+
5
30
  ## [Version 2.0.0-next.213](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.212...v2.0.0-next.213)
6
31
 
7
32
  <sup>Released on **2026-01-05**</sup>
@@ -18,6 +18,7 @@
18
18
  "build:mac:local": "npm run build && UPDATE_CHANNEL=nightly electron-builder --mac --config electron-builder.js --publish never",
19
19
  "build:win": "npm run build && electron-builder --win --config electron-builder.js --publish never",
20
20
  "dev": "electron-vite dev",
21
+ "dev:static": "cross-env DESKTOP_RENDERER_STATIC=1 npm run electron:dev",
21
22
  "electron:dev": "electron-vite dev",
22
23
  "electron:run-unpack": "electron .",
23
24
  "format": "prettier --write ",
@@ -57,11 +58,11 @@
57
58
  "@lobechat/file-loaders": "workspace:*",
58
59
  "@lobehub/i18n-cli": "^1.25.1",
59
60
  "@modelcontextprotocol/sdk": "^1.24.3",
61
+ "@t3-oss/env-core": "^0.13.8",
60
62
  "@types/async-retry": "^1.4.9",
61
63
  "@types/resolve": "^1.20.6",
62
64
  "@types/semver": "^7.7.1",
63
65
  "@types/set-cookie-parser": "^2.4.10",
64
- "@t3-oss/env-core": "^0.13.8",
65
66
  "@typescript/native-preview": "7.0.0-dev.20251210.1",
66
67
  "async-retry": "^1.3.3",
67
68
  "consola": "^3.4.2",
@@ -104,4 +105,4 @@
104
105
  "electron-builder"
105
106
  ]
106
107
  }
107
- }
108
+ }
@@ -31,5 +31,5 @@ export const STORE_DEFAULTS: ElectronMainStore = {
31
31
  networkProxy: defaultProxySettings,
32
32
  shortcuts: DEFAULT_SHORTCUTS_CONFIG,
33
33
  storagePath: appStorageDir,
34
- themeMode: 'auto',
34
+ themeMode: 'system',
35
35
  };
@@ -258,9 +258,8 @@ export default class SystemController extends ControllerModule {
258
258
  return nativeTheme.themeSource;
259
259
  }
260
260
 
261
- @IpcMethod()
262
- async setSystemThemeMode(themeMode: ThemeMode) {
263
- nativeTheme.themeSource = themeMode === 'auto' ? 'system' : themeMode;
261
+ private async setSystemThemeMode(themeMode: ThemeMode) {
262
+ nativeTheme.themeSource = themeMode;
264
263
  }
265
264
 
266
265
  /**
@@ -142,10 +142,17 @@ export class App {
142
142
  * This allows nativeTheme.shouldUseDarkColors to be used consistently everywhere
143
143
  */
144
144
  private initializeThemeMode() {
145
- const themeMode = this.storeManager.get('themeMode');
145
+ let themeMode = this.storeManager.get('themeMode');
146
+
147
+ // Migrate legacy 'auto' value to 'system' (nativeTheme.themeSource doesn't accept 'auto')
148
+ if (Object.is(themeMode, 'auto')) {
149
+ themeMode = 'system';
150
+ this.storeManager.set('themeMode', themeMode);
151
+ logger.info(`Migrated legacy theme mode 'auto' to 'system'`);
152
+ }
146
153
 
147
154
  if (themeMode) {
148
- nativeTheme.themeSource = themeMode === 'auto' ? 'system' : themeMode;
155
+ nativeTheme.themeSource = themeMode;
149
156
  logger.debug(
150
157
  `Theme mode initialized to: ${themeMode} (themeSource: ${nativeTheme.themeSource})`,
151
158
  );
@@ -401,4 +408,4 @@ export class App {
401
408
  // 执行清理操作
402
409
  this.staticFileServerManager.destroy();
403
410
  };
404
- }
411
+ }
@@ -11,7 +11,7 @@ export interface ElectronMainStore {
11
11
  networkProxy: NetworkProxySettings;
12
12
  shortcuts: Record<string, string>;
13
13
  storagePath: string;
14
- themeMode: 'dark' | 'light' | 'auto';
14
+ themeMode: 'dark' | 'light' | 'system';
15
15
  }
16
16
 
17
17
  export type StoreKey = keyof ElectronMainStore;
package/changelog/v1.json CHANGED
@@ -1,4 +1,9 @@
1
1
  [
2
+ {
3
+ "children": {},
4
+ "date": "2026-01-05",
5
+ "version": "2.0.0-next.214"
6
+ },
2
7
  {
3
8
  "children": {
4
9
  "improvements": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/lobehub",
3
- "version": "2.0.0-next.213",
3
+ "version": "2.0.0-next.214",
4
4
  "description": "LobeHub - an open-source,comprehensive AI Agent framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
5
5
  "keywords": [
6
6
  "framework",
@@ -205,7 +205,7 @@
205
205
  "@lobehub/icons": "^4.0.2",
206
206
  "@lobehub/market-sdk": "^0.25.1",
207
207
  "@lobehub/tts": "^4.0.2",
208
- "@lobehub/ui": "^4.8.0",
208
+ "@lobehub/ui": "^4.9.0",
209
209
  "@modelcontextprotocol/sdk": "^1.25.1",
210
210
  "@neondatabase/serverless": "^1.0.2",
211
211
  "@next/third-parties": "^16.1.1",
@@ -234,7 +234,7 @@
234
234
  "@zumer/snapdom": "^1.9.14",
235
235
  "ahooks": "^3.9.6",
236
236
  "antd": "^6.1.1",
237
- "antd-style": "^4.1.0",
237
+ "antd-style": "4.1.0",
238
238
  "async-retry": "^1.3.3",
239
239
  "bcryptjs": "^3.0.3",
240
240
  "better-auth": "1.4.6",
@@ -281,6 +281,7 @@
281
281
  "next": "^16.1.1",
282
282
  "next-auth": "5.0.0-beta.30",
283
283
  "next-mdx-remote": "^5.0.0",
284
+ "next-themes": "^0.4.6",
284
285
  "nextjs-toploader": "^3.9.17",
285
286
  "node-machine-id": "^1.1.12",
286
287
  "nodemailer": "^7.0.11",
@@ -2,7 +2,8 @@
2
2
 
3
3
  import { FileSearchResult } from '@lobechat/types';
4
4
  import { Center, Flexbox, MaterialFileTypeIcon, Text, Tooltip } from '@lobehub/ui';
5
- import { cx, useThemeMode } from 'antd-style';
5
+ import { cx } from 'antd-style';
6
+ import { useTheme } from 'next-themes';
6
7
  import { memo } from 'react';
7
8
 
8
9
  import { styles } from './style';
@@ -12,7 +13,8 @@ export interface FileItemProps extends FileSearchResult {
12
13
  }
13
14
 
14
15
  const FileItem = memo<FileItemProps>(({ fileId, fileName, relevanceScore }) => {
15
- const { isDarkMode } = useThemeMode();
16
+ const { resolvedTheme } = useTheme();
17
+ const isDarkMode = resolvedTheme === 'dark';
16
18
 
17
19
  return (
18
20
  <Flexbox
@@ -1,9 +1,9 @@
1
1
  import { type EditLocalFileParams } from '@lobechat/electron-client-ipc';
2
2
  import { type BuiltinInterventionProps } from '@lobechat/types';
3
3
  import { Flexbox, Icon, Skeleton, Text } from '@lobehub/ui';
4
- import { useThemeMode } from 'antd-style';
5
4
  import { createPatch } from 'diff';
6
5
  import { ChevronRight } from 'lucide-react';
6
+ import { useTheme } from 'next-themes';
7
7
  import path from 'path-browserify-esm';
8
8
  import React, { memo, useMemo } from 'react';
9
9
  import { Diff, Hunk, parseDiff } from 'react-diff-view';
@@ -29,7 +29,8 @@ const EditLocalFile = memo<BuiltinInterventionProps<EditLocalFileParams>>(({ arg
29
29
  },
30
30
  );
31
31
 
32
- const { isDarkMode } = useThemeMode();
32
+ const { resolvedTheme } = useTheme();
33
+ const isDarkMode = resolvedTheme === 'dark';
33
34
  // Generate diff from full file content
34
35
  const files = useMemo(() => {
35
36
  if (!fileData?.content) return [];
@@ -2,8 +2,8 @@ import { type EditLocalFileState } from '@lobechat/builtin-tool-local-system';
2
2
  import { type EditLocalFileParams } from '@lobechat/electron-client-ipc';
3
3
  import { type BuiltinRenderProps } from '@lobechat/types';
4
4
  import { Alert, Flexbox, Icon, Skeleton } from '@lobehub/ui';
5
- import { useThemeMode } from 'antd-style';
6
5
  import { ChevronRight } from 'lucide-react';
6
+ import { useTheme } from 'next-themes';
7
7
  import path from 'path-browserify-esm';
8
8
  import React, { memo, useMemo } from 'react';
9
9
  import { Diff, Hunk, parseDiff } from 'react-diff-view';
@@ -28,7 +28,8 @@ const EditLocalFile = memo<BuiltinRenderProps<EditLocalFileParams, EditLocalFile
28
28
  return [];
29
29
  }
30
30
  }, [pluginState?.diffText]);
31
- const { isDarkMode } = useThemeMode();
31
+ const { resolvedTheme } = useTheme();
32
+ const isDarkMode = resolvedTheme === 'dark';
32
33
 
33
34
  if (!args) return <Skeleton active />;
34
35
 
@@ -1,5 +1,3 @@
1
- export const LOBE_THEME_APPEARANCE = 'LOBE_THEME_APPEARANCE';
2
-
3
1
  export const LOBE_THEME_PRIMARY_COLOR = 'LOBE_THEME_PRIMARY_COLOR';
4
2
 
5
3
  export const LOBE_THEME_NEUTRAL_COLOR = 'LOBE_THEME_NEUTRAL_COLOR';
@@ -31,31 +31,26 @@ export interface IRouteVariants {
31
31
  locale: Locales;
32
32
  neutralColor?: string;
33
33
  primaryColor?: string;
34
- theme: 'dark' | 'light';
35
34
  }
36
35
 
37
- const SUPPORTED_THEMES = ['dark', 'light'] as const;
38
-
39
36
  export const DEFAULT_VARIANTS: IRouteVariants = {
40
37
  isMobile: false,
41
38
  locale: DEFAULT_LANG,
42
- theme: 'light',
43
39
  };
44
40
 
45
41
  const SPLITTER = '__';
46
42
 
47
43
  export class RouteVariants {
48
44
  static serializeVariants = (variants: IRouteVariants): string =>
49
- [variants.locale, Number(variants.isMobile), variants.theme].join(SPLITTER);
45
+ [variants.locale, Number(variants.isMobile)].join(SPLITTER);
50
46
 
51
47
  static deserializeVariants = (serialized: string): IRouteVariants => {
52
48
  try {
53
- const [locale, isMobile, theme] = serialized.split(SPLITTER);
49
+ const [locale, isMobile] = serialized.split(SPLITTER);
54
50
 
55
51
  return {
56
52
  isMobile: isMobile === '1',
57
53
  locale: RouteVariants.isValidLocale(locale) ? (locale as Locales) : DEFAULT_VARIANTS.locale,
58
- theme: RouteVariants.isValidTheme(theme) ? (theme as any) : DEFAULT_VARIANTS.theme,
59
54
  };
60
55
  } catch {
61
56
  return { ...DEFAULT_VARIANTS };
@@ -68,6 +63,4 @@ export class RouteVariants {
68
63
  });
69
64
 
70
65
  private static isValidLocale = (locale: string): boolean => locales.includes(locale as any);
71
-
72
- private static isValidTheme = (theme: string): boolean => SUPPORTED_THEMES.includes(theme as any);
73
66
  }
@@ -25,5 +25,5 @@ export interface UserPathData {
25
25
  videos?: string; // User's home directory
26
26
  }
27
27
 
28
- export type ThemeMode = 'auto' | 'dark' | 'light';
28
+ export type ThemeMode = 'system' | 'dark' | 'light';
29
29
  export type ThemeAppearance = 'dark' | 'light' | string;
@@ -40,13 +40,19 @@ export const modifyNextConfig = async (TEMP_DIR: string) => {
40
40
  }
41
41
 
42
42
  // 1. Remove redirects
43
- const redirectsPair = nextConfigDecl.find({
44
- rule: {
45
- pattern: 'redirects: $A',
46
- },
47
- });
48
- if (redirectsPair) {
49
- const range = redirectsPair.range();
43
+ const redirectsPair = nextConfigDecl
44
+ .findAll({
45
+ rule: {
46
+ kind: 'pair',
47
+ },
48
+ })
49
+ .find((node) => {
50
+ const text = node.text();
51
+ return text.startsWith('redirects:') || text.startsWith('redirects :');
52
+ });
53
+ invariant(redirectsPair, '[modifyNextConfig] redirects pair not found');
54
+ {
55
+ const range = redirectsPair!.range();
50
56
  edits.push({ end: range.end.index, start: range.start.index, text: '' });
51
57
  }
52
58
 
@@ -61,18 +67,39 @@ export const modifyNextConfig = async (TEMP_DIR: string) => {
61
67
  const text = node.text();
62
68
  return text.startsWith('async headers') || text.startsWith('headers');
63
69
  });
64
- if (headersMethod) {
65
- const range = headersMethod.range();
70
+ invariant(headersMethod, '[modifyNextConfig] headers method not found');
71
+ {
72
+ const range = headersMethod!.range();
73
+ edits.push({ end: range.end.index, start: range.start.index, text: '' });
74
+ }
75
+
76
+ // 3. Remove webVitalsAttribution
77
+ const webVitalsPair = nextConfigDecl
78
+ .findAll({
79
+ rule: {
80
+ kind: 'pair',
81
+ },
82
+ })
83
+ .find((node) => {
84
+ const text = node.text();
85
+ return (
86
+ text.startsWith('webVitalsAttribution:') || text.startsWith('webVitalsAttribution :')
87
+ );
88
+ });
89
+ invariant(webVitalsPair, '[modifyNextConfig] webVitalsAttribution pair not found');
90
+ {
91
+ const range = webVitalsPair!.range();
66
92
  edits.push({ end: range.end.index, start: range.start.index, text: '' });
67
93
  }
68
94
 
69
- // 3. Remove spread element
95
+ // 4. Remove spread element
70
96
  const spreads = nextConfigDecl.findAll({
71
97
  rule: {
72
98
  kind: 'spread_element',
73
99
  },
74
100
  });
75
101
 
102
+ // eslint-disable-next-line unicorn/consistent-function-scoping
76
103
  const isObjectLevelSpread = (node: any) => node.parent()?.kind() === 'object';
77
104
 
78
105
  const standaloneSpread = spreads.find((node) => {
@@ -84,12 +111,13 @@ export const modifyNextConfig = async (TEMP_DIR: string) => {
84
111
  const objectLevelSpread = standaloneSpread ? null : spreads.find(isObjectLevelSpread);
85
112
 
86
113
  const spreadToRemove = standaloneSpread || objectLevelSpread;
87
- if (spreadToRemove) {
88
- const range = spreadToRemove.range();
114
+ invariant(spreadToRemove, '[modifyNextConfig] spread element not found');
115
+ {
116
+ const range = spreadToRemove!.range();
89
117
  edits.push({ end: range.end.index, start: range.start.index, text: '' });
90
118
  }
91
119
 
92
- // 4. Inject/force output: 'export'
120
+ // 5. Inject/force output: 'export'
93
121
  const outputPair = nextConfigDecl.find({
94
122
  rule: {
95
123
  pattern: 'output: $A',
@@ -2,17 +2,18 @@
2
2
 
3
3
  import { Center, Flexbox, Text } from '@lobehub/ui';
4
4
  import { Divider } from 'antd';
5
- import { cx, useThemeMode } from 'antd-style';
5
+ import { cx } from 'antd-style';
6
6
  import type { FC, PropsWithChildren } from 'react';
7
7
 
8
8
  import { ProductLogo } from '@/components/Branding';
9
9
  import LangButton from '@/features/User/UserPanel/LangButton';
10
10
  import ThemeButton from '@/features/User/UserPanel/ThemeButton';
11
+ import { useIsDark } from '@/hooks/useIsDark';
11
12
 
12
13
  import { styles } from './style';
13
14
 
14
15
  const AuthContainer: FC<PropsWithChildren> = ({ children }) => {
15
- const { isDarkMode } = useThemeMode();
16
+ const isDarkMode = useIsDark();
16
17
  return (
17
18
  <Flexbox className={styles.outerContainer} height={'100%'} padding={8} width={'100%'}>
18
19
  <Flexbox
@@ -1,18 +1,13 @@
1
1
  import { createStaticStyles } from 'antd-style';
2
2
 
3
3
  export const styles = createStaticStyles(({ css, cssVar }) => ({
4
-
5
-
6
- // Divider 样式
7
- divider: css`
4
+ // Divider 样式
5
+ divider: css`
8
6
  height: 24px;
9
7
  `,
10
8
 
11
-
12
-
13
-
14
- // 内层容器 - 深色模式
15
- innerContainerDark: css`
9
+ // 内层容器 - 深色模式
10
+ innerContainerDark: css`
16
11
  position: relative;
17
12
 
18
13
  overflow: hidden;
@@ -23,11 +18,8 @@ innerContainerDark: css`
23
18
  background: ${cssVar.colorBgContainer};
24
19
  `,
25
20
 
26
-
27
-
28
-
29
- // 内层容器 - 浅色模式
30
- innerContainerLight: css`
21
+ // 内层容器 - 浅色模式
22
+ innerContainerLight: css`
31
23
  position: relative;
32
24
 
33
25
  overflow: hidden;
@@ -38,10 +30,8 @@ innerContainerLight: css`
38
30
  background: ${cssVar.colorBgContainer};
39
31
  `,
40
32
 
41
-
42
-
43
- // 外层容器
44
- outerContainer: css`
33
+ // 外层容器
34
+ outerContainer: css`
45
35
  position: relative;
46
36
  `,
47
37
  }));
@@ -1,13 +1,17 @@
1
1
  import { NuqsAdapter } from 'nuqs/adapters/next/app';
2
2
  import { type FC, type PropsWithChildren } from 'react';
3
3
 
4
+ import ClientOnly from '@/components/client/ClientOnly';
5
+
4
6
  import AuthContainer from './_layout';
5
7
 
6
8
  const AuthLayout: FC<PropsWithChildren> = ({ children }) => {
7
9
  return (
8
- <NuqsAdapter>
9
- <AuthContainer>{children}</AuthContainer>
10
- </NuqsAdapter>
10
+ <ClientOnly>
11
+ <NuqsAdapter>
12
+ <AuthContainer>{children}</AuthContainer>
13
+ </NuqsAdapter>
14
+ </ClientOnly>
11
15
  );
12
16
  };
13
17
 
@@ -2,16 +2,17 @@
2
2
 
3
3
  import { Center, Flexbox, Text } from '@lobehub/ui';
4
4
  import { Divider } from 'antd';
5
- import { cx, useThemeMode } from 'antd-style';
5
+ import { cx } from 'antd-style';
6
6
  import type { FC, PropsWithChildren } from 'react';
7
7
 
8
8
  import LangButton from '@/features/User/UserPanel/LangButton';
9
9
  import ThemeButton from '@/features/User/UserPanel/ThemeButton';
10
+ import { useIsDark } from '@/hooks/useIsDark';
10
11
 
11
12
  import { styles } from './style';
12
13
 
13
14
  const OnboardingContainer: FC<PropsWithChildren> = ({ children }) => {
14
- const { isDarkMode } = useThemeMode();
15
+ const isDarkMode = useIsDark();
15
16
  return (
16
17
  <Flexbox className={styles.outerContainer} height={'100%'} padding={8} width={'100%'}>
17
18
  <Flexbox
@@ -21,6 +22,7 @@ const OnboardingContainer: FC<PropsWithChildren> = ({ children }) => {
21
22
  >
22
23
  <Flexbox
23
24
  align={'center'}
25
+ className={cx(styles.drag)}
24
26
  gap={8}
25
27
  horizontal
26
28
  justify={'space-between'}
@@ -6,6 +6,9 @@ export const styles = createStaticStyles(({ css, cssVar }) => ({
6
6
  height: 24px;
7
7
  `,
8
8
 
9
+ drag: css`
10
+ -webkit-app-region: drag;
11
+ `,
9
12
  // 内层容器 - 深色模式
10
13
  innerContainerDark: css`
11
14
  position: relative;
@@ -1,15 +1,16 @@
1
1
  import { Flexbox } from '@lobehub/ui';
2
- import { cssVar, useThemeMode } from 'antd-style';
2
+ import { cssVar } from 'antd-style';
3
3
  import { type FC, type PropsWithChildren, useMemo } from 'react';
4
4
 
5
5
  import { isDesktop } from '@/const/version';
6
+ import { useIsDark } from '@/hooks/useIsDark';
6
7
  import { useGlobalStore } from '@/store/global';
7
8
  import { systemStatusSelectors } from '@/store/global/selectors';
8
9
 
9
10
  import { styles } from './DesktopLayoutContainer/style';
10
11
 
11
12
  const DesktopLayoutContainer: FC<PropsWithChildren> = ({ children }) => {
12
- const { isDarkMode } = useThemeMode();
13
+ const isDarkMode = useIsDark();
13
14
  const [expand] = useGlobalStore((s) => [systemStatusSelectors.showLeftPanel(s)]);
14
15
 
15
16
  // CSS 变量用于动态样式
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { KLAVIS_SERVER_TYPES, type KlavisServerType } from '@lobechat/const';
4
4
  import { Avatar, Icon, Tag } from '@lobehub/ui';
5
- import { createStaticStyles, cssVar, useThemeMode } from 'antd-style';
5
+ import { createStaticStyles, cssVar } from 'antd-style';
6
6
  import isEqual from 'fast-deep-equal';
7
7
  import { AlertCircle, X } from 'lucide-react';
8
8
  import Image from 'next/image';
@@ -10,6 +10,7 @@ import React, { memo, useMemo } from 'react';
10
10
  import { useTranslation } from 'react-i18next';
11
11
 
12
12
  import PluginAvatar from '@/components/Plugins/PluginAvatar';
13
+ import { useIsDark } from '@/hooks/useIsDark';
13
14
  import { useDiscoverStore } from '@/store/discover';
14
15
  import { serverConfigSelectors, useServerConfigStore } from '@/store/serverConfig';
15
16
  import { useToolStore } from '@/store/tool';
@@ -53,7 +54,7 @@ interface PluginTagProps {
53
54
  }
54
55
 
55
56
  const PluginTag = memo<PluginTagProps>(({ pluginId, onRemove }) => {
56
- const { isDarkMode } = useThemeMode();
57
+ const isDarkMode = useIsDark();
57
58
  const { t } = useTranslation('setting');
58
59
 
59
60
  // Extract identifier
@@ -1,9 +1,10 @@
1
1
  import { Button, Flexbox, Text } from '@lobehub/ui';
2
- import { createStaticStyles, cx, useThemeMode } from 'antd-style';
2
+ import { createStaticStyles, cx } from 'antd-style';
3
3
  import { memo, useCallback, useState } from 'react';
4
4
  import { useTranslation } from 'react-i18next';
5
5
 
6
6
  import DefaultFooter from '@/features/Setting/Footer';
7
+ import { useIsDark } from '@/hooks/useIsDark';
7
8
  import { useMarketAuth } from '@/layout/AuthProvider/MarketAuth';
8
9
 
9
10
  const styles = createStaticStyles(({ css }) => ({
@@ -27,7 +28,7 @@ const styles = createStaticStyles(({ css }) => ({
27
28
 
28
29
  const Footer = memo(() => {
29
30
  const { t } = useTranslation('discover');
30
- const { isDarkMode } = useThemeMode();
31
+ const isDarkMode = useIsDark();
31
32
  const { isAuthenticated, signIn } = useMarketAuth();
32
33
  const [loading, setLoading] = useState(false);
33
34
  const handleSignIn = useCallback(async () => {
@@ -1,9 +1,10 @@
1
1
  import { Flexbox, Text } from '@lobehub/ui';
2
- import { createStaticStyles, cx, useThemeMode } from 'antd-style';
2
+ import { createStaticStyles, cx } from 'antd-style';
3
3
  import isEqual from 'fast-deep-equal';
4
4
  import { type CSSProperties, memo } from 'react';
5
5
  import { useTranslation } from 'react-i18next';
6
6
 
7
+ import { useIsDark } from '@/hooks/useIsDark';
7
8
  import { useChatStore } from '@/store/chat';
8
9
  import { threadSelectors } from '@/store/chat/selectors';
9
10
 
@@ -32,7 +33,7 @@ interface ThreadProps {
32
33
 
33
34
  const Thread = memo<ThreadProps>(({ id, placement, style }) => {
34
35
  const { t } = useTranslation('chat');
35
- const { isDarkMode } = useThemeMode();
36
+ const isDarkMode = useIsDark();
36
37
 
37
38
  const threads = useChatStore(threadSelectors.getThreadsBySourceMsgId(id), isEqual);
38
39
 
@@ -16,7 +16,6 @@ const AgentBuilder = memo(() => {
16
16
  const setChatPanelExpanded = useProfileStore((s) => s.setChatPanelExpanded);
17
17
  const groupAgentBuilderId = useAgentStore(builtinAgentSelectors.groupAgentBuilderId);
18
18
 
19
- console.log('groupAgentBuilderId', groupAgentBuilderId);
20
19
  const [width, setWidth] = useState<string | number>(360);
21
20
 
22
21
  const useInitBuiltinAgent = useAgentStore((s) => s.useInitBuiltinAgent);
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { KLAVIS_SERVER_TYPES, type KlavisServerType } from '@lobechat/const';
4
4
  import { Avatar, Icon, Tag } from '@lobehub/ui';
5
- import { createStaticStyles, cssVar, useThemeMode } from 'antd-style';
5
+ import { createStaticStyles, cssVar } from 'antd-style';
6
6
  import isEqual from 'fast-deep-equal';
7
7
  import { AlertCircle, X } from 'lucide-react';
8
8
  import Image from 'next/image';
@@ -10,6 +10,7 @@ import React, { memo, useMemo } from 'react';
10
10
  import { useTranslation } from 'react-i18next';
11
11
 
12
12
  import PluginAvatar from '@/components/Plugins/PluginAvatar';
13
+ import { useIsDark } from '@/hooks/useIsDark';
13
14
  import { useDiscoverStore } from '@/store/discover';
14
15
  import { serverConfigSelectors, useServerConfigStore } from '@/store/serverConfig';
15
16
  import { useToolStore } from '@/store/tool';
@@ -53,7 +54,7 @@ interface PluginTagProps {
53
54
  }
54
55
 
55
56
  const PluginTag = memo<PluginTagProps>(({ pluginId, onRemove }) => {
56
- const { isDarkMode } = useThemeMode();
57
+ const isDarkMode = useIsDark();
57
58
  const { t } = useTranslation('setting');
58
59
 
59
60
  // Extract identifier
@@ -1,9 +1,9 @@
1
1
  import { Avatar, Block, Flexbox, Input } from '@lobehub/ui';
2
2
  import { Popover } from 'antd';
3
- import { useThemeMode } from 'antd-style';
4
3
  import { memo, useCallback, useState } from 'react';
5
4
 
6
5
  import EmojiPicker from '@/components/EmojiPicker';
6
+ import { useIsDark } from '@/hooks/useIsDark';
7
7
  import { useAgentStore } from '@/store/agent';
8
8
  import { useGlobalStore } from '@/store/global';
9
9
  import { globalGeneralSelectors } from '@/store/global/selectors';
@@ -18,7 +18,7 @@ interface EditingProps {
18
18
 
19
19
  const Editing = memo<EditingProps>(({ id, title, avatar, toggleEditing }) => {
20
20
  const locale = useGlobalStore(globalGeneralSelectors.currentLanguage);
21
- const { isDarkMode } = useThemeMode();
21
+ const isDarkMode = useIsDark();
22
22
 
23
23
  const editing = useHomeStore((s) => s.agentRenamingId === id);
24
24
 
@@ -118,7 +118,7 @@ const Footer = memo(() => {
118
118
  </a>
119
119
  )}
120
120
  </Flexbox>
121
- <ThemeButton placement={'top'} size={16} />
121
+ <ThemeButton placement={'topCenter'} size={16} />
122
122
  </Flexbox>
123
123
  <LabsModal onClose={handleCloseLabsModal} open={isLabsModalOpen} />
124
124
  <ChangelogModal