mirror of
https://github.com/RSSNext/Folo.git
synced 2026-10-29 12:12:59 +08:00
feat: shortcut mention
This commit is contained in:
+1
-1
@@ -141,7 +141,7 @@ export const UserChatMessage: React.FC<UserChatMessageProps> = React.memo(({ mes
|
||||
>
|
||||
<div className="text-text relative flex max-w-[calc(100%-1rem)] flex-col gap-2">
|
||||
{/* Normal message display - always rendered to maintain layout */}
|
||||
<div className="text-text bg-mix-accent/background-1/4 rounded-2xl px-4 py-2.5 backdrop-blur-sm">
|
||||
<div className="text-text bg-sidebar-light rounded-2xl px-4 py-2.5 backdrop-blur-sm">
|
||||
<div className="flex select-text flex-col gap-2 text-sm">
|
||||
<UserMessageParts message={message} />
|
||||
</div>
|
||||
|
||||
+45
@@ -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<UserRichTextMessageProps> = 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 (
|
||||
<div className={cn("text-text relative cursor-text text-sm", className)}>
|
||||
<MentionComponent mentionData={shortcutMention} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const editorState = typeof data.state === "object" ? JSON.stringify(data.state) : data.state
|
||||
|
||||
let initialConfig: InitialConfigType = null!
|
||||
|
||||
+10
-2
@@ -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",
|
||||
)}
|
||||
>
|
||||
<MentionTypeIcon type={mentionData.type} value={mentionData.value} className="size-3" />
|
||||
@@ -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<MentionComponentProps> = ({ mentionData, className }) => {
|
||||
@@ -89,7 +93,11 @@ export const MentionComponent: React.FC<MentionComponentProps> = ({ 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<MentionComponentProps> = ({ mentionData,
|
||||
value={mentionData.value}
|
||||
className="mr-1 translate-y-[2px]"
|
||||
/>
|
||||
<span>@{displayName}</span>
|
||||
<span>{displayName}</span>
|
||||
</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipPortal>
|
||||
|
||||
+3
@@ -38,6 +38,9 @@ export const MentionTypeIcon: React.FC<MentionTypeIconProps> = ({
|
||||
}
|
||||
return <i className={`i-mgc-grid-cute-re ${className}`} />
|
||||
}
|
||||
case "shortcut": {
|
||||
return <i className={`i-mgc-ai-cute-re ${className}`} />
|
||||
}
|
||||
default: {
|
||||
return <i className={`i-mgc-ai-cute-re ${className}`} />
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user