feat(ai-chat): add shortcut functionality with AI page support

- Updated the ChatShortcutsRow component to include logic for displaying shortcuts based on the AI page context.
- Added a new target option for shortcuts to be displayed specifically on the AI page.
- Modified the ShortcutModalContent to allow users to select the AI page as a target for shortcuts.
- Updated localization files to include new translations for the AI page shortcut target.

Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
Innei 2025-10-22 22:57:15 +08:00
parent 26ea58a87b
commit 2d66d07d34
No known key found for this signature in database
GPG Key ID: 0F62D33977F021F7
6 changed files with 31 additions and 9 deletions

View File

@ -1,3 +1,4 @@
import { getReadonlyRoute } from "@follow/components/atoms/route.js"
import { DEFAULT_SHORTCUT_TARGETS } from "@follow/shared/settings/interface"
import { useCallback, useMemo } from "react"
import { useTranslation } from "react-i18next"
@ -17,12 +18,13 @@ export const ChatShortcutsRow: React.FC<ChatShortcutsRowProps> = ({ onSelect })
const { t } = useTranslation("ai")
const aiSettings = useAISettingValue()
const mainEntryId = useMainEntryId()
const isAiPage = useMemo(() => getReadonlyRoute().location.pathname === "/ai", [])
const shortcutsToDisplay = useMemo(() => {
const shortcuts = aiSettings.shortcuts ?? []
const list: typeof shortcuts = []
const entry: typeof shortcuts = []
const aiPage: typeof shortcuts = []
for (const shortcut of shortcuts) {
if (!shortcut.enabled) continue
const targets =
@ -35,10 +37,19 @@ export const ChatShortcutsRow: React.FC<ChatShortcutsRowProps> = ({ onSelect })
if (targets.includes("entry")) {
entry.push(shortcut)
}
if (targets.includes("ai-page")) {
aiPage.push(shortcut)
}
}
return (mainEntryId ? entry : list) ?? []
}, [aiSettings.shortcuts, mainEntryId])
if (mainEntryId) {
return entry
}
if (isAiPage) {
return aiPage
}
return list
}, [aiSettings.shortcuts, mainEntryId, isAiPage])
const handleAddShortcut = useCreateAIShortcutModal()
const handleCustomize = useCallback(() => {
@ -52,9 +63,12 @@ export const ChatShortcutsRow: React.FC<ChatShortcutsRowProps> = ({ onSelect })
onClick={handleCustomize}
animationDelay={0}
size="sm"
title={t("customize_shortcuts_title")}
title={t("new_shortcuts")}
>
<i className="i-mgc-add-cute-re" />
<span className={shortcutsToDisplay.length > 0 ? "sr-only" : "text-text"}>
{t("new_shortcuts")}
</span>
</AIShortcutButton>
{shortcutsToDisplay.map((shortcut) => (
<AIShortcutButton

View File

@ -197,6 +197,14 @@ export const ShortcutModalContent = ({ shortcut, onSave, onCancel }: ShortcutMod
/>
<span>{t("shortcuts.targets.entry")}</span>
</label>
<label className="flex items-center gap-2">
<Checkbox
size="sm"
checked={displayTargets.includes("ai-page")}
onCheckedChange={(value) => handleTargetChange("ai-page", Boolean(value))}
/>
<span>{t("shortcuts.targets.ai-page")}</span>
</label>
</div>
<p className="text-xs text-text-tertiary">{t("shortcuts.targets.help")}</p>
</div>

View File

@ -27,7 +27,6 @@
"common.generating_title": "Generating title...",
"common.new_chat": "New Chat",
"customize_shortcuts": "Customize shortcuts",
"customize_shortcuts_title": "Customize AI shortcuts",
"delete_chat": "Delete Chat",
"delete_chat_error": "Failed to delete chat",
"delete_chat_message": "Are you sure you want to delete \"{{title}}\"? This action cannot be undone.",
@ -125,6 +124,7 @@
"mentions.section.entry": "Entries",
"mentions.section.feed": "Feeds",
"mentions.section.view": "Views",
"new_shortcuts": "New shortcut",
"personalize.description": "Tell me about yourself to get personalized AI responses.",
"personalize.prompt.help": "This helps AI provide personalized responses based on your preferences.",
"personalize.prompt.placeholder": "Tell me about yourself and how you prefer to read content...",
@ -185,6 +185,7 @@
"shortcuts.name_placeholder": "e.g. Summarize Article",
"shortcuts.prompt": "Prompt",
"shortcuts.prompt_placeholder": "Write a clear instruction for the AI...",
"shortcuts.targets.ai-page": "AI Page",
"shortcuts.targets.entry": "Entry Details",
"shortcuts.targets.help": "Choose scenarios to control where this shortcut appears.",
"shortcuts.targets.label": "Display location",

View File

@ -27,7 +27,6 @@
"common.generating_title": "タイトルを生成中...",
"common.new_chat": "新規チャット",
"customize_shortcuts": "ショートカットをカスタマイズ",
"customize_shortcuts_title": "AIショートカットをカスタマイズ",
"delete_chat": "Chat を削除",
"delete_chat_error": "Chat の削除に失敗しました",
"delete_chat_message": "本当に「{{title}}」を削除してもよろしいですか?この操作は元に戻すことはできません。",

View File

@ -27,7 +27,6 @@
"common.generating_title": "正在生成标题...",
"common.new_chat": "新对话",
"customize_shortcuts": "自定义快捷方式",
"customize_shortcuts_title": "自定义 AI 快捷方式",
"delete_chat": "删除对话",
"delete_chat_error": "删除对话失败",
"delete_chat_message": "确定要删除\"{{title}}\"吗?此操作无法撤销。",
@ -179,6 +178,7 @@
"shortcuts.name_placeholder": "例如:总结文章",
"shortcuts.prompt": "提示",
"shortcuts.prompt_placeholder": "为AI编写清晰的指令...",
"shortcuts.targets.ai-page": "AI 页面",
"shortcuts.targets.entry": "条目详情",
"shortcuts.targets.help": "选择适用场景以控制此快捷方式的展示位置。",
"shortcuts.targets.label": "展示位置",

View File

@ -182,9 +182,9 @@ export interface CustomIntegration {
enabled: boolean
}
export type AIShortcutTarget = "list" | "entry"
export type AIShortcutTarget = "list" | "entry" | "ai-page"
export const DEFAULT_SHORTCUT_TARGETS: readonly AIShortcutTarget[] = ["list", "entry"]
export const DEFAULT_SHORTCUT_TARGETS: readonly AIShortcutTarget[] = ["list", "entry", "ai-page"]
export interface AIShortcut {
id: string