import { useCallback, useEffect, useMemo, useRef, useState } from "react" import { AnimatePresence, motion } from "framer-motion" import { ArrowBendUpLeft, PaperPlaneTilt, X, ChatCircle } from "@phosphor-icons/react" import type { AgentMessageRecord, AgentRecord, MessageChannel } from "@shared/types" import { unwrap } from "../../lib/desktop" import { InlineNotice } from "../ui" import { AgentAvatar } from "./MessageItem" import { useT } from "../../i18n" function SendButton({ sending, disabled, onClick, label }: { sending: boolean; disabled: boolean; onClick: () => void; label: string }) { return ( ) } interface MessageComposerProps { agents: AgentRecord[]; companyId: string; channel: MessageChannel; channelTargetId: string | null directParticipantIds?: string[]; replyTo: AgentMessageRecord | null; onSent: () => void; onCancelReply: () => void } export function MessageComposer({ agents, companyId, channel, channelTargetId, directParticipantIds = [], replyTo, onSent, onCancelReply }: MessageComposerProps) { const [fromAgentId, setFromAgentId] = useState(agents[0]?.id ?? "") const [body, setBody] = useState(""); const [subject, setSubject] = useState("") const [sending, setSending] = useState(false); const [sendError, setSendError] = useState(null) const textareaRef = useRef(null) useEffect(() => { if (replyTo) textareaRef.current?.focus() }, [replyTo]) useEffect(() => { if (agents.length === 0) { if (fromAgentId) setFromAgentId(""); return }; if (!agents.some((a) => a.id === fromAgentId)) setFromAgentId(agents[0]?.id ?? "") }, [agents, fromAgentId]) const directRecipientId = useMemo(() => { if (channel !== "direct") return null if (replyTo?.fromAgentId) return replyTo.fromAgentId if (directParticipantIds.length === 0) return null if (directParticipantIds.length === 1) return directParticipantIds[0] ?? null if (fromAgentId && directParticipantIds.includes(fromAgentId)) return directParticipantIds.find((id) => id !== fromAgentId) ?? null return directParticipantIds[0] ?? null }, [channel, replyTo, directParticipantIds, fromAgentId]) const handleSend = useCallback(async () => { if (!body.trim() || !fromAgentId) return; if (channel === "direct" && !directRecipientId) return if (!agents.some((a) => a.id === fromAgentId)) { setSendError("Select a valid sender."); return } setSending(true); setSendError(null) try { unwrap(await window.agentCompany.sendAgentMessage({ companyId, fromAgentId, toAgentId: channel === "direct" ? directRecipientId : null, channel, channelTargetId, subject: subject.trim() || (replyTo ? `Re: ${replyTo.subject}` : ""), body: body.trim(), priority: "normal", parentMessageId: replyTo?.id ?? null, attachmentsJson: "[]" })); setBody(""); setSubject(""); onSent() } catch (e) { setSendError(e instanceof Error ? e.message : "Failed to send message.") } finally { setSending(false) } }, [agents, body, channel, channelTargetId, companyId, directRecipientId, fromAgentId, onSent, replyTo, subject]) const handleKeyDown = useCallback((e: React.KeyboardEvent) => { if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) { e.preventDefault(); void handleSend() } }, [handleSend]) const fromAgent = agents.find((a) => a.id === fromAgentId) return (
{sendError ?
: null} {channel === "direct" && !directRecipientId ?
: null} {replyTo ? ( Replying to {agents.find((a) => a.id === replyTo.fromAgentId)?.name ?? "agent"}{replyTo.subject ? `: ${replyTo.subject}` : ""} ) : null}
{!replyTo ? setSubject(e.target.value)} placeholder="Subject (optional)" aria-label="Message subject" className="min-w-0 flex-1 rounded-lg border border-border bg-card px-2.5 py-1 text-[11px] text-foreground placeholder:text-muted-foreground" /> : null}