feat(24-03): add bookmark toggle to ChatMessage and ChatMessageActions
- Add onBookmark/isBookmarked props to ChatMessageActions - Render ChatMessageBookmark as last action for user and assistant messages - Add onBookmark/isBookmarked props to ChatMessage, thread to ChatMessageActions - System messages do not receive bookmark actions
This commit is contained in:
parent
0dde83b566
commit
ce037c235c
2 changed files with 51 additions and 18 deletions
|
|
@ -26,6 +26,8 @@ interface ChatMessageProps {
|
||||||
onEdit?: (messageId: string, newContent: string) => void;
|
onEdit?: (messageId: string, newContent: string) => void;
|
||||||
onRetry?: (messageId: string) => void;
|
onRetry?: (messageId: string) => void;
|
||||||
onHandoff?: (spec: { what: string; why: string; constraints: string; success: string }) => void;
|
onHandoff?: (spec: { what: string; why: string; constraints: string; success: string }) => void;
|
||||||
|
onBookmark?: (messageId: string) => void;
|
||||||
|
isBookmarked?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ChatMessage({
|
export function ChatMessage({
|
||||||
|
|
@ -43,6 +45,8 @@ export function ChatMessage({
|
||||||
onEdit,
|
onEdit,
|
||||||
onRetry,
|
onRetry,
|
||||||
onHandoff,
|
onHandoff,
|
||||||
|
onBookmark,
|
||||||
|
isBookmarked,
|
||||||
}: ChatMessageProps) {
|
}: ChatMessageProps) {
|
||||||
const [isEditing, setIsEditing] = useState(false);
|
const [isEditing, setIsEditing] = useState(false);
|
||||||
const [editValue, setEditValue] = useState(content);
|
const [editValue, setEditValue] = useState(content);
|
||||||
|
|
@ -135,6 +139,8 @@ export function ChatMessage({
|
||||||
role="user"
|
role="user"
|
||||||
isStreaming={isAnyStreaming}
|
isStreaming={isAnyStreaming}
|
||||||
onEdit={() => setIsEditing(true)}
|
onEdit={() => setIsEditing(true)}
|
||||||
|
onBookmark={id && onBookmark ? () => onBookmark(id) : undefined}
|
||||||
|
isBookmarked={isBookmarked}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -159,6 +165,8 @@ export function ChatMessage({
|
||||||
role="assistant"
|
role="assistant"
|
||||||
isStreaming={isAnyStreaming}
|
isStreaming={isAnyStreaming}
|
||||||
onRetry={id && onRetry ? () => onRetry(id) : undefined}
|
onRetry={id && onRetry ? () => onRetry(id) : undefined}
|
||||||
|
onBookmark={id && onBookmark ? () => onBookmark(id) : undefined}
|
||||||
|
isBookmarked={isBookmarked}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,23 @@
|
||||||
import { Pencil, RefreshCw } from "lucide-react";
|
import { Pencil, RefreshCw } from "lucide-react";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
|
||||||
|
import { ChatMessageBookmark } from "./ChatMessageBookmark";
|
||||||
|
|
||||||
interface ChatMessageActionsProps {
|
interface ChatMessageActionsProps {
|
||||||
role: "user" | "assistant" | "system";
|
role: "user" | "assistant" | "system";
|
||||||
isStreaming?: boolean;
|
isStreaming?: boolean;
|
||||||
onEdit?: () => void;
|
onEdit?: () => void;
|
||||||
onRetry?: () => void;
|
onRetry?: () => void;
|
||||||
|
onBookmark?: () => void;
|
||||||
|
isBookmarked?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ChatMessageActions({ role, isStreaming, onEdit, onRetry }: ChatMessageActionsProps) {
|
export function ChatMessageActions({ role, isStreaming, onEdit, onRetry, onBookmark, isBookmarked }: ChatMessageActionsProps) {
|
||||||
if (isStreaming) return null;
|
if (isStreaming) return null;
|
||||||
|
|
||||||
if (role === "user" && onEdit) {
|
if (role === "user" && onEdit) {
|
||||||
return (
|
return (
|
||||||
<div className="absolute top-1 right-1 hidden group-hover:flex">
|
<div className="absolute top-1 right-1 hidden group-hover:flex items-center gap-0.5">
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<Button
|
<Button
|
||||||
|
|
@ -29,27 +32,49 @@ export function ChatMessageActions({ role, isStreaming, onEdit, onRetry }: ChatM
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent>Edit message</TooltipContent>
|
<TooltipContent>Edit message</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
{onBookmark && (
|
||||||
|
<ChatMessageBookmark
|
||||||
|
messageId=""
|
||||||
|
conversationId=""
|
||||||
|
isBookmarked={isBookmarked ?? false}
|
||||||
|
onToggle={onBookmark}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (role === "assistant" && onRetry) {
|
if (role === "assistant") {
|
||||||
|
const hasActions = !!onRetry || !!onBookmark;
|
||||||
|
if (!hasActions) return null;
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-end mt-1">
|
<div className="flex justify-end mt-1 gap-0.5">
|
||||||
<Tooltip>
|
{onRetry && (
|
||||||
<TooltipTrigger asChild>
|
<Tooltip>
|
||||||
<Button
|
<TooltipTrigger asChild>
|
||||||
variant="ghost"
|
<Button
|
||||||
size="icon"
|
variant="ghost"
|
||||||
className="h-6 w-6 hidden group-hover:inline-flex"
|
size="icon"
|
||||||
onClick={onRetry}
|
className="h-6 w-6 hidden group-hover:inline-flex"
|
||||||
aria-label="Retry response"
|
onClick={onRetry}
|
||||||
>
|
aria-label="Retry response"
|
||||||
<RefreshCw className="h-3.5 w-3.5" />
|
>
|
||||||
</Button>
|
<RefreshCw className="h-3.5 w-3.5" />
|
||||||
</TooltipTrigger>
|
</Button>
|
||||||
<TooltipContent>Retry response</TooltipContent>
|
</TooltipTrigger>
|
||||||
</Tooltip>
|
<TooltipContent>Retry response</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
{onBookmark && (
|
||||||
|
<div className="hidden group-hover:inline-flex">
|
||||||
|
<ChatMessageBookmark
|
||||||
|
messageId=""
|
||||||
|
conversationId=""
|
||||||
|
isBookmarked={isBookmarked ?? false}
|
||||||
|
onToggle={onBookmark}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue