Skip to content

Commit 44708d7

Browse files
committed
feat(shortcuts): 添加快捷键提示功能至多个组件
1 parent f4d99d6 commit 44708d7

4 files changed

Lines changed: 31 additions & 4 deletions

File tree

src/components/chat/ChatSidebar.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import Conversations from '@ant-design/x/es/conversations'
99
import type { ConversationItemType } from '@ant-design/x/es/conversations/interface'
1010
import { useTranslation } from 'react-i18next'
1111
import { useConversationStore, useProviderStore, useSettingsStore } from '@/stores'
12+
import { getShortcutBinding, formatShortcutForDisplay } from '@/lib/shortcuts'
13+
import type { ShortcutAction } from '@/lib/shortcuts'
1214
import type { Conversation, Message } from '@/types'
1315

1416
function getDateGroup(timestamp: number): string {
@@ -50,6 +52,12 @@ export function ChatSidebar() {
5052
const providers = useProviderStore((s) => s.providers)
5153
const settings = useSettingsStore((s) => s.settings)
5254

55+
const shortcutHint = useCallback((label: string, action: ShortcutAction) => {
56+
if (!settings) return label
57+
const binding = getShortcutBinding(settings, action)
58+
return `${label} (${formatShortcutForDisplay(binding)})`
59+
}, [settings])
60+
5361
const [searchText, setSearchText] = useState('')
5462
const [searchVisible, setSearchVisible] = useState(false)
5563
const [multiSelectMode, setMultiSelectMode] = useState(false)
@@ -586,7 +594,7 @@ export function ChatSidebar() {
586594
onClick={handleShowArchived}
587595
/>
588596
</Tooltip>
589-
<Tooltip title={t('chat.newConversation')}>
597+
<Tooltip title={shortcutHint(t('chat.newConversation'), 'newConversation')}>
590598
<Button
591599
type="text"
592600
icon={<MessageSquarePlus size={16} />}

src/components/chat/ModelSelector.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import React, { useMemo, useState, useCallback, useEffect } from 'react';
2-
import { Tag, Modal, Input, theme } from 'antd';
2+
import { Tag, Modal, Input, theme, Tooltip } from 'antd';
33
import { Search, Settings, Pin, PinOff } from 'lucide-react';
44
import { ModelIcon } from '@lobehub/icons';
55
import { useTranslation } from 'react-i18next';
66
import { useProviderStore, useConversationStore, useSettingsStore, useUIStore } from '@/stores';
7+
import { getShortcutBinding, formatShortcutForDisplay } from '@/lib/shortcuts';
78

89
const PINNED_MODELS_KEY = 'aqbot_pinned_models';
910

@@ -210,6 +211,7 @@ export function ModelSelector({ style, onSelect, overrideCurrentModel, children,
210211
{children ? (
211212
<span onClick={() => setOpen(true)}>{children}</span>
212213
) : (
214+
<Tooltip title={`${t('chat.switchModel', '切换模型')} (${formatShortcutForDisplay(getShortcutBinding(settings, 'toggleModelSelector'))})`}>
213215
<Tag
214216
onClick={() => setOpen(true)}
215217
style={{
@@ -233,6 +235,7 @@ export function ModelSelector({ style, onSelect, overrideCurrentModel, children,
233235
</>
234236
)}
235237
</Tag>
238+
</Tooltip>
236239
)}
237240

238241
<Modal

src/components/layout/Sidebar.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ import { useState } from 'react';
22
import { Tooltip, Avatar, theme } from 'antd';
33
import { MessageSquare, Router, FolderOpen, User } from 'lucide-react';
44
import { useTranslation } from 'react-i18next';
5-
import { useUIStore } from '@/stores';
5+
import { useUIStore, useSettingsStore } from '@/stores';
66
import { useUserProfileStore } from '@/stores/userProfileStore';
7+
import { getShortcutBinding, formatShortcutForDisplay } from '@/lib/shortcuts';
8+
import type { ShortcutAction } from '@/lib/shortcuts';
79
import { useResolvedAvatarSrc } from '@/hooks/useResolvedAvatarSrc';
810
import { UserProfileModal } from './UserProfileModal';
911
import type { PageKey } from '@/types';
@@ -22,11 +24,21 @@ export function Sidebar() {
2224
const profile = useUserProfileStore((s) => s.profile);
2325
const [profileModalOpen, setProfileModalOpen] = useState(false);
2426
const resolvedAvatarSrc = useResolvedAvatarSrc(profile.avatarType, profile.avatarValue);
27+
const settings = useSettingsStore((s) => s.settings);
28+
29+
const NAV_SHORTCUT_MAP: Partial<Record<PageKey, ShortcutAction>> = {
30+
gateway: 'toggleGateway',
31+
};
2532

2633
const renderNavButton = (item: { key: PageKey; icon: React.ReactNode; labelKey: string }) => {
2734
const isActive = activePage === item.key;
35+
const label = t(item.labelKey);
36+
const action = NAV_SHORTCUT_MAP[item.key];
37+
const title = action
38+
? `${label} (${formatShortcutForDisplay(getShortcutBinding(settings, action))})`
39+
: label;
2840
return (
29-
<Tooltip key={item.key} title={t(item.labelKey)} placement="right">
41+
<Tooltip key={item.key} title={title} placement="right">
3042
<button
3143
onClick={() => setActivePage(item.key)}
3244
className="flex items-center justify-center text-base transition-colors"

src/components/layout/TitleBar.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Settings, XCircle, Sun, Moon, Monitor, Globe, Pin, PinOff, RefreshCw }
55
import { useTranslation } from 'react-i18next';
66
import { useUIStore, useSettingsStore } from '@/stores';
77
import { isTauri, invoke } from '@/lib/invoke';
8+
import { getShortcutBinding, formatShortcutForDisplay } from '@/lib/shortcuts';
89

910
const THEME_OPTIONS = [
1011
{ key: 'system', icon: <Monitor size={14} />, labelKey: 'settings.themeSystem' },
@@ -33,6 +34,7 @@ export function TitleBar() {
3334
const themeMode = useSettingsStore((s) => s.settings.theme_mode);
3435
const alwaysOnTop = useSettingsStore((s) => s.settings.always_on_top);
3536
const saveSettings = useSettingsStore((s) => s.saveSettings);
37+
const settings = useSettingsStore((s) => s.settings);
3638

3739
const isInSettings = activePage === 'settings';
3840
const [pinned, setPinned] = useState(alwaysOnTop ?? false);
@@ -224,6 +226,7 @@ export function TitleBar() {
224226
</Tooltip>
225227

226228
{/* Settings Toggle */}
229+
<Tooltip title={`${isInSettings ? t('settings.closeSettings', '关闭设置') : t('settings.openSettings', '设置')} (${formatShortcutForDisplay(getShortcutBinding(settings, 'openSettings'))})`}>
227230
<button
228231
onClick={handleSettingsToggle}
229232
style={{
@@ -247,6 +250,7 @@ export function TitleBar() {
247250
>
248251
{isInSettings ? <XCircle size={14} /> : <Settings size={14} />}
249252
</button>
253+
</Tooltip>
250254
</div>
251255
</div>
252256
);

0 commit comments

Comments
 (0)