diff --git a/apps/desktop/layer/renderer/src/modules/ai-chat/components/message/UserChatMessage.tsx b/apps/desktop/layer/renderer/src/modules/ai-chat/components/message/UserChatMessage.tsx index 6b7340bc1..8a6afeff5 100644 --- a/apps/desktop/layer/renderer/src/modules/ai-chat/components/message/UserChatMessage.tsx +++ b/apps/desktop/layer/renderer/src/modules/ai-chat/components/message/UserChatMessage.tsx @@ -141,7 +141,7 @@ export const UserChatMessage: React.FC = React.memo(({ mes >
{/* Normal message display - always rendered to maintain layout */} -
+
diff --git a/apps/desktop/layer/renderer/src/modules/ai-chat/components/message/UserRichTextMessage.tsx b/apps/desktop/layer/renderer/src/modules/ai-chat/components/message/UserRichTextMessage.tsx index f0e9eb209..87292b7e6 100644 --- a/apps/desktop/layer/renderer/src/modules/ai-chat/components/message/UserRichTextMessage.tsx +++ b/apps/desktop/layer/renderer/src/modules/ai-chat/components/message/UserRichTextMessage.tsx @@ -10,7 +10,10 @@ import type { SerializedEditorState } from "lexical" import * as React from "react" import isEqual from "react-fast-compare" +import { useAISettingValue } from "~/atoms/settings/ai" + import { LexicalAIEditorNodes } from "../../editor" +import { MentionComponent } from "../../editor/plugins/mention" function onError(error: Error) { console.error("Lexical Read-Only Editor Error:", error) @@ -26,6 +29,48 @@ interface UserRichTextMessageProps { export const UserRichTextMessage: React.FC = React.memo( ({ data, className }) => { + const aiSettings = useAISettingValue() + const { shortcuts } = aiSettings + + const shortcutMention = React.useMemo(() => { + const rawText = data.text + const normalizedText = rawText.trim() + if (!normalizedText) { + return null + } + + const matchedShortcut = shortcuts.find((shortcut) => { + if (!shortcut.enabled) { + return false + } + + if (shortcut.prompt === rawText) { + return true + } + + return shortcut.prompt.trim() === normalizedText + }) + + if (!matchedShortcut) { + return null + } + + return { + id: matchedShortcut.id, + name: matchedShortcut.name, + type: "shortcut" as const, + value: matchedShortcut.prompt, + } + }, [data.text, shortcuts]) + + if (shortcutMention) { + return ( +
+ +
+ ) + } + const editorState = typeof data.state === "object" ? JSON.stringify(data.state) : data.state let initialConfig: InitialConfigType = null! diff --git a/apps/desktop/layer/renderer/src/modules/ai-chat/editor/plugins/mention/components/MentionComponent.tsx b/apps/desktop/layer/renderer/src/modules/ai-chat/editor/plugins/mention/components/MentionComponent.tsx index 7517a788d..bb8e98ceb 100644 --- a/apps/desktop/layer/renderer/src/modules/ai-chat/editor/plugins/mention/components/MentionComponent.tsx +++ b/apps/desktop/layer/renderer/src/modules/ai-chat/editor/plugins/mention/components/MentionComponent.tsx @@ -33,6 +33,7 @@ const MentionTooltipContent = ({ mentionData.type === "entry" && "bg-blue", mentionData.type === "feed" && "bg-orange", mentionData.type === "date" && "bg-purple", + mentionData.type === "shortcut" && "bg-amber-700", )} > @@ -79,6 +80,9 @@ const getMentionStyles = (type: MentionData["type"]) => { case "view": { return cn(baseStyles) } + case "shortcut": { + return cn(baseStyles, "text-amber-700 border-amber-700/20", "hover:border-amber-700/30") + } } } export const MentionComponent: React.FC = ({ mentionData, className }) => { @@ -89,7 +93,11 @@ export const MentionComponent: React.FC = ({ mentionData, if (mentionData.type === "date") { return getDateMentionDisplayName(mentionData, t, language, RANGE_WITH_LABEL_KEY) } - return mentionData.name + if (mentionData.type === "shortcut") { + return mentionData.name + } else { + return `@${mentionData.name}` + } }, [mentionData, t, language]) const handleClick = (e: React.MouseEvent) => { @@ -108,7 +116,7 @@ export const MentionComponent: React.FC = ({ mentionData, value={mentionData.value} className="mr-1 translate-y-[2px]" /> - @{displayName} + {displayName} diff --git a/apps/desktop/layer/renderer/src/modules/ai-chat/editor/plugins/mention/components/shared/MentionTypeIcon.tsx b/apps/desktop/layer/renderer/src/modules/ai-chat/editor/plugins/mention/components/shared/MentionTypeIcon.tsx index 5568deede..0df175408 100644 --- a/apps/desktop/layer/renderer/src/modules/ai-chat/editor/plugins/mention/components/shared/MentionTypeIcon.tsx +++ b/apps/desktop/layer/renderer/src/modules/ai-chat/editor/plugins/mention/components/shared/MentionTypeIcon.tsx @@ -38,6 +38,9 @@ export const MentionTypeIcon: React.FC = ({ } return } + case "shortcut": { + return + } default: { return } diff --git a/apps/desktop/layer/renderer/src/modules/ai-chat/editor/plugins/mention/types.ts b/apps/desktop/layer/renderer/src/modules/ai-chat/editor/plugins/mention/types.ts index fb3f26d7b..9a4ec8d28 100644 --- a/apps/desktop/layer/renderer/src/modules/ai-chat/editor/plugins/mention/types.ts +++ b/apps/desktop/layer/renderer/src/modules/ai-chat/editor/plugins/mention/types.ts @@ -1,4 +1,4 @@ -export type MentionType = "entry" | "feed" | "date" | "category" | "view" +export type MentionType = "entry" | "feed" | "date" | "category" | "view" | "shortcut" export type MentionLabelValue = string | number | boolean | MentionLabelDescriptor