@lobehub/lobehub 2.0.0-next.324 → 2.0.0-next.326

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 (69) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/CLAUDE.md +4 -0
  3. package/apps/desktop/src/main/core/browser/Browser.ts +40 -1
  4. package/apps/desktop/src/main/core/infrastructure/I18nManager.ts +0 -11
  5. package/apps/desktop/src/main/core/infrastructure/UpdaterManager.ts +52 -2
  6. package/apps/desktop/src/main/core/infrastructure/__tests__/UpdaterManager.test.ts +41 -0
  7. package/changelog/v1.json +10 -0
  8. package/package.json +2 -2
  9. package/packages/database/src/models/__tests__/session.test.ts +0 -29
  10. package/src/app/[variants]/(main)/agent/features/Conversation/AgentWelcome/OpeningQuestions.tsx +0 -2
  11. package/src/app/[variants]/(main)/community/(detail)/agent/features/Sidebar/TocList/index.tsx +0 -36
  12. package/src/app/[variants]/(main)/community/(list)/_layout/Header.tsx +0 -2
  13. package/src/app/[variants]/(main)/group/_layout/Sidebar/GroupConfig/GroupMember.tsx +0 -4
  14. package/src/app/[variants]/(main)/group/features/Conversation/ConversationArea.tsx +0 -7
  15. package/src/app/[variants]/(main)/group/features/Conversation/MainChatInput/GroupChat.tsx +0 -2
  16. package/src/app/[variants]/(main)/home/_layout/Body/index.tsx +0 -2
  17. package/src/app/[variants]/(main)/page/_layout/Body/List/Item/useDropdownMenu.tsx +0 -6
  18. package/src/app/[variants]/(main)/page/_layout/Body/useDropdownMenu.tsx +0 -15
  19. package/src/app/[variants]/(main)/resource/features/DndContextWrapper.tsx +0 -5
  20. package/src/app/[variants]/(main)/settings/provider/features/ModelList/CreateNewModelModal/index.tsx +0 -1
  21. package/src/app/[variants]/(main)/settings/provider/features/ModelList/ModelItem.tsx +0 -10
  22. package/src/app/[variants]/(main)/settings/provider/features/ProviderConfig/Checker.tsx +1 -1
  23. package/src/app/[variants]/(mobile)/(home)/features/SessionListContent/List/Item/Actions.tsx +0 -1
  24. package/src/app/[variants]/layout.tsx +0 -2
  25. package/src/envs/__tests__/app.test.ts +0 -6
  26. package/src/features/ChatInput/ActionBar/Knowledge/useControls.tsx +0 -22
  27. package/src/features/ChatInput/store/action.ts +0 -2
  28. package/src/features/Conversation/Messages/Task/TaskDetailPanel/index.tsx +1 -15
  29. package/src/features/DataImporter/ImportDetail.tsx +0 -20
  30. package/src/features/DevPanel/features/Table/TableCell.tsx +1 -36
  31. package/src/features/DevPanel/index.tsx +0 -9
  32. package/src/features/ModelSwitchPanel/__mocks__/mockEnabledChatModels.ts +159 -0
  33. package/src/features/ModelSwitchPanel/components/List/{VirtualItemRenderer.tsx → ListItemRenderer.tsx} +15 -25
  34. package/src/features/ModelSwitchPanel/components/List/MultipleProvidersModelItem.tsx +95 -69
  35. package/src/features/ModelSwitchPanel/components/List/index.tsx +39 -40
  36. package/src/features/ModelSwitchPanel/components/PanelContent.tsx +0 -8
  37. package/src/features/ModelSwitchPanel/hooks/{useBuildVirtualItems.ts → useBuildListItems.ts} +7 -17
  38. package/src/features/ModelSwitchPanel/index.tsx +24 -23
  39. package/src/features/ModelSwitchPanel/styles.ts +3 -0
  40. package/src/features/ModelSwitchPanel/types.ts +3 -8
  41. package/src/features/ModelSwitchPanel/utils.ts +2 -2
  42. package/src/features/NavPanel/SideBarDrawer.tsx +12 -2
  43. package/src/features/NavPanel/SideBarHeaderLayout.tsx +3 -1
  44. package/src/features/Portal/GroupThread/Body/index.tsx +0 -6
  45. package/src/features/ResourceManager/components/Header/AddButton.tsx +0 -16
  46. package/src/features/ShareModal/ShareImage/index.tsx +0 -8
  47. package/src/hooks/useProviderName.ts +0 -1
  48. package/src/layout/GlobalProvider/Locale.tsx +0 -12
  49. package/src/layout/GlobalProvider/index.tsx +0 -1
  50. package/src/libs/better-auth/sso/helpers.ts +0 -1
  51. package/src/libs/next/config/define-config.ts +5 -0
  52. package/src/locales/create.ts +0 -17
  53. package/src/services/aiChat.ts +0 -4
  54. package/src/services/debug.ts +1 -34
  55. package/src/services/models.ts +0 -15
  56. package/src/store/chat/agents/GroupOrchestration/createGroupOrchestrationExecutors.ts +0 -9
  57. package/src/store/chat/slices/aiChat/actions/conversationLifecycle.ts +0 -3
  58. package/src/store/chat/slices/aiChat/actions/index.ts +1 -3
  59. package/src/store/file/slices/chat/action.test.ts +0 -89
  60. package/src/store/file/slices/chunk/selectors.ts +0 -1
  61. package/src/store/file/slices/fileManager/selectors.ts +0 -1
  62. package/src/store/file/slices/tts/selectors.ts +0 -2
  63. package/src/store/tool/slices/customPlugin/index.ts +0 -1
  64. package/src/store/tool/slices/mcpStore/index.ts +0 -1
  65. package/src/store/tool/slices/oldStore/index.ts +0 -1
  66. package/src/store/tool/slices/plugin/index.ts +0 -1
  67. package/src/styles/global.ts +6 -0
  68. package/src/utils/router.tsx +1 -7
  69. package/src/utils/server/parseModels.ts +0 -1
@@ -1,29 +1,22 @@
1
1
  import { Flexbox, TooltipGroup } from '@lobehub/ui';
2
2
  import type { FC } from 'react';
3
- import { useMemo } from 'react';
3
+ import { useCallback, useMemo, useState } from 'react';
4
4
  import { useTranslation } from 'react-i18next';
5
+ import { Virtuoso } from 'react-virtuoso';
5
6
 
6
7
  import { useEnabledChatModels } from '@/hooks/useEnabledChatModels';
7
8
 
8
- import {
9
- FOOTER_HEIGHT,
10
- INITIAL_RENDER_COUNT,
11
- ITEM_HEIGHT,
12
- MAX_PANEL_HEIGHT,
13
- TOOLBAR_HEIGHT,
14
- } from '../../const';
15
- import { useBuildVirtualItems } from '../../hooks/useBuildVirtualItems';
16
- import { useDelayedRender } from '../../hooks/useDelayedRender';
9
+ import { FOOTER_HEIGHT, ITEM_HEIGHT, MAX_PANEL_HEIGHT, TOOLBAR_HEIGHT } from '../../const';
10
+ import { useBuildListItems } from '../../hooks/useBuildListItems';
17
11
  import { useModelAndProvider } from '../../hooks/useModelAndProvider';
18
12
  import { usePanelHandlers } from '../../hooks/usePanelHandlers';
19
13
  import { styles } from '../../styles';
20
14
  import type { GroupMode } from '../../types';
21
- import { getVirtualItemKey, menuKey } from '../../utils';
22
- import { VirtualItemRenderer } from './VirtualItemRenderer';
15
+ import { menuKey } from '../../utils';
16
+ import { ListItemRenderer } from './ListItemRenderer';
23
17
 
24
18
  interface ListProps {
25
19
  groupMode: GroupMode;
26
- isOpen: boolean;
27
20
  model?: string;
28
21
  onModelChange?: (params: { model: string; provider: string }) => Promise<void>;
29
22
  onOpenChange?: (open: boolean) => void;
@@ -33,7 +26,6 @@ interface ListProps {
33
26
 
34
27
  export const List: FC<ListProps> = ({
35
28
  groupMode,
36
- isOpen,
37
29
  model: modelProp,
38
30
  onModelChange: onModelChangeProp,
39
31
  onOpenChange,
@@ -43,25 +35,15 @@ export const List: FC<ListProps> = ({
43
35
  const { t: tCommon } = useTranslation('common');
44
36
  const newLabel = tCommon('new');
45
37
 
46
- // Get enabled models list
38
+ const [isScrolling, setIsScrolling] = useState(false);
47
39
  const enabledList = useEnabledChatModels();
48
-
49
- // Get delayed render state
50
- const renderAll = useDelayedRender(isOpen);
51
-
52
- // Get model and provider
53
40
  const { model, provider } = useModelAndProvider(modelProp, providerProp);
54
-
55
- // Get handlers
56
41
  const { handleModelChange, handleClose } = usePanelHandlers({
57
42
  onModelChange: onModelChangeProp,
58
43
  onOpenChange,
59
44
  });
45
+ const listItems = useBuildListItems(enabledList, groupMode, searchKeyword);
60
46
 
61
- // Build virtual items
62
- const virtualItems = useBuildVirtualItems(enabledList, groupMode, searchKeyword);
63
-
64
- // Calculate panel height
65
47
  const panelHeight = useMemo(
66
48
  () =>
67
49
  enabledList.length === 0
@@ -70,31 +52,48 @@ export const List: FC<ListProps> = ({
70
52
  [enabledList.length],
71
53
  );
72
54
 
73
- // Calculate active key
74
55
  const activeKey = menuKey(provider, model);
75
56
 
57
+ const handleScrollingStateChange = useCallback((scrolling: boolean) => {
58
+ setIsScrolling(scrolling);
59
+ }, []);
60
+
61
+ const itemContent = useCallback(
62
+ (index: number) => {
63
+ const item = listItems[index];
64
+ return (
65
+ <ListItemRenderer
66
+ activeKey={activeKey}
67
+ isScrolling={isScrolling}
68
+ item={item}
69
+ newLabel={newLabel}
70
+ onClose={handleClose}
71
+ onModelChange={handleModelChange}
72
+ />
73
+ );
74
+ },
75
+ [activeKey, handleClose, handleModelChange, isScrolling, listItems, newLabel],
76
+ );
77
+
78
+ const listHeight = panelHeight - TOOLBAR_HEIGHT - FOOTER_HEIGHT;
79
+
76
80
  return (
77
81
  <Flexbox
78
82
  className={styles.list}
79
83
  flex={1}
80
84
  style={{
81
- height: panelHeight - TOOLBAR_HEIGHT - FOOTER_HEIGHT,
85
+ height: listHeight,
82
86
  paddingBlock: groupMode === 'byModel' ? 8 : 0,
83
87
  }}
84
88
  >
85
89
  <TooltipGroup>
86
- {virtualItems
87
- .slice(0, renderAll ? virtualItems.length : INITIAL_RENDER_COUNT)
88
- .map((item) => (
89
- <VirtualItemRenderer
90
- activeKey={activeKey}
91
- item={item}
92
- key={getVirtualItemKey(item)}
93
- newLabel={newLabel}
94
- onClose={handleClose}
95
- onModelChange={handleModelChange}
96
- />
97
- ))}
90
+ <Virtuoso
91
+ isScrolling={handleScrollingStateChange}
92
+ itemContent={itemContent}
93
+ overscan={200}
94
+ style={{ height: listHeight }}
95
+ totalCount={listItems.length}
96
+ />
98
97
  </TooltipGroup>
99
98
  </Flexbox>
100
99
  );
@@ -13,7 +13,6 @@ import { List } from './List';
13
13
  import { Toolbar } from './Toolbar';
14
14
 
15
15
  interface PanelContentProps {
16
- isOpen: boolean;
17
16
  model?: string;
18
17
  onModelChange?: (params: { model: string; provider: string }) => Promise<void>;
19
18
  onOpenChange?: (open: boolean) => void;
@@ -21,19 +20,13 @@ interface PanelContentProps {
21
20
  }
22
21
 
23
22
  export const PanelContent: FC<PanelContentProps> = ({
24
- isOpen,
25
23
  model: modelProp,
26
24
  onModelChange: onModelChangeProp,
27
25
  onOpenChange,
28
26
  provider: providerProp,
29
27
  }) => {
30
- // Get enabled models list
31
28
  const enabledList = useEnabledChatModels();
32
-
33
- // Search keyword state
34
29
  const [searchKeyword, setSearchKeyword] = useState('');
35
-
36
- // Hooks for state management
37
30
  const { groupMode, handleGroupModeChange } = usePanelState();
38
31
  const { panelHeight, panelWidth, handlePanelWidthChange } = usePanelSize(enabledList.length);
39
32
  const { handleClose } = usePanelHandlers({
@@ -62,7 +55,6 @@ export const PanelContent: FC<PanelContentProps> = ({
62
55
  />
63
56
  <List
64
57
  groupMode={groupMode}
65
- isOpen={isOpen}
66
58
  model={modelProp}
67
59
  onModelChange={onModelChangeProp}
68
60
  onOpenChange={onOpenChange}
@@ -2,26 +2,25 @@ import { useMemo } from 'react';
2
2
 
3
3
  import type { EnabledProviderWithModels } from '@/types/aiProvider';
4
4
 
5
- import type { GroupMode, ModelWithProviders, VirtualItem } from '../types';
5
+ import type { GroupMode, ListItem, ModelWithProviders } from '../types';
6
6
 
7
- export const useBuildVirtualItems = (
7
+ export const useBuildListItems = (
8
8
  enabledList: EnabledProviderWithModels[],
9
9
  groupMode: GroupMode,
10
10
  searchKeyword: string = '',
11
- ): VirtualItem[] => {
11
+ ): ListItem[] => {
12
12
  return useMemo(() => {
13
13
  if (enabledList.length === 0) {
14
- return [{ type: 'no-provider' }] as VirtualItem[];
14
+ return [{ type: 'no-provider' }] as ListItem[];
15
15
  }
16
16
 
17
- // Filter function for search
18
17
  const matchesSearch = (text: string): boolean => {
19
18
  if (!searchKeyword.trim()) return true;
20
19
  const keyword = searchKeyword.toLowerCase().trim();
21
20
  return text.toLowerCase().includes(keyword);
22
21
  };
23
22
 
24
- // Sort providers: lobehub first, then others
23
+ // lobehub first, then others
25
24
  const sortedProviders = [...enabledList].sort((a, b) => {
26
25
  const aIsLobehub = a.id === 'lobehub';
27
26
  const bIsLobehub = b.id === 'lobehub';
@@ -31,14 +30,12 @@ export const useBuildVirtualItems = (
31
30
  });
32
31
 
33
32
  if (groupMode === 'byModel') {
34
- // Group models by display name
35
33
  const modelMap = new Map<string, ModelWithProviders>();
36
34
 
37
35
  for (const providerItem of sortedProviders) {
38
36
  for (const modelItem of providerItem.children) {
39
37
  const displayName = modelItem.displayName || modelItem.id;
40
38
 
41
- // Filter by search keyword
42
39
  if (!matchesSearch(displayName) && !matchesSearch(providerItem.name)) {
43
40
  continue;
44
41
  }
@@ -61,7 +58,7 @@ export const useBuildVirtualItems = (
61
58
  }
62
59
  }
63
60
 
64
- // Sort providers within each model: lobehub first
61
+ // lobehub first
65
62
  const modelArray = Array.from(modelMap.values());
66
63
  for (const model of modelArray) {
67
64
  model.providers.sort((a, b) => {
@@ -73,7 +70,6 @@ export const useBuildVirtualItems = (
73
70
  });
74
71
  }
75
72
 
76
- // Convert to array and sort by display name
77
73
  return modelArray
78
74
  .sort((a, b) => a.displayName.localeCompare(b.displayName))
79
75
  .map((data) => ({
@@ -84,27 +80,21 @@ export const useBuildVirtualItems = (
84
80
  : ('model-item-multiple' as const),
85
81
  }));
86
82
  } else {
87
- // Group by provider (original structure)
88
- const items: VirtualItem[] = [];
83
+ const items: ListItem[] = [];
89
84
 
90
85
  for (const providerItem of sortedProviders) {
91
- // Filter models by search keyword
92
86
  const filteredModels = providerItem.children.filter(
93
87
  (modelItem) =>
94
88
  matchesSearch(modelItem.displayName || modelItem.id) ||
95
89
  matchesSearch(providerItem.name),
96
90
  );
97
91
 
98
- // Only add provider group header if there are matching models or if search is empty
99
92
  if (filteredModels.length > 0 || !searchKeyword.trim()) {
100
- // Add provider group header
101
93
  items.push({ provider: providerItem, type: 'group-header' });
102
94
 
103
95
  if (filteredModels.length === 0) {
104
- // Add empty model placeholder
105
96
  items.push({ provider: providerItem, type: 'empty-model' });
106
97
  } else {
107
- // Add each filtered model item
108
98
  for (const modelItem of filteredModels) {
109
99
  items.push({
110
100
  model: modelItem,
@@ -1,4 +1,10 @@
1
- import { Popover } from '@lobehub/ui';
1
+ import {
2
+ DropdownMenuPopup,
3
+ DropdownMenuPortal,
4
+ DropdownMenuPositioner,
5
+ DropdownMenuRoot,
6
+ DropdownMenuTrigger,
7
+ } from '@lobehub/ui';
2
8
  import { memo, useCallback, useState } from 'react';
3
9
 
4
10
  import { PanelContent } from './components/PanelContent';
@@ -16,8 +22,6 @@ const ModelSwitchPanel = memo<ModelSwitchPanelProps>(
16
22
  provider: providerProp,
17
23
  }) => {
18
24
  const [internalOpen, setInternalOpen] = useState(false);
19
-
20
- // Use controlled open if provided, otherwise use internal state
21
25
  const isOpen = open ?? internalOpen;
22
26
 
23
27
  const handleOpenChange = useCallback(
@@ -29,26 +33,23 @@ const ModelSwitchPanel = memo<ModelSwitchPanelProps>(
29
33
  );
30
34
 
31
35
  return (
32
- <Popover
33
- classNames={{
34
- content: styles.container,
35
- }}
36
- content={
37
- <PanelContent
38
- isOpen={isOpen}
39
- model={modelProp}
40
- onModelChange={onModelChange}
41
- onOpenChange={handleOpenChange}
42
- provider={providerProp}
43
- />
44
- }
45
- nativeButton={false}
46
- onOpenChange={handleOpenChange}
47
- open={isOpen}
48
- placement={placement}
49
- >
50
- {children}
51
- </Popover>
36
+ <DropdownMenuRoot onOpenChange={handleOpenChange} open={isOpen}>
37
+ <DropdownMenuTrigger nativeButton={false} openOnHover>
38
+ {children}
39
+ </DropdownMenuTrigger>
40
+ <DropdownMenuPortal>
41
+ <DropdownMenuPositioner hoverTrigger placement={placement}>
42
+ <DropdownMenuPopup className={styles.container}>
43
+ <PanelContent
44
+ model={modelProp}
45
+ onModelChange={onModelChange}
46
+ onOpenChange={handleOpenChange}
47
+ provider={providerProp}
48
+ />
49
+ </DropdownMenuPopup>
50
+ </DropdownMenuPositioner>
51
+ </DropdownMenuPortal>
52
+ </DropdownMenuRoot>
52
53
  );
53
54
  },
54
55
  );
@@ -69,6 +69,9 @@ export const styles = createStaticStyles(({ css, cssVar }) => ({
69
69
  }
70
70
  }
71
71
  `,
72
+ menuItemActive: css`
73
+ background: ${cssVar.colorFillTertiary};
74
+ `,
72
75
  toolbar: css`
73
76
  border-block-end: 1px solid ${cssVar.colorBorderSecondary};
74
77
  `,
@@ -1,3 +1,4 @@
1
+ import type { DropdownMenuPlacement } from '@lobehub/ui';
1
2
  import type { AiModelForSelect } from 'model-bank';
2
3
  import type { ReactNode } from 'react';
3
4
 
@@ -16,7 +17,7 @@ export interface ModelWithProviders {
16
17
  }>;
17
18
  }
18
19
 
19
- export type VirtualItem =
20
+ export type ListItem =
20
21
  | {
21
22
  data: ModelWithProviders;
22
23
  type: 'model-item-single';
@@ -42,13 +43,7 @@ export type VirtualItem =
42
43
  type: 'no-provider';
43
44
  };
44
45
 
45
- export type DropdownPlacement =
46
- | 'bottom'
47
- | 'bottomLeft'
48
- | 'bottomRight'
49
- | 'top'
50
- | 'topLeft'
51
- | 'topRight';
46
+ export type DropdownPlacement = DropdownMenuPlacement;
52
47
 
53
48
  export interface ModelSwitchPanelProps {
54
49
  children?: ReactNode;
@@ -1,8 +1,8 @@
1
- import type { VirtualItem } from './types';
1
+ import type { ListItem } from './types';
2
2
 
3
3
  export const menuKey = (provider: string, model: string) => `${provider}-${model}`;
4
4
 
5
- export const getVirtualItemKey = (item: VirtualItem): string => {
5
+ export const getListItemKey = (item: ListItem): string => {
6
6
  switch (item.type) {
7
7
  case 'model-item-single':
8
8
  case 'model-item-multiple': {
@@ -23,6 +23,7 @@ interface SideBarDrawerProps {
23
23
 
24
24
  const SideBarDrawer = memo<SideBarDrawerProps>(
25
25
  ({ subHeader, open, onClose, children, title, action }) => {
26
+ const size = 280;
26
27
  return (
27
28
  <Drawer
28
29
  closable={false}
@@ -33,9 +34,13 @@ const SideBarDrawer = memo<SideBarDrawerProps>(
33
34
  open={open}
34
35
  placement="left"
35
36
  rootStyle={{
37
+ bottom: 0,
38
+ overflow: 'hidden',
36
39
  position: 'absolute',
40
+ top: 0,
41
+ width: `${size}px`,
37
42
  }}
38
- size={280}
43
+ size={size}
39
44
  styles={{
40
45
  body: {
41
46
  background: cssVar.colorBgLayout,
@@ -58,7 +63,12 @@ const SideBarDrawer = memo<SideBarDrawerProps>(
58
63
  <SideBarHeaderLayout
59
64
  left={
60
65
  typeof title === 'string' ? (
61
- <Text ellipsis fontSize={14} style={{ paddingLeft: 4 }} weight={400}>
66
+ <Text
67
+ ellipsis
68
+ fontSize={14}
69
+ style={{ fontWeight: 600, paddingLeft: 8 }}
70
+ weight={400}
71
+ >
62
72
  {title}
63
73
  </Text>
64
74
  ) : (
@@ -8,6 +8,8 @@ import { type ReactNode, memo } from 'react';
8
8
  import { flushSync } from 'react-dom';
9
9
  import { useNavigate } from 'react-router-dom';
10
10
 
11
+ import { isDesktop } from '@/const/version';
12
+
11
13
  import ToggleLeftPanelButton from './ToggleLeftPanelButton';
12
14
  import BackButton from './components/BackButton';
13
15
 
@@ -35,7 +37,7 @@ const styles = createStaticStyles(({ css, cssVar }) => ({
35
37
  `,
36
38
  container: css`
37
39
  overflow: hidden;
38
- margin-block-start: 8px;
40
+ margin-block-start: ${isDesktop ? '' : '8px'};
39
41
  `,
40
42
  }));
41
43
 
@@ -3,20 +3,14 @@
3
3
  import { Flexbox } from '@lobehub/ui';
4
4
  import { memo } from 'react';
5
5
 
6
- // import ChatInput from '@/app/[variants]/(main)/chat/features/Conversation/ChatInput';
7
- // import { useChatGroupStore } from '@/store/chatGroup';
8
-
9
6
  import ThreadChatList from './ThreadChatList';
10
7
 
11
8
  const Body = memo(() => {
12
- // const activeThreadAgentId = useChatGroupStore((s) => s.activeThreadAgentId);
13
-
14
9
  return (
15
10
  <Flexbox height={'100%'}>
16
11
  <Flexbox flex={1} style={{ overflow: 'hidden', position: 'relative' }}>
17
12
  <ThreadChatList />
18
13
  </Flexbox>
19
- {/*{activeThreadAgentId && <ChatInput targetMemberId={activeThreadAgentId} />}*/}
20
14
  </Flexbox>
21
15
  );
22
16
  });
@@ -187,22 +187,6 @@ const AddButton = () => {
187
187
  label: 'Notion',
188
188
  onClick: handleOpenNotionGuide,
189
189
  },
190
- // {
191
- // icon: <Icon icon={Notion} />,
192
- // key: 'connect-google-drive',
193
- // label: 'Google Drive',
194
- // onClick: () => {
195
- // // TODO: Implement Google Drive connection
196
- // },
197
- // },
198
- // {
199
- // icon: <Icon icon={Notion} />,
200
- // key: 'connect-onedrive',
201
- // label: 'OneDrive',
202
- // onClick: () => {
203
- // // TODO: Implement OneDrive connection
204
- // },
205
- // },
206
190
  ],
207
191
  icon: <Icon icon={Link} />,
208
192
  key: 'connect',
@@ -56,14 +56,6 @@ const ShareImage = memo<{ mobile?: boolean }>(() => {
56
56
  name: 'withSystemRole',
57
57
  valuePropName: 'checked',
58
58
  },
59
- // {
60
- // children: <Switch />,
61
- // label: t('shareModal.withBackground'),
62
- // layout: 'horizontal',
63
- // minWidth: undefined,
64
- // name: 'withBackground',
65
- // valuePropName: 'checked',
66
- // },
67
59
  {
68
60
  children: <Switch />,
69
61
  label: t('shareModal.withFooter'),
@@ -1,7 +1,6 @@
1
1
  import { DEFAULT_MODEL_PROVIDER_LIST } from 'model-bank/modelProviders';
2
2
 
3
3
  export const useProviderName = (provider: string) => {
4
- // const { t } = useTranslation('modelProvider');
5
4
  const providerCard = DEFAULT_MODEL_PROVIDER_LIST.find((p) => p.id === provider);
6
5
 
7
6
  return providerCard?.name || provider;
@@ -12,7 +12,6 @@ import { getAntdLocale } from '@/utils/locale';
12
12
  import Editor from './Editor';
13
13
 
14
14
  const updateDayjs = async (lang: string) => {
15
- // load default lang
16
15
  let dayJSLocale;
17
16
  try {
18
17
  // dayjs locale is using `en` instead of `en-US`
@@ -38,21 +37,10 @@ const Locale = memo<LocaleLayoutProps>(({ children, defaultLang, antdLocale }) =
38
37
  const [lang, setLang] = useState(defaultLang);
39
38
  const [locale, setLocale] = useState(antdLocale);
40
39
 
41
- // if run on server side, init i18n instance everytime
42
40
  if (isOnServerSide) {
43
- // use sync mode to init instantly
44
41
  i18n.init({ initAsync: false });
45
-
46
- // load the dayjs locale
47
- // if (lang) {
48
- // const dayJSLocale = require(`dayjs/locale/${lang!.toLowerCase()}.js`);
49
- //
50
- // dayjs.locale(dayJSLocale);
51
- // }
52
42
  } else {
53
- // if on browser side, init i18n instance only once
54
43
  if (!i18n.instance.isInitialized)
55
- // console.debug('locale', lang);
56
44
  i18n.init().then(async () => {
57
45
  if (!lang) return;
58
46
 
@@ -67,7 +67,6 @@ const GlobalLayout = async ({
67
67
  <QueryProvider>
68
68
  <StoreInitialization />
69
69
  <FaviconProvider>
70
- {/* {process.env.NODE_ENV === 'development' && <FaviconTestPanel />} */}
71
70
  <GroupWizardProvider>
72
71
  <DragUploadProvider>
73
72
  <LazyMotion features={domMax}>
@@ -55,7 +55,6 @@ export const buildOidcConfig = ({
55
55
  pkce,
56
56
  providerId,
57
57
  scopes,
58
- // ...fallbackEndpoints,
59
58
  ...overrides,
60
59
  } satisfies GenericOAuthConfig;
61
60
  };
@@ -308,6 +308,11 @@ export function defineConfig(config: CustomNextConfig) {
308
308
  permanent: false,
309
309
  source: '/repos',
310
310
  },
311
+ {
312
+ destination: '/',
313
+ permanent: true,
314
+ source: '/chat',
315
+ },
311
316
  ...(config.redirects ?? []),
312
317
  ],
313
318
 
@@ -45,21 +45,6 @@ export const createI18nNext = (lang?: string) => {
45
45
  return instance.init({
46
46
  debug: debugMode,
47
47
  defaultNS: ['error', 'common', 'chat'],
48
-
49
- // detection: {
50
- // caches: ['cookie'],
51
- // cookieMinutes: 60 * 24 * COOKIE_CACHE_DAYS,
52
- // /**
53
- // Set `sameSite` to `lax` so that the i18n cookie can be passed to the
54
- // server side when returning from the OAuth authorization website.
55
- // ref: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#samesitesamesite-value
56
- // discussion: https://github.com/lobehub/lobe-chat/pull/1474
57
- // */
58
- // cookieOptions: {
59
- // sameSite: 'lax',
60
- // },
61
- // lookupCookie: LOBE_LOCALE_COOKIE,
62
- // },
63
48
  fallbackLng: DEFAULT_LANG,
64
49
 
65
50
  initAsync,
@@ -67,8 +52,6 @@ export const createI18nNext = (lang?: string) => {
67
52
  interpolation: {
68
53
  escapeValue: false,
69
54
  },
70
- // Use flat keys with dots (e.g. "notFound.title") instead of nested objects.
71
- // This keeps both runtime lookup and TS key inference consistent.
72
55
  keySeparator: false,
73
56
 
74
57
  lng: lang,
@@ -20,10 +20,6 @@ class AiChatService {
20
20
  signal: abortController?.signal,
21
21
  });
22
22
  };
23
-
24
- // sendGroupMessageInServer = async (params: SendMessageServerParams) => {
25
- // return lambdaClient.aiChat.sendGroupMessageInServer.mutate(cleanObject(params));
26
- // };
27
23
  }
28
24
 
29
25
  export const aiChatService = new AiChatService();
@@ -1,38 +1,5 @@
1
1
  class DebugService {
2
- async insertLargeDataToDB() {
3
- // await DEBUG_MODEL.createRandomData({
4
- // messageCount: 100_000,
5
- // sessionCount: 40,
6
- // startIndex: 0,
7
- // topicCount: 200,
8
- // });
9
- //
10
- // console.log('Inserted 100k');
11
- //
12
- // await DEBUG_MODEL.createRandomData({
13
- // messageCount: 300_000,
14
- // sessionCount: 40,
15
- // startIndex: 100_001,
16
- // topicCount: 200,
17
- // });
18
- // console.log('Inserted 400k');
19
- //
20
- // await DEBUG_MODEL.createRandomData({
21
- // messageCount: 300_000,
22
- // sessionCount: 40,
23
- // startIndex: 400_001,
24
- // topicCount: 200,
25
- // });
26
- // console.log('Inserted 700k');
27
- //
28
- // await DEBUG_MODEL.createRandomData({
29
- // messageCount: 300_000,
30
- // sessionCount: 40,
31
- // startIndex: 700_001,
32
- // topicCount: 200,
33
- // });
34
- // console.log('Inserted 1M');
35
- }
2
+ async insertLargeDataToDB() {}
36
3
  }
37
4
 
38
5
  export const debugService = new DebugService();