({ message, cwd, onOpenFile, entryId, onFork, forking, onNavigate, prevAssistantEntryId, onEditContent }: {
message: UserMessage;
cwd?: string;
onOpenFile?: (filePath: string) => void;
entryId?: string;
onFork?: (entryId: string) => void;
forking?: boolean;
onNavigate?: (entryId: string) => void;
prevAssistantEntryId?: string;
onEditContent?: (content: string) => void;
})
| 137 | }); |
| 138 | |
| 139 | function UserMessageView({ message, cwd, onOpenFile, entryId, onFork, forking, onNavigate, prevAssistantEntryId, onEditContent }: { |
| 140 | message: UserMessage; |
| 141 | cwd?: string; |
| 142 | onOpenFile?: (filePath: string) => void; |
| 143 | entryId?: string; |
| 144 | onFork?: (entryId: string) => void; |
| 145 | forking?: boolean; |
| 146 | onNavigate?: (entryId: string) => void; |
| 147 | prevAssistantEntryId?: string; |
| 148 | onEditContent?: (content: string) => void; |
| 149 | }) { |
| 150 | const [hovered, setHovered] = useState(false); |
| 151 | const [copied, setCopied] = useState(false); |
| 152 | |
| 153 | const content = |
| 154 | typeof message.content === "string" |
| 155 | ? message.content |
| 156 | : message.content |
| 157 | .filter((b): b is TextContent => b.type === "text") |
| 158 | .map((b) => b.text) |
| 159 | .join("\n"); |
| 160 | |
| 161 | const imageBlocks: ImageContent[] = |
| 162 | typeof message.content === "string" |
| 163 | ? [] |
| 164 | : message.content.filter((b): b is ImageContent => b.type === "image"); |
| 165 | |
| 166 | const time = formatTime(message.timestamp); |
| 167 | const canFork = !!entryId && !!onFork; |
| 168 | const canNavigate = !!prevAssistantEntryId && !!onNavigate; |
| 169 | |
| 170 | const copyContent = () => { |
| 171 | copyText(content).then(() => { |
| 172 | setCopied(true); |
| 173 | setTimeout(() => setCopied(false), 1500); |
| 174 | }); |
| 175 | }; |
| 176 | |
| 177 | return ( |
| 178 | <div |
| 179 | style={{ marginBottom: 16, display: "flex", flexDirection: "column", alignItems: "flex-end" }} |
| 180 | onMouseEnter={() => setHovered(true)} |
| 181 | onMouseLeave={() => setHovered(false)} |
| 182 | > |
| 183 | <div style={{ display: "flex", alignItems: "flex-end", gap: 6, maxWidth: "85%" }}> |
| 184 | <div |
| 185 | style={{ |
| 186 | flex: 1, |
| 187 | minWidth: 0, |
| 188 | background: "var(--user-bg)", |
| 189 | border: "1px solid rgba(59,130,246,0.2)", |
| 190 | borderRadius: 12, |
| 191 | padding: "8px 12px", |
| 192 | fontSize: 14, |
| 193 | lineHeight: 1.6, |
| 194 | color: "var(--text)", |
| 195 | wordBreak: "break-word", |
| 196 | }} |
nothing calls this directly
no test coverage detected