@lobehub/chat 1.75.5 → 1.76.0
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.
- package/CHANGELOG.md +25 -0
- package/changelog/v1.json +9 -0
- package/docs/developer/database-schema.dbml +1 -0
- package/locales/ar/hotkey.json +46 -0
- package/locales/ar/setting.json +12 -0
- package/locales/bg-BG/hotkey.json +46 -0
- package/locales/bg-BG/setting.json +12 -0
- package/locales/de-DE/hotkey.json +46 -0
- package/locales/de-DE/setting.json +12 -0
- package/locales/en-US/hotkey.json +46 -0
- package/locales/en-US/setting.json +12 -0
- package/locales/es-ES/hotkey.json +46 -0
- package/locales/es-ES/setting.json +12 -0
- package/locales/fa-IR/hotkey.json +46 -0
- package/locales/fa-IR/setting.json +12 -0
- package/locales/fr-FR/hotkey.json +46 -0
- package/locales/fr-FR/setting.json +12 -0
- package/locales/it-IT/hotkey.json +46 -0
- package/locales/it-IT/setting.json +12 -0
- package/locales/ja-JP/hotkey.json +46 -0
- package/locales/ja-JP/setting.json +12 -0
- package/locales/ko-KR/hotkey.json +46 -0
- package/locales/ko-KR/setting.json +12 -0
- package/locales/nl-NL/hotkey.json +46 -0
- package/locales/nl-NL/setting.json +12 -0
- package/locales/pl-PL/hotkey.json +46 -0
- package/locales/pl-PL/setting.json +12 -0
- package/locales/pt-BR/hotkey.json +46 -0
- package/locales/pt-BR/setting.json +12 -0
- package/locales/ru-RU/hotkey.json +46 -0
- package/locales/ru-RU/setting.json +12 -0
- package/locales/tr-TR/hotkey.json +46 -0
- package/locales/tr-TR/setting.json +12 -0
- package/locales/vi-VN/hotkey.json +46 -0
- package/locales/vi-VN/setting.json +12 -0
- package/locales/zh-CN/hotkey.json +46 -0
- package/locales/zh-CN/setting.json +12 -0
- package/locales/zh-TW/hotkey.json +46 -0
- package/locales/zh-TW/setting.json +12 -0
- package/package.json +3 -3
- package/src/app/[variants]/(main)/(mobile)/me/(home)/features/Category.tsx +1 -1
- package/src/app/[variants]/(main)/(mobile)/me/(home)/layout.tsx +3 -2
- package/src/app/[variants]/(main)/(mobile)/me/data/features/Category.tsx +1 -1
- package/src/app/[variants]/(main)/(mobile)/me/profile/features/Category.tsx +1 -1
- package/src/app/[variants]/(main)/(mobile)/me/settings/features/Category.tsx +1 -1
- package/src/app/[variants]/(main)/_layout/Desktop/RegisterHotkeys.tsx +11 -0
- package/src/app/[variants]/(main)/_layout/Desktop/SideBar/PinList/index.tsx +6 -23
- package/src/app/[variants]/(main)/_layout/Desktop/SideBar/TopActions.test.tsx +2 -0
- package/src/app/[variants]/(main)/_layout/Desktop/index.tsx +11 -4
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/Footer/SendMore.tsx +6 -21
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/Footer/ShortcutHint.tsx +13 -34
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ChatInput/Desktop/Footer/index.tsx +1 -1
- package/src/app/[variants]/(main)/chat/(workspace)/@conversation/features/ZenModeToast/Toast.tsx +7 -4
- package/src/app/[variants]/(main)/chat/(workspace)/_layout/Desktop/ChatHeader/HeaderAction.tsx +12 -8
- package/src/app/[variants]/(main)/chat/(workspace)/_layout/Desktop/ChatHeader/Main.tsx +24 -30
- package/src/app/[variants]/(main)/chat/(workspace)/_layout/Desktop/index.tsx +0 -2
- package/src/app/[variants]/(main)/chat/(workspace)/features/SettingButton.tsx +12 -7
- package/src/app/[variants]/(main)/chat/@session/features/SessionSearchBar.tsx +5 -1
- package/src/app/[variants]/(main)/chat/_layout/Desktop/RegisterHotkeys.tsx +10 -0
- package/src/app/[variants]/(main)/chat/_layout/Desktop/index.tsx +5 -0
- package/src/app/[variants]/(main)/chat/_layout/Mobile.tsx +1 -1
- package/src/app/[variants]/(main)/discover/features/StoreSearchBar.tsx +5 -1
- package/src/app/[variants]/(main)/settings/hooks/useCategory.tsx +31 -21
- package/src/app/[variants]/(main)/settings/hotkey/features/HotkeySetting.tsx +80 -0
- package/src/app/[variants]/(main)/settings/hotkey/index.tsx +9 -0
- package/src/app/[variants]/(main)/settings/hotkey/page.tsx +15 -0
- package/src/app/[variants]/layout.tsx +16 -13
- package/src/const/hotkeys.ts +80 -10
- package/src/const/settings/hotkey.ts +10 -0
- package/src/const/settings/index.ts +3 -0
- package/src/database/client/migrations.json +46 -32
- package/src/database/migrations/0019_add_hotkey_user_settings.sql +2 -0
- package/src/database/migrations/meta/0019_snapshot.json +4218 -0
- package/src/database/migrations/meta/_journal.json +7 -0
- package/src/database/schemas/user.ts +1 -0
- package/src/database/server/models/user.ts +2 -0
- package/src/features/ChatInput/Desktop/InputArea/index.tsx +8 -0
- package/src/features/ChatInput/Desktop/index.tsx +0 -1
- package/src/features/ChatInput/Topic/index.tsx +10 -15
- package/src/features/FileManager/Header/FilesSearchBar.tsx +6 -2
- package/src/features/HotkeyHelperPanel/HotkeyContent.tsx +62 -0
- package/src/features/HotkeyHelperPanel/index.tsx +59 -0
- package/src/hooks/useHotkeys/chatScope.ts +105 -0
- package/src/hooks/useHotkeys/globalScope.ts +69 -0
- package/src/hooks/useHotkeys/index.ts +2 -0
- package/src/hooks/useHotkeys/useHotkeyById.test.ts +194 -0
- package/src/hooks/useHotkeys/useHotkeyById.ts +57 -0
- package/src/locales/default/hotkey.ts +50 -0
- package/src/locales/default/index.ts +2 -0
- package/src/locales/default/setting.ts +12 -0
- package/src/store/global/initialState.ts +3 -0
- package/src/store/user/slices/settings/selectors/__snapshots__/settings.test.ts.snap +79 -0
- package/src/store/user/slices/settings/selectors/settings.test.ts +131 -0
- package/src/store/user/slices/settings/selectors/settings.ts +6 -0
- package/src/types/hotkey.ts +59 -0
- package/src/types/user/settings/hotkey.ts +3 -0
- package/src/types/user/settings/index.ts +3 -0
- package/src/app/[variants]/(main)/chat/(workspace)/_layout/Desktop/HotKeys.tsx +0 -44
- package/src/components/HotKeys/index.tsx +0 -77
@@ -1,6 +1,6 @@
|
|
1
1
|
'use client';
|
2
2
|
|
3
|
-
import { ActionIcon } from '@lobehub/ui';
|
3
|
+
import { ActionIcon, Tooltip } from '@lobehub/ui';
|
4
4
|
import { AlignJustify } from 'lucide-react';
|
5
5
|
import dynamic from 'next/dynamic';
|
6
6
|
import { memo } from 'react';
|
@@ -9,24 +9,29 @@ import { useTranslation } from 'react-i18next';
|
|
9
9
|
import { DESKTOP_HEADER_ICON_SIZE, MOBILE_HEADER_ICON_SIZE } from '@/const/layoutTokens';
|
10
10
|
import { useOpenChatSettings } from '@/hooks/useInterceptingRoutes';
|
11
11
|
import { useSessionStore } from '@/store/session';
|
12
|
+
import { useUserStore } from '@/store/user';
|
13
|
+
import { settingsSelectors } from '@/store/user/selectors';
|
14
|
+
import { HotkeyEnum } from '@/types/hotkey';
|
12
15
|
|
13
16
|
const AgentSettings = dynamic(() => import('./AgentSettings'), {
|
14
17
|
ssr: false,
|
15
18
|
});
|
16
19
|
|
17
20
|
const SettingButton = memo<{ mobile?: boolean }>(({ mobile }) => {
|
21
|
+
const hotkey = useUserStore(settingsSelectors.getHotkeyById(HotkeyEnum.OpenChatSettings));
|
18
22
|
const { t } = useTranslation('common');
|
19
23
|
const openChatSettings = useOpenChatSettings();
|
20
24
|
const id = useSessionStore((s) => s.activeId);
|
21
25
|
|
22
26
|
return (
|
23
27
|
<>
|
24
|
-
<
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
28
|
+
<Tooltip hotkey={hotkey} title={t('openChatSettings.title', { ns: 'hotkey' })}>
|
29
|
+
<ActionIcon
|
30
|
+
icon={AlignJustify}
|
31
|
+
onClick={() => openChatSettings()}
|
32
|
+
size={mobile ? MOBILE_HEADER_ICON_SIZE : DESKTOP_HEADER_ICON_SIZE}
|
33
|
+
/>
|
34
|
+
</Tooltip>
|
30
35
|
<AgentSettings key={id} />
|
31
36
|
</>
|
32
37
|
);
|
@@ -5,9 +5,13 @@ import { memo } from 'react';
|
|
5
5
|
import { useTranslation } from 'react-i18next';
|
6
6
|
|
7
7
|
import { useSessionStore } from '@/store/session';
|
8
|
+
import { useUserStore } from '@/store/user';
|
9
|
+
import { settingsSelectors } from '@/store/user/selectors';
|
10
|
+
import { HotkeyEnum } from '@/types/hotkey';
|
8
11
|
|
9
12
|
const SessionSearchBar = memo<{ mobile?: boolean }>(({ mobile }) => {
|
10
13
|
const { t } = useTranslation('chat');
|
14
|
+
const hotkey = useUserStore(settingsSelectors.getHotkeyById(HotkeyEnum.Search));
|
11
15
|
|
12
16
|
const [keywords, useSearchSessions, updateSearchKeywords] = useSessionStore((s) => [
|
13
17
|
s.sessionSearchKeywords,
|
@@ -26,7 +30,7 @@ const SessionSearchBar = memo<{ mobile?: boolean }>(({ mobile }) => {
|
|
26
30
|
updateSearchKeywords(e.target.value);
|
27
31
|
}}
|
28
32
|
placeholder={t('searchAgentPlaceholder')}
|
29
|
-
shortKey={
|
33
|
+
shortKey={hotkey}
|
30
34
|
spotlight={!mobile}
|
31
35
|
type={mobile ? 'block' : 'ghost'}
|
32
36
|
value={keywords}
|
@@ -1,8 +1,10 @@
|
|
1
|
+
import { Suspense } from 'react';
|
1
2
|
import { Flexbox } from 'react-layout-kit';
|
2
3
|
|
3
4
|
import InitClientDB from '@/features/InitClientDB';
|
4
5
|
|
5
6
|
import { LayoutProps } from '../type';
|
7
|
+
import RegisterHotkeys from './RegisterHotkeys';
|
6
8
|
import SessionPanel from './SessionPanel';
|
7
9
|
|
8
10
|
const Layout = ({ children, session }: LayoutProps) => {
|
@@ -23,6 +25,9 @@ const Layout = ({ children, session }: LayoutProps) => {
|
|
23
25
|
{/* ↓ cloud slot ↓ */}
|
24
26
|
|
25
27
|
{/* ↑ cloud slot ↑ */}
|
28
|
+
<Suspense>
|
29
|
+
<RegisterHotkeys />
|
30
|
+
</Suspense>
|
26
31
|
</>
|
27
32
|
);
|
28
33
|
};
|
@@ -10,7 +10,10 @@ import urlJoin from 'url-join';
|
|
10
10
|
|
11
11
|
import { withSuspense } from '@/components/withSuspense';
|
12
12
|
import { useQueryRoute } from '@/hooks/useQueryRoute';
|
13
|
+
import { useUserStore } from '@/store/user';
|
14
|
+
import { settingsSelectors } from '@/store/user/selectors';
|
13
15
|
import { DiscoverTab } from '@/types/discover';
|
16
|
+
import { HotkeyEnum } from '@/types/hotkey';
|
14
17
|
|
15
18
|
import { useNav } from './useNav';
|
16
19
|
|
@@ -34,6 +37,7 @@ const StoreSearchBar = memo<StoreSearchBarProps>(({ mobile, onBlur, onFocus, ...
|
|
34
37
|
const pathname = usePathname();
|
35
38
|
const { activeKey } = useNav();
|
36
39
|
const [searchKey, setSearchKey] = useQueryState('q', { clearOnDefault: true, defaultValue: '' });
|
40
|
+
const hotkey = useUserStore(settingsSelectors.getHotkeyById(HotkeyEnum.Search));
|
37
41
|
|
38
42
|
const { t } = useTranslation('discover');
|
39
43
|
const { cx, styles } = useStyles();
|
@@ -69,7 +73,7 @@ const StoreSearchBar = memo<StoreSearchBarProps>(({ mobile, onBlur, onFocus, ...
|
|
69
73
|
}}
|
70
74
|
onSearch={handleSearch}
|
71
75
|
placeholder={t('search.placeholder')}
|
72
|
-
shortKey={
|
76
|
+
shortKey={hotkey}
|
73
77
|
spotlight={!mobile}
|
74
78
|
style={{ width: mobile || active ? '100%' : 'min(480px,100%)' }}
|
75
79
|
styles={{ input: { width: '100%' } }}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { Icon } from '@lobehub/ui';
|
2
2
|
import { Tag } from 'antd';
|
3
|
-
import { Bot, Brain, Cloudy, Info, Mic2, Settings2, Sparkles } from 'lucide-react';
|
3
|
+
import { Bot, Brain, Cloudy, Info, KeyboardIcon, Mic2, Settings2, Sparkles } from 'lucide-react';
|
4
4
|
import Link from 'next/link';
|
5
5
|
import { useMemo } from 'react';
|
6
6
|
import { useTranslation } from 'react-i18next';
|
@@ -13,6 +13,7 @@ import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfi
|
|
13
13
|
|
14
14
|
export const useCategory = () => {
|
15
15
|
const { t } = useTranslation('setting');
|
16
|
+
const mobile = useServerConfigStore((s) => s.isMobile);
|
16
17
|
const { enableWebrtc, showLLM, enableSTT, hideDocs } =
|
17
18
|
useServerConfigStore(featureFlagsSelectors);
|
18
19
|
|
@@ -52,26 +53,26 @@ export const useCategory = () => {
|
|
52
53
|
),
|
53
54
|
},
|
54
55
|
showLLM &&
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
56
|
+
// TODO: Remove /llm when v2.0
|
57
|
+
(isDeprecatedEdition
|
58
|
+
? {
|
59
|
+
icon: <Icon icon={Brain} />,
|
60
|
+
key: SettingsTabs.LLM,
|
61
|
+
label: (
|
62
|
+
<Link href={'/settings/llm'} onClick={(e) => e.preventDefault()}>
|
63
|
+
{t('tab.llm')}
|
64
|
+
</Link>
|
65
|
+
),
|
66
|
+
}
|
67
|
+
: {
|
68
|
+
icon: <Icon icon={Brain} />,
|
69
|
+
key: SettingsTabs.Provider,
|
70
|
+
label: (
|
71
|
+
<Link href={'/settings/provider'} onClick={(e) => e.preventDefault()}>
|
72
|
+
{t('tab.provider')}
|
73
|
+
</Link>
|
74
|
+
),
|
75
|
+
}),
|
75
76
|
|
76
77
|
enableSTT && {
|
77
78
|
icon: <Icon icon={Mic2} />,
|
@@ -91,6 +92,15 @@ export const useCategory = () => {
|
|
91
92
|
</Link>
|
92
93
|
),
|
93
94
|
},
|
95
|
+
!mobile && {
|
96
|
+
icon: <Icon icon={KeyboardIcon} />,
|
97
|
+
key: SettingsTabs.Hotkey,
|
98
|
+
label: (
|
99
|
+
<Link href={'/settings/hotkey'} onClick={(e) => e.preventDefault()}>
|
100
|
+
{t('tab.hotkey')}
|
101
|
+
</Link>
|
102
|
+
),
|
103
|
+
},
|
94
104
|
!hideDocs && {
|
95
105
|
icon: <Icon icon={Info} />,
|
96
106
|
key: SettingsTabs.About,
|
@@ -0,0 +1,80 @@
|
|
1
|
+
'use client';
|
2
|
+
|
3
|
+
import { Form, HotkeyInput, type ItemGroup } from '@lobehub/ui';
|
4
|
+
import isEqual from 'fast-deep-equal';
|
5
|
+
import { memo } from 'react';
|
6
|
+
import { useTranslation } from 'react-i18next';
|
7
|
+
|
8
|
+
import { HOTKEYS_REGISTRATION } from '@/const/hotkeys';
|
9
|
+
import { FORM_STYLE } from '@/const/layoutTokens';
|
10
|
+
import hotkeyMeta from '@/locales/default/hotkey';
|
11
|
+
import { useUserStore } from '@/store/user';
|
12
|
+
import { settingsSelectors } from '@/store/user/selectors';
|
13
|
+
import { HotkeyGroupEnum, HotkeyItem } from '@/types/hotkey';
|
14
|
+
|
15
|
+
type SettingItemGroup = ItemGroup;
|
16
|
+
|
17
|
+
const HOTKEY_SETTING_KEY = 'hotkey';
|
18
|
+
|
19
|
+
const HotkeySetting = memo(() => {
|
20
|
+
const { t } = useTranslation(['setting', 'hotkey']);
|
21
|
+
const [form] = Form.useForm();
|
22
|
+
|
23
|
+
const settings = useUserStore(settingsSelectors.currentSettings, isEqual);
|
24
|
+
const [setSettings] = useUserStore((s) => [s.setSettings]);
|
25
|
+
|
26
|
+
const mapHotkeyItem = (item: HotkeyItem) => {
|
27
|
+
const hotkeyConflicts = Object.entries(settings.hotkey)
|
28
|
+
.map(([key, value]) => {
|
29
|
+
if (key === item.id) return false;
|
30
|
+
return value;
|
31
|
+
})
|
32
|
+
.filter(Boolean) as string[];
|
33
|
+
return {
|
34
|
+
children: (
|
35
|
+
<HotkeyInput
|
36
|
+
disabled={item.nonEditable}
|
37
|
+
hotkeyConflicts={hotkeyConflicts}
|
38
|
+
placeholder={t('hotkey.record')}
|
39
|
+
resetValue={item.keys}
|
40
|
+
texts={{
|
41
|
+
conflicts: t('hotkey.conflicts'),
|
42
|
+
invalidCombination: t('hotkey.invalidCombination'),
|
43
|
+
reset: t('hotkey.reset'),
|
44
|
+
}}
|
45
|
+
/>
|
46
|
+
),
|
47
|
+
desc: hotkeyMeta[item.id].desc ? t(`${item.id}.desc`, { ns: 'hotkey' }) : undefined,
|
48
|
+
label: t(`${item.id}.title`, { ns: 'hotkey' }),
|
49
|
+
name: [HOTKEY_SETTING_KEY, item.id],
|
50
|
+
};
|
51
|
+
};
|
52
|
+
|
53
|
+
const essential: SettingItemGroup = {
|
54
|
+
children: HOTKEYS_REGISTRATION.filter((item) => item.group === HotkeyGroupEnum.Essential).map(
|
55
|
+
(item) => mapHotkeyItem(item),
|
56
|
+
),
|
57
|
+
title: t('hotkey.group.essential'),
|
58
|
+
};
|
59
|
+
|
60
|
+
const conversation: SettingItemGroup = {
|
61
|
+
children: HOTKEYS_REGISTRATION.filter(
|
62
|
+
(item) => item.group === HotkeyGroupEnum.Conversation,
|
63
|
+
).map((item) => mapHotkeyItem(item)),
|
64
|
+
title: t('hotkey.group.conversation'),
|
65
|
+
};
|
66
|
+
|
67
|
+
return (
|
68
|
+
<Form
|
69
|
+
form={form}
|
70
|
+
initialValues={settings}
|
71
|
+
items={[essential, conversation]}
|
72
|
+
itemsType={'group'}
|
73
|
+
onValuesChange={setSettings}
|
74
|
+
variant={'pure'}
|
75
|
+
{...FORM_STYLE}
|
76
|
+
/>
|
77
|
+
);
|
78
|
+
});
|
79
|
+
|
80
|
+
export default HotkeySetting;
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import { metadataModule } from '@/server/metadata';
|
2
|
+
import { translation } from '@/server/translation';
|
3
|
+
import { DynamicLayoutProps } from '@/types/next';
|
4
|
+
import { RouteVariants } from '@/utils/server/routeVariants';
|
5
|
+
|
6
|
+
export const generateMetadata = async (props: DynamicLayoutProps) => {
|
7
|
+
const locale = await RouteVariants.getLocale(props);
|
8
|
+
const { t } = await translation('setting', locale);
|
9
|
+
return metadataModule.generate({
|
10
|
+
description: t('header.desc'),
|
11
|
+
title: t('tab.hotkey'),
|
12
|
+
url: '/settings/hotkey',
|
13
|
+
});
|
14
|
+
};
|
15
|
+
export { default } from './index';
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import { SpeedInsights } from '@vercel/speed-insights/next';
|
2
2
|
import { ThemeAppearance } from 'antd-style';
|
3
3
|
import { ResolvingViewport } from 'next';
|
4
|
+
import { NuqsAdapter } from 'nuqs/adapters/next/app';
|
4
5
|
import { ReactNode } from 'react';
|
5
6
|
import { isRtlLang } from 'rtl-detect';
|
6
7
|
|
@@ -31,19 +32,21 @@ const RootLayout = async ({ children, params, modal }: RootLayoutProps) => {
|
|
31
32
|
return (
|
32
33
|
<html dir={direction} lang={locale} suppressHydrationWarning>
|
33
34
|
<body>
|
34
|
-
<
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
35
|
+
<NuqsAdapter>
|
36
|
+
<GlobalProvider
|
37
|
+
appearance={theme}
|
38
|
+
isMobile={isMobile}
|
39
|
+
locale={locale}
|
40
|
+
neutralColor={neutralColor}
|
41
|
+
primaryColor={primaryColor}
|
42
|
+
>
|
43
|
+
<AuthProvider>
|
44
|
+
{children}
|
45
|
+
{!isMobile && modal}
|
46
|
+
</AuthProvider>
|
47
|
+
<PWAInstall />
|
48
|
+
</GlobalProvider>
|
49
|
+
</NuqsAdapter>
|
47
50
|
<Analytics />
|
48
51
|
{inVercel && <SpeedInsights />}
|
49
52
|
</body>
|
package/src/const/hotkeys.ts
CHANGED
@@ -1,11 +1,81 @@
|
|
1
|
-
|
2
|
-
export const META_KEY = 'mod';
|
3
|
-
export const SAVE_TOPIC_KEY = 'n';
|
4
|
-
export const CLEAN_MESSAGE_KEY = 'backspace';
|
1
|
+
import { combineKeys } from '@lobehub/ui/es/Hotkey';
|
5
2
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
3
|
+
import {
|
4
|
+
HotkeyEnum,
|
5
|
+
HotkeyGroupEnum,
|
6
|
+
HotkeyRegistration,
|
7
|
+
HotkeyScopeEnum,
|
8
|
+
KeyEnum,
|
9
|
+
} from '@/types/hotkey';
|
10
|
+
|
11
|
+
// mod 在 Mac 上是 command 键,alt 在 Win 上是 ctrl 键
|
12
|
+
export const HOTKEYS_REGISTRATION: HotkeyRegistration = [
|
13
|
+
{
|
14
|
+
group: HotkeyGroupEnum.Essential,
|
15
|
+
id: HotkeyEnum.Search,
|
16
|
+
keys: combineKeys([KeyEnum.Mod, 'k']),
|
17
|
+
scopes: [HotkeyScopeEnum.Global],
|
18
|
+
},
|
19
|
+
{
|
20
|
+
group: HotkeyGroupEnum.Essential,
|
21
|
+
id: HotkeyEnum.SwitchAgent,
|
22
|
+
keys: combineKeys([KeyEnum.Ctrl, KeyEnum.Number]),
|
23
|
+
nonEditable: true,
|
24
|
+
scopes: [HotkeyScopeEnum.Global],
|
25
|
+
},
|
26
|
+
{
|
27
|
+
group: HotkeyGroupEnum.Essential,
|
28
|
+
id: HotkeyEnum.ToggleZenMode,
|
29
|
+
keys: combineKeys([KeyEnum.Mod, KeyEnum.Backslash]),
|
30
|
+
scopes: [HotkeyScopeEnum.Chat],
|
31
|
+
},
|
32
|
+
{
|
33
|
+
group: HotkeyGroupEnum.Essential,
|
34
|
+
id: HotkeyEnum.ToggleLeftPanel,
|
35
|
+
keys: combineKeys([KeyEnum.Mod, KeyEnum.BracketLeft]),
|
36
|
+
scopes: [HotkeyScopeEnum.Chat],
|
37
|
+
},
|
38
|
+
{
|
39
|
+
group: HotkeyGroupEnum.Essential,
|
40
|
+
id: HotkeyEnum.ToggleRightPanel,
|
41
|
+
keys: combineKeys([KeyEnum.Mod, KeyEnum.BracketRight]),
|
42
|
+
scopes: [HotkeyScopeEnum.Chat],
|
43
|
+
},
|
44
|
+
{
|
45
|
+
group: HotkeyGroupEnum.Essential,
|
46
|
+
id: HotkeyEnum.OpenHotkeyHelper,
|
47
|
+
keys: combineKeys([KeyEnum.Ctrl, KeyEnum.Shift, KeyEnum.QuestionMark]),
|
48
|
+
scopes: [HotkeyScopeEnum.Global],
|
49
|
+
},
|
50
|
+
{
|
51
|
+
group: HotkeyGroupEnum.Conversation,
|
52
|
+
id: HotkeyEnum.OpenChatSettings,
|
53
|
+
keys: combineKeys([KeyEnum.Alt, KeyEnum.Comma]),
|
54
|
+
scopes: [HotkeyScopeEnum.Chat],
|
55
|
+
},
|
56
|
+
{
|
57
|
+
group: HotkeyGroupEnum.Conversation,
|
58
|
+
id: HotkeyEnum.RegenerateMessage,
|
59
|
+
keys: combineKeys([KeyEnum.Alt, 'r']),
|
60
|
+
scopes: [HotkeyScopeEnum.Chat],
|
61
|
+
},
|
62
|
+
{
|
63
|
+
group: HotkeyGroupEnum.Conversation,
|
64
|
+
id: HotkeyEnum.SaveTopic,
|
65
|
+
keys: combineKeys([KeyEnum.Alt, 'n']),
|
66
|
+
scopes: [HotkeyScopeEnum.Chat],
|
67
|
+
},
|
68
|
+
{
|
69
|
+
group: HotkeyGroupEnum.Conversation,
|
70
|
+
id: HotkeyEnum.AddUserMessage,
|
71
|
+
keys: combineKeys([KeyEnum.Alt, KeyEnum.Enter]),
|
72
|
+
// 不通过 Scope 模式激活
|
73
|
+
},
|
74
|
+
{
|
75
|
+
group: HotkeyGroupEnum.Conversation,
|
76
|
+
id: HotkeyEnum.EditMessage,
|
77
|
+
keys: combineKeys([KeyEnum.Alt, KeyEnum.LeftDoubleClick]),
|
78
|
+
nonEditable: true,
|
79
|
+
scopes: [HotkeyScopeEnum.Chat],
|
80
|
+
},
|
81
|
+
];
|
@@ -0,0 +1,10 @@
|
|
1
|
+
import { HOTKEYS_REGISTRATION } from '@/const/hotkeys';
|
2
|
+
import { UserHotkeyConfig } from '@/types/user/settings';
|
3
|
+
|
4
|
+
export const DEFAULT_HOTKEY_CONFIG: UserHotkeyConfig = HOTKEYS_REGISTRATION.reduce(
|
5
|
+
(acc: UserHotkeyConfig, item) => {
|
6
|
+
acc[item.id] = item.keys;
|
7
|
+
return acc;
|
8
|
+
},
|
9
|
+
{} as UserHotkeyConfig,
|
10
|
+
);
|
@@ -2,6 +2,7 @@ import { UserSettings } from '@/types/user/settings';
|
|
2
2
|
|
3
3
|
import { DEFAULT_AGENT } from './agent';
|
4
4
|
import { DEFAULT_COMMON_SETTINGS } from './common';
|
5
|
+
import { DEFAULT_HOTKEY_CONFIG } from './hotkey';
|
5
6
|
import { DEFAULT_LLM_CONFIG } from './llm';
|
6
7
|
import { DEFAULT_SYNC_CONFIG } from './sync';
|
7
8
|
import { DEFAULT_SYSTEM_AGENT_CONFIG } from './systemAgent';
|
@@ -11,6 +12,7 @@ import { DEFAULT_TTS_CONFIG } from './tts';
|
|
11
12
|
export const COOKIE_CACHE_DAYS = 30;
|
12
13
|
|
13
14
|
export * from './agent';
|
15
|
+
export * from './hotkey';
|
14
16
|
export * from './llm';
|
15
17
|
export * from './systemAgent';
|
16
18
|
export * from './tool';
|
@@ -19,6 +21,7 @@ export * from './tts';
|
|
19
21
|
export const DEFAULT_SETTINGS: UserSettings = {
|
20
22
|
defaultAgent: DEFAULT_AGENT,
|
21
23
|
general: DEFAULT_COMMON_SETTINGS,
|
24
|
+
hotkey: DEFAULT_HOTKEY_CONFIG,
|
22
25
|
keyVaults: {},
|
23
26
|
languageModel: DEFAULT_LLM_CONFIG,
|
24
27
|
sync: DEFAULT_SYNC_CONFIG,
|
@@ -223,7 +223,10 @@
|
|
223
223
|
"hash": "9646161fa041354714f823d726af27247bcd6e60fa3be5698c0d69f337a5700b"
|
224
224
|
},
|
225
225
|
{
|
226
|
-
"sql": [
|
226
|
+
"sql": [
|
227
|
+
"DROP TABLE \"user_budgets\";",
|
228
|
+
"\nDROP TABLE \"user_subscriptions\";"
|
229
|
+
],
|
227
230
|
"bps": true,
|
228
231
|
"folderMillis": 1729699958471,
|
229
232
|
"hash": "7dad43a2a25d1aec82124a4e53f8d82f8505c3073f23606c1dc5d2a4598eacf9"
|
@@ -295,7 +298,9 @@
|
|
295
298
|
"hash": "845a692ceabbfc3caf252a97d3e19a213bc0c433df2689900135f9cfded2cf49"
|
296
299
|
},
|
297
300
|
{
|
298
|
-
"sql": [
|
301
|
+
"sql": [
|
302
|
+
"ALTER TABLE \"messages\" ADD COLUMN \"reasoning\" jsonb;"
|
303
|
+
],
|
299
304
|
"bps": true,
|
300
305
|
"folderMillis": 1737609172353,
|
301
306
|
"hash": "2cb36ae4fcdd7b7064767e04bfbb36ae34518ff4bb1b39006f2dd394d1893868"
|
@@ -383,37 +388,46 @@
|
|
383
388
|
},
|
384
389
|
{
|
385
390
|
"sql": [
|
386
|
-
"ALTER TABLE \"session_groups\" DROP CONSTRAINT \"session_group_client_id_user_unique\";",
|
387
|
-
"\nALTER TABLE \"sessions\" DROP CONSTRAINT \"sessions_client_id_user_id_unique\";",
|
388
|
-
"\nALTER TABLE \"topics\" DROP CONSTRAINT \"topic_client_id_user_id_unique\";",
|
389
|
-
"\nALTER TABLE \"agents\" ADD COLUMN \"client_id\" text;",
|
390
|
-
"\nALTER TABLE \"files\" ADD COLUMN \"client_id\" text;",
|
391
|
-
"\nALTER TABLE \"knowledge_bases\" ADD COLUMN \"client_id\" text;",
|
392
|
-
"\nALTER TABLE \"message_plugins\" ADD COLUMN \"client_id\" text;",
|
393
|
-
"\nALTER TABLE \"message_queries\" ADD COLUMN \"client_id\" text;",
|
394
|
-
"\nALTER TABLE \"message_tts\" ADD COLUMN \"client_id\" text;",
|
395
|
-
"\nALTER TABLE \"message_translates\" ADD COLUMN \"client_id\" text;",
|
396
|
-
"\nALTER TABLE \"chunks\" ADD COLUMN \"client_id\" text;",
|
397
|
-
"\nALTER TABLE \"embeddings\" ADD COLUMN \"client_id\" text;",
|
398
|
-
"\nALTER TABLE \"unstructured_chunks\" ADD COLUMN \"client_id\" text;",
|
399
|
-
"\nALTER TABLE \"threads\" ADD COLUMN \"client_id\" text;",
|
400
|
-
"\nCREATE UNIQUE INDEX \"client_id_user_id_unique\" ON \"agents\" USING btree (\"client_id\",\"user_id\");",
|
401
|
-
"\nCREATE UNIQUE INDEX \"files_client_id_user_id_unique\" ON \"files\" USING btree (\"client_id\",\"user_id\");",
|
402
|
-
"\nCREATE UNIQUE INDEX \"knowledge_bases_client_id_user_id_unique\" ON \"knowledge_bases\" USING btree (\"client_id\",\"user_id\");",
|
403
|
-
"\nCREATE UNIQUE INDEX \"message_plugins_client_id_user_id_unique\" ON \"message_plugins\" USING btree (\"client_id\",\"user_id\");",
|
404
|
-
"\nCREATE UNIQUE INDEX \"message_queries_client_id_user_id_unique\" ON \"message_queries\" USING btree (\"client_id\",\"user_id\");",
|
405
|
-
"\nCREATE UNIQUE INDEX \"message_tts_client_id_user_id_unique\" ON \"message_tts\" USING btree (\"client_id\",\"user_id\");",
|
406
|
-
"\nCREATE UNIQUE INDEX \"message_translates_client_id_user_id_unique\" ON \"message_translates\" USING btree (\"client_id\",\"user_id\");",
|
407
|
-
"\nCREATE UNIQUE INDEX \"chunks_client_id_user_id_unique\" ON \"chunks\" USING btree (\"client_id\",\"user_id\");",
|
408
|
-
"\nCREATE UNIQUE INDEX \"embeddings_client_id_user_id_unique\" ON \"embeddings\" USING btree (\"client_id\",\"user_id\");",
|
409
|
-
"\nCREATE UNIQUE INDEX \"unstructured_chunks_client_id_user_id_unique\" ON \"unstructured_chunks\" USING btree (\"client_id\",\"user_id\");",
|
410
|
-
"\nCREATE UNIQUE INDEX \"session_groups_client_id_user_id_unique\" ON \"session_groups\" USING btree (\"client_id\",\"user_id\");",
|
411
|
-
"\nCREATE UNIQUE INDEX \"sessions_client_id_user_id_unique\" ON \"sessions\" USING btree (\"client_id\",\"user_id\");",
|
412
|
-
"\nCREATE UNIQUE INDEX \"threads_client_id_user_id_unique\" ON \"threads\" USING btree (\"client_id\",\"user_id\");",
|
413
|
-
"\nCREATE UNIQUE INDEX \"topics_client_id_user_id_unique\" ON \"topics\" USING btree (\"client_id\",\"user_id\")
|
391
|
+
"ALTER TABLE \"session_groups\" DROP CONSTRAINT IF EXISTS \"session_group_client_id_user_unique\";",
|
392
|
+
"\nALTER TABLE \"sessions\" DROP CONSTRAINT IF EXISTS \"sessions_client_id_user_id_unique\";",
|
393
|
+
"\nALTER TABLE \"topics\" DROP CONSTRAINT IF EXISTS \"topic_client_id_user_id_unique\";",
|
394
|
+
"\n\n-- add client_id column\nALTER TABLE \"agents\" ADD COLUMN IF NOT EXISTS \"client_id\" text;",
|
395
|
+
"\nALTER TABLE \"files\" ADD COLUMN IF NOT EXISTS \"client_id\" text;",
|
396
|
+
"\nALTER TABLE \"knowledge_bases\" ADD COLUMN IF NOT EXISTS \"client_id\" text;",
|
397
|
+
"\nALTER TABLE \"message_plugins\" ADD COLUMN IF NOT EXISTS \"client_id\" text;",
|
398
|
+
"\nALTER TABLE \"message_queries\" ADD COLUMN IF NOT EXISTS \"client_id\" text;",
|
399
|
+
"\nALTER TABLE \"message_tts\" ADD COLUMN IF NOT EXISTS \"client_id\" text;",
|
400
|
+
"\nALTER TABLE \"message_translates\" ADD COLUMN IF NOT EXISTS \"client_id\" text;",
|
401
|
+
"\nALTER TABLE \"chunks\" ADD COLUMN IF NOT EXISTS \"client_id\" text;",
|
402
|
+
"\nALTER TABLE \"embeddings\" ADD COLUMN IF NOT EXISTS \"client_id\" text;",
|
403
|
+
"\nALTER TABLE \"unstructured_chunks\" ADD COLUMN IF NOT EXISTS \"client_id\" text;",
|
404
|
+
"\nALTER TABLE \"threads\" ADD COLUMN IF NOT EXISTS \"client_id\" text;",
|
405
|
+
"\n\n-- Create unique index(using IF NOT EXISTS)\nCREATE UNIQUE INDEX IF NOT EXISTS \"client_id_user_id_unique\" ON \"agents\" USING btree (\"client_id\",\"user_id\");",
|
406
|
+
"\nCREATE UNIQUE INDEX IF NOT EXISTS \"files_client_id_user_id_unique\" ON \"files\" USING btree (\"client_id\",\"user_id\");",
|
407
|
+
"\nCREATE UNIQUE INDEX IF NOT EXISTS \"knowledge_bases_client_id_user_id_unique\" ON \"knowledge_bases\" USING btree (\"client_id\",\"user_id\");",
|
408
|
+
"\nCREATE UNIQUE INDEX IF NOT EXISTS \"message_plugins_client_id_user_id_unique\" ON \"message_plugins\" USING btree (\"client_id\",\"user_id\");",
|
409
|
+
"\nCREATE UNIQUE INDEX IF NOT EXISTS \"message_queries_client_id_user_id_unique\" ON \"message_queries\" USING btree (\"client_id\",\"user_id\");",
|
410
|
+
"\nCREATE UNIQUE INDEX IF NOT EXISTS \"message_tts_client_id_user_id_unique\" ON \"message_tts\" USING btree (\"client_id\",\"user_id\");",
|
411
|
+
"\nCREATE UNIQUE INDEX IF NOT EXISTS \"message_translates_client_id_user_id_unique\" ON \"message_translates\" USING btree (\"client_id\",\"user_id\");",
|
412
|
+
"\nCREATE UNIQUE INDEX IF NOT EXISTS \"chunks_client_id_user_id_unique\" ON \"chunks\" USING btree (\"client_id\",\"user_id\");",
|
413
|
+
"\nCREATE UNIQUE INDEX IF NOT EXISTS \"embeddings_client_id_user_id_unique\" ON \"embeddings\" USING btree (\"client_id\",\"user_id\");",
|
414
|
+
"\nCREATE UNIQUE INDEX IF NOT EXISTS \"unstructured_chunks_client_id_user_id_unique\" ON \"unstructured_chunks\" USING btree (\"client_id\",\"user_id\");",
|
415
|
+
"\nCREATE UNIQUE INDEX IF NOT EXISTS \"session_groups_client_id_user_id_unique\" ON \"session_groups\" USING btree (\"client_id\",\"user_id\");",
|
416
|
+
"\nCREATE UNIQUE INDEX IF NOT EXISTS \"sessions_client_id_user_id_unique\" ON \"sessions\" USING btree (\"client_id\",\"user_id\");",
|
417
|
+
"\nCREATE UNIQUE INDEX IF NOT EXISTS \"threads_client_id_user_id_unique\" ON \"threads\" USING btree (\"client_id\",\"user_id\");",
|
418
|
+
"\nCREATE UNIQUE INDEX IF NOT EXISTS \"topics_client_id_user_id_unique\" ON \"topics\" USING btree (\"client_id\",\"user_id\");\n"
|
414
419
|
],
|
415
420
|
"bps": true,
|
416
421
|
"folderMillis": 1742616026643,
|
417
|
-
"hash": "
|
422
|
+
"hash": "110a49a1a7c42ded9a9613edb8dc15fee0b4b3dd8061f871b7b42241f29987b5"
|
423
|
+
},
|
424
|
+
{
|
425
|
+
"sql": [
|
426
|
+
"-- Add hotkey column to user_settings table\nALTER TABLE \"user_settings\" ADD COLUMN IF NOT EXISTS \"hotkey\" jsonb;",
|
427
|
+
"\n"
|
428
|
+
],
|
429
|
+
"bps": true,
|
430
|
+
"folderMillis": 1742806552131,
|
431
|
+
"hash": "d9032edf59f717e0e71da5a95b3545ec251c311155cafe14df01a12800a9eae0"
|
418
432
|
}
|
419
|
-
]
|
433
|
+
]
|