@lobehub/lobehub 2.0.0-next.212 → 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 (152) hide show
  1. package/.github/workflows/auto-i18n.yml +1 -1
  2. package/.github/workflows/bundle-analyzer.yml +1 -1
  3. package/.github/workflows/claude-auto-testing.yml +1 -1
  4. package/.github/workflows/claude-dedupe-issues.yml +1 -1
  5. package/.github/workflows/claude-issue-triage.yml +1 -1
  6. package/.github/workflows/claude-translate-comments.yml +1 -1
  7. package/.github/workflows/claude-translator.yml +1 -1
  8. package/.github/workflows/claude.yml +1 -1
  9. package/.github/workflows/desktop-build-electron.yml +2 -2
  10. package/.github/workflows/e2e.yml +1 -1
  11. package/.github/workflows/issue-auto-close-duplicates.yml +1 -1
  12. package/.github/workflows/lighthouse.yml +2 -2
  13. package/.github/workflows/lock-closed-issues.yml +1 -1
  14. package/.github/workflows/manual-build-desktop.yml +6 -6
  15. package/.github/workflows/pr-build-desktop.yml +5 -5
  16. package/.github/workflows/pr-build-docker.yml +2 -2
  17. package/.github/workflows/release-desktop-beta.yml +4 -4
  18. package/.github/workflows/release-docker.yml +2 -2
  19. package/.github/workflows/release.yml +1 -1
  20. package/.github/workflows/sync-database-schema.yml +1 -1
  21. package/.github/workflows/sync.yml +1 -1
  22. package/.github/workflows/test.yml +5 -5
  23. package/.github/workflows/verify-desktop-patch.yml +1 -1
  24. package/CHANGELOG.md +58 -0
  25. package/apps/desktop/package.json +3 -2
  26. package/apps/desktop/src/main/const/store.ts +1 -1
  27. package/apps/desktop/src/main/controllers/SystemCtr.ts +2 -3
  28. package/apps/desktop/src/main/core/App.ts +10 -3
  29. package/apps/desktop/src/main/types/store.ts +1 -1
  30. package/changelog/v1.json +14 -0
  31. package/locales/ar/models.json +35 -4
  32. package/locales/ar/providers.json +1 -0
  33. package/locales/bg-BG/models.json +24 -1
  34. package/locales/bg-BG/providers.json +1 -0
  35. package/locales/de-DE/models.json +30 -1
  36. package/locales/de-DE/providers.json +1 -0
  37. package/locales/en-US/models.json +1 -0
  38. package/locales/en-US/providers.json +1 -0
  39. package/locales/es-ES/models.json +32 -1
  40. package/locales/es-ES/providers.json +1 -0
  41. package/locales/fa-IR/models.json +48 -1
  42. package/locales/fa-IR/providers.json +1 -0
  43. package/locales/fr-FR/models.json +47 -1
  44. package/locales/fr-FR/providers.json +1 -0
  45. package/locales/it-IT/models.json +32 -1
  46. package/locales/it-IT/providers.json +1 -0
  47. package/locales/ja-JP/models.json +2 -1
  48. package/locales/ja-JP/providers.json +1 -0
  49. package/locales/ko-KR/models.json +24 -1
  50. package/locales/ko-KR/providers.json +1 -0
  51. package/locales/nl-NL/models.json +46 -1
  52. package/locales/nl-NL/providers.json +1 -0
  53. package/locales/pl-PL/models.json +41 -1
  54. package/locales/pl-PL/providers.json +1 -0
  55. package/locales/pt-BR/models.json +32 -1
  56. package/locales/pt-BR/providers.json +1 -0
  57. package/locales/ru-RU/models.json +54 -2
  58. package/locales/ru-RU/providers.json +1 -0
  59. package/locales/tr-TR/models.json +32 -1
  60. package/locales/tr-TR/providers.json +1 -0
  61. package/locales/vi-VN/models.json +37 -1
  62. package/locales/vi-VN/providers.json +1 -0
  63. package/locales/zh-CN/models.json +24 -3
  64. package/locales/zh-CN/providers.json +1 -0
  65. package/locales/zh-TW/models.json +11 -1
  66. package/locales/zh-TW/providers.json +1 -0
  67. package/package.json +4 -3
  68. package/packages/builtin-tool-knowledge-base/src/client/Render/SearchKnowledgeBase/Item/index.tsx +4 -2
  69. package/packages/builtin-tool-local-system/src/client/Intervention/EditLocalFile/index.tsx +3 -2
  70. package/packages/builtin-tool-local-system/src/client/Render/EditLocalFile/index.tsx +3 -2
  71. package/packages/const/src/theme.ts +0 -2
  72. package/packages/context-engine/src/engine/messages/types.ts +1 -1
  73. package/packages/desktop-bridge/src/routeVariants.ts +2 -9
  74. package/packages/electron-client-ipc/src/types/system.ts +1 -1
  75. package/packages/model-runtime/src/core/BaseAI.ts +1 -1
  76. package/packages/model-runtime/src/core/streams/qwen.test.ts +140 -0
  77. package/packages/model-runtime/src/core/streams/qwen.ts +17 -5
  78. package/packages/model-runtime/src/types/chat.ts +12 -12
  79. package/packages/model-runtime/src/types/error.ts +1 -1
  80. package/packages/model-runtime/src/types/image.ts +1 -1
  81. package/scripts/electronWorkflow/modifiers/nextConfig.mts +41 -13
  82. package/src/app/[variants]/(auth)/_layout/index.tsx +3 -2
  83. package/src/app/[variants]/(auth)/_layout/style.ts +8 -18
  84. package/src/app/[variants]/(auth)/layout.tsx +7 -3
  85. package/src/app/[variants]/(desktop)/desktop-onboarding/_layout/index.tsx +4 -2
  86. package/src/app/[variants]/(desktop)/desktop-onboarding/_layout/style.ts +3 -0
  87. package/src/app/[variants]/(main)/_layout/DesktopLayoutContainer.tsx +3 -2
  88. package/src/app/[variants]/(main)/chat/features/Conversation/Header/index.tsx +2 -1
  89. package/src/app/[variants]/(main)/chat/profile/features/ProfileEditor/PluginTag.tsx +3 -2
  90. package/src/app/[variants]/(main)/community/(list)/_layout/Footer.tsx +3 -2
  91. package/src/app/[variants]/(main)/group/features/Conversation/ChatItem/Thread.tsx +3 -2
  92. package/src/app/[variants]/(main)/group/profile/features/AgentBuilder/index.tsx +0 -1
  93. package/src/app/[variants]/(main)/group/profile/features/ProfileEditor/PluginTag.tsx +3 -2
  94. package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/AgentItem/Editing.tsx +2 -2
  95. package/src/app/[variants]/(main)/home/_layout/Footer/index.tsx +1 -1
  96. package/src/app/[variants]/(main)/home/_layout/index.tsx +3 -2
  97. package/src/app/[variants]/(main)/home/features/CommunityAgents/Item.tsx +3 -2
  98. package/src/app/[variants]/(main)/image/_layout/ConfigPanel/components/AspectRatioSelect/index.tsx +4 -2
  99. package/src/app/[variants]/(main)/image/_layout/ConfigPanel/components/ModelSelect/ImageModelItem.tsx +3 -2
  100. package/src/app/[variants]/(main)/image/_layout/ConfigPanel/components/Select/index.tsx +4 -2
  101. package/src/app/[variants]/(main)/image/features/PromptInput/index.tsx +3 -2
  102. package/src/app/[variants]/(main)/memory/features/TimeLineView/index.tsx +9 -4
  103. package/src/app/[variants]/(main)/page/_layout/Body/List/Item/Editing.tsx +2 -2
  104. package/src/app/[variants]/(main)/settings/common/features/Common/Common.tsx +11 -11
  105. package/src/app/[variants]/(main)/settings/provider/(list)/ProviderGrid/Card.tsx +3 -2
  106. package/src/app/[variants]/(main)/settings/stats/features/overview/ShareButton/TotalCard.tsx +4 -2
  107. package/src/app/[variants]/(mobile)/me/(home)/features/Header.tsx +6 -8
  108. package/src/app/[variants]/layout.tsx +10 -15
  109. package/src/app/[variants]/onboarding/_layout/index.tsx +3 -2
  110. package/src/app/[variants]/onboarding/features/ModeSelectionStep.tsx +3 -2
  111. package/src/app/[variants]/router/index.tsx +12 -8
  112. package/src/components/Cell/Divider.tsx +4 -2
  113. package/src/components/DataStyleModal/index.tsx +4 -2
  114. package/src/components/FeatureList/index.tsx +4 -2
  115. package/src/components/FileParsingStatus/EmbeddingStatus.tsx +3 -2
  116. package/src/components/FileParsingStatus/index.tsx +3 -2
  117. package/src/components/Notification/index.tsx +4 -2
  118. package/src/components/client/ClientOnly.tsx +17 -0
  119. package/src/features/AlertBanner/CloudBanner.tsx +4 -3
  120. package/src/features/CommandMenu/ThemeMenu.tsx +1 -1
  121. package/src/features/CommandMenu/types.ts +5 -2
  122. package/src/features/CommandMenu/useCommandMenu.ts +3 -2
  123. package/src/features/Conversation/Markdown/plugins/LobeArtifact/Render/index.tsx +3 -2
  124. package/src/features/Conversation/Messages/components/FileChunks/ChunkItem.tsx +3 -2
  125. package/src/features/Conversation/Messages/components/FileChunks/index.tsx +4 -2
  126. package/src/features/Conversation/Messages/components/SearchGrounding.tsx +3 -2
  127. package/src/features/ElectronTitlebar/hooks/useWatchThemeUpdate.ts +21 -38
  128. package/src/features/GroupChatSettings/AgentCard.tsx +3 -2
  129. package/src/features/GroupChatSettings/HostMemberCard.tsx +3 -2
  130. package/src/features/PageEditor/DiffAllToolbar.tsx +4 -2
  131. package/src/features/User/UserPanel/ThemeButton.tsx +18 -29
  132. package/src/hooks/useIsDark.ts +11 -0
  133. package/src/layout/AuthProvider/Clerk/useAppearance.ts +4 -2
  134. package/src/layout/AuthProvider/MarketAuth/MarketAuthConfirmModal.tsx +3 -2
  135. package/src/layout/GlobalProvider/AppTheme.tsx +15 -19
  136. package/src/layout/GlobalProvider/NextThemeProvider.tsx +22 -0
  137. package/src/layout/GlobalProvider/StyleRegistry.tsx +18 -13
  138. package/src/layout/GlobalProvider/index.tsx +38 -36
  139. package/src/libs/next/proxy/define-config.ts +2 -11
  140. package/src/server/services/comfyui/config/constants.ts +7 -7
  141. package/src/server/services/comfyui/config/promptToolConst.ts +26 -26
  142. package/src/server/services/comfyui/utils/promptSplitter.ts +23 -23
  143. package/src/server/services/comfyui/utils/weightDType.ts +4 -5
  144. package/src/store/global/action.test.ts +0 -15
  145. package/src/store/global/actions/__tests__/general.test.ts +0 -37
  146. package/src/store/global/actions/general.ts +0 -21
  147. package/src/store/global/initialState.ts +0 -6
  148. package/src/store/global/selectors/systemStatus.test.ts +0 -20
  149. package/src/store/global/selectors/systemStatus.ts +0 -2
  150. package/src/styles/global.ts +0 -2
  151. package/src/utils/server/routeVariants.test.ts +17 -51
  152. package/src/utils/server/routeVariants.ts +0 -1
@@ -23,7 +23,7 @@ export const StandardErrorType = {
23
23
  export type ErrorType = (typeof StandardErrorType)[keyof typeof StandardErrorType];
24
24
 
25
25
  /**
26
- * 聊天消息错误对象
26
+ * Chat message error object
27
27
  */
28
28
  export interface ChatMessageError {
29
29
  body?: any;
@@ -34,7 +34,7 @@ export type CreateImageResponse = {
34
34
  modelUsage?: ModelUsage;
35
35
  };
36
36
 
37
- // 新增:支持认证图片下载的运行时接口
37
+ // New: Runtime interface for authenticated image download support
38
38
  export interface AuthenticatedImageRuntime {
39
39
  /**
40
40
  * Get authentication headers for image download
@@ -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 变量用于动态样式
@@ -1,5 +1,6 @@
1
1
  'use client';
2
2
 
3
+ import { isDesktop } from '@lobechat/const';
3
4
  import { Flexbox } from '@lobehub/ui';
4
5
  import { cssVar } from 'antd-style';
5
6
  import { memo } from 'react';
@@ -22,7 +23,7 @@ const Header = memo(() => {
22
23
  }
23
24
  right={
24
25
  <Flexbox align={'center'} horizontal style={{ backgroundColor: cssVar.colorBgContainer }}>
25
- <WorkingDirectory />
26
+ {isDesktop && <WorkingDirectory />}
26
27
  <NotebookButton />
27
28
  <ShareButton />
28
29
  <HeaderActions />
@@ -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
@@ -1,8 +1,9 @@
1
1
  import { Flexbox } from '@lobehub/ui';
2
- import { useTheme, useThemeMode } from 'antd-style';
2
+ import { useTheme } from 'antd-style';
3
3
  import { Activity, type FC, type ReactNode, useEffect, useMemo, useState } from 'react';
4
4
  import { Outlet, useLocation, useNavigate } from 'react-router-dom';
5
5
 
6
+ import { useIsDark } from '@/hooks/useIsDark';
6
7
  import { useHomeStore } from '@/store/home';
7
8
 
8
9
  import RecentHydration from './RecentHydration';
@@ -14,7 +15,7 @@ interface LayoutProps {
14
15
  }
15
16
 
16
17
  const Layout: FC<LayoutProps> = ({ children }) => {
17
- const { isDarkMode } = useThemeMode();
18
+ const isDarkMode = useIsDark();
18
19
  const theme = useTheme(); // Keep for colorBgContainerSecondary (not in cssVar)
19
20
  const navigate = useNavigate();
20
21
  const { pathname } = useLocation();
@@ -1,14 +1,15 @@
1
1
  import { Avatar, Block, Flexbox, Text } from '@lobehub/ui';
2
- import { cssVar, useThemeMode } from 'antd-style';
2
+ import { cssVar } from 'antd-style';
3
3
  import { memo } from 'react';
4
4
 
5
5
  import { RECENT_BLOCK_SIZE } from '@/app/[variants]/(main)/home/features/const';
6
6
  import { DEFAULT_AVATAR } from '@/const/meta';
7
+ import { useIsDark } from '@/hooks/useIsDark';
7
8
  import { type DiscoverAssistantItem } from '@/types/discover';
8
9
 
9
10
  const CommunityAgentItem = memo<DiscoverAssistantItem>(
10
11
  ({ title, avatar, backgroundColor, author, description }) => {
11
- const { isDarkMode } = useThemeMode();
12
+ const isDarkMode = useIsDark();
12
13
 
13
14
  return (
14
15
  <Block
@@ -1,10 +1,12 @@
1
1
  'use client';
2
2
 
3
3
  import { Block, Center, Grid, type GridProps, Text } from '@lobehub/ui';
4
- import { cssVar, useThemeMode } from 'antd-style';
4
+ import { cssVar } from 'antd-style';
5
5
  import { memo } from 'react';
6
6
  import useMergeState from 'use-merge-value';
7
7
 
8
+ import { useIsDark } from '@/hooks/useIsDark';
9
+
8
10
  export interface AspectRatioSelectProps extends Omit<GridProps, 'children' | 'onChange'> {
9
11
  defaultValue?: string;
10
12
  onChange?: (value: string) => void;
@@ -14,7 +16,7 @@ export interface AspectRatioSelectProps extends Omit<GridProps, 'children' | 'on
14
16
 
15
17
  const AspectRatioSelect = memo<AspectRatioSelectProps>(
16
18
  ({ options, onChange, value, defaultValue, ...rest }) => {
17
- const { isDarkMode } = useThemeMode();
19
+ const isDarkMode = useIsDark();
18
20
  const [active, setActive] = useMergeState('1:1', {
19
21
  defaultValue: defaultValue || '1:1',
20
22
  onChange,
@@ -1,12 +1,13 @@
1
1
  import { ModelIcon } from '@lobehub/icons';
2
2
  import { Flexbox, Text } from '@lobehub/ui';
3
3
  import { Popover } from 'antd';
4
- import { createStaticStyles, cx, useThemeMode } from 'antd-style';
4
+ import { createStaticStyles, cx } from 'antd-style';
5
5
  import { type AiModelForSelect } from 'model-bank';
6
6
  import numeral from 'numeral';
7
7
  import { memo, useMemo } from 'react';
8
8
 
9
9
  import NewModelBadge from '@/components/ModelSelect/NewModelBadge';
10
+ import { useIsDark } from '@/hooks/useIsDark';
10
11
 
11
12
  const POPOVER_MAX_WIDTH = 320;
12
13
 
@@ -59,7 +60,7 @@ const ImageModelItem = memo<ImageModelItemProps>(
59
60
  showBadge = true,
60
61
  ...model
61
62
  }) => {
62
- const { isDarkMode } = useThemeMode();
63
+ const isDarkMode = useIsDark();
63
64
 
64
65
  const priceLabel = useMemo(() => {
65
66
  // Priority 1: Use exact price
@@ -1,10 +1,12 @@
1
1
  'use client';
2
2
 
3
3
  import { Block, Center, Grid, type GridProps, Select, Text } from '@lobehub/ui';
4
- import { cssVar, useThemeMode } from 'antd-style';
4
+ import { cssVar } from 'antd-style';
5
5
  import { type ReactNode, memo } from 'react';
6
6
  import useMergeState from 'use-merge-value';
7
7
 
8
+ import { useIsDark } from '@/hooks/useIsDark';
9
+
8
10
  export interface SizeSelectProps extends Omit<GridProps, 'children' | 'onChange'> {
9
11
  defaultValue?: 'auto' | string;
10
12
  onChange?: (value: string) => void;
@@ -26,7 +28,7 @@ const canParseAsRatio = (value: string): boolean => {
26
28
  };
27
29
 
28
30
  const SizeSelect = memo<SizeSelectProps>(({ options, onChange, value, defaultValue, ...rest }) => {
29
- const { isDarkMode } = useThemeMode();
31
+ const isDarkMode = useIsDark();
30
32
  const [active, setActive] = useMergeState('auto', {
31
33
  defaultValue,
32
34
  onChange,
@@ -2,13 +2,14 @@
2
2
 
3
3
  import { ChatInput } from '@lobehub/editor/react';
4
4
  import { Button, Flexbox, TextArea } from '@lobehub/ui';
5
- import { createStaticStyles, cx, useThemeMode } from 'antd-style';
5
+ import { createStaticStyles, cx } from 'antd-style';
6
6
  import { Sparkles } from 'lucide-react';
7
7
  import type { KeyboardEvent } from 'react';
8
8
  import { useTranslation } from 'react-i18next';
9
9
 
10
10
  import { loginRequired } from '@/components/Error/loginRequiredNotification';
11
11
  import { useGeminiChineseWarning } from '@/hooks/useGeminiChineseWarning';
12
+ import { useIsDark } from '@/hooks/useIsDark';
12
13
  import { useImageStore } from '@/store/image';
13
14
  import { createImageSelectors } from '@/store/image/selectors';
14
15
  import { useGenerationConfigParam } from '@/store/image/slices/generationConfig/hooks';
@@ -39,7 +40,7 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
39
40
  }));
40
41
 
41
42
  const PromptInput = ({ showTitle = false }: PromptInputProps) => {
42
- const { isDarkMode } = useThemeMode();
43
+ const isDarkMode = useIsDark();
43
44
  const { t } = useTranslation('image');
44
45
  const { value, setValue } = useGenerationConfigParam('prompt');
45
46
  const isCreating = useImageStore(createImageSelectors.isCreating);
@@ -1,11 +1,12 @@
1
1
  'use client';
2
2
 
3
- import { createStaticStyles, cx, useThemeMode } from 'antd-style';
3
+ import { createStaticStyles, cx } from 'antd-style';
4
4
  import dayjs from 'dayjs';
5
5
  import { type ReactNode, memo, useMemo } from 'react';
6
6
  import { GroupedVirtuoso } from 'react-virtuoso';
7
7
 
8
8
  import Loading from '@/app/[variants]/(main)/memory/features/Loading';
9
+ import { useIsDark } from '@/hooks/useIsDark';
9
10
 
10
11
  import { useScrollParent } from './useScrollParent';
11
12
 
@@ -31,7 +32,9 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
31
32
 
32
33
  export type GroupBy = 'day' | 'month';
33
34
 
34
- interface TimelineViewProps<T extends { capturedAt?: Date | string; createdAt?: Date | string; id: string }> {
35
+ interface TimelineViewProps<
36
+ T extends { capturedAt?: Date | string; createdAt?: Date | string; id: string },
37
+ > {
35
38
  data: T[];
36
39
  /**
37
40
  * Custom date field extractor for grouping
@@ -68,7 +71,9 @@ const getDateValue = <T extends { capturedAt?: Date | string; createdAt?: Date |
68
71
  return item.capturedAt ?? item.createdAt ?? new Date();
69
72
  };
70
73
 
71
- function TimelineViewInner<T extends { capturedAt?: Date | string; createdAt?: Date | string; id: string }>({
74
+ function TimelineViewInner<
75
+ T extends { capturedAt?: Date | string; createdAt?: Date | string; id: string },
76
+ >({
72
77
  data,
73
78
  groupBy = 'day',
74
79
  getDateForGrouping,
@@ -78,7 +83,7 @@ function TimelineViewInner<T extends { capturedAt?: Date | string; createdAt?: D
78
83
  renderHeader,
79
84
  renderItem,
80
85
  }: TimelineViewProps<T>) {
81
- const { isDarkMode } = useThemeMode();
86
+ const isDarkMode = useIsDark();
82
87
  const scrollParent = useScrollParent();
83
88
 
84
89
  const { groupCounts, sortedPeriods, groupedItems } = useMemo(() => {
@@ -1,10 +1,10 @@
1
1
  import { 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
  import { useTranslation } from 'react-i18next';
6
5
 
7
6
  import EmojiPicker from '@/components/EmojiPicker';
7
+ import { useIsDark } from '@/hooks/useIsDark';
8
8
  import { useFileStore } from '@/store/file';
9
9
  import { useGlobalStore } from '@/store/global';
10
10
  import { globalGeneralSelectors } from '@/store/global/selectors';
@@ -18,7 +18,7 @@ interface EditingProps {
18
18
 
19
19
  const Editing = memo<EditingProps>(({ documentId, title, currentEmoji, toggleEditing }) => {
20
20
  const locale = useGlobalStore(globalGeneralSelectors.currentLanguage);
21
- const { isDarkMode } = useThemeMode();
21
+ const isDarkMode = useIsDark();
22
22
  const { t } = useTranslation('file');
23
23
 
24
24
  const editing = useFileStore((s) => s.renamingPageId === documentId);