import { useCallback, useMemo } from 'react'; import { MentionableTextarea } from '@renderer/components/ui/MentionableTextarea'; import { Tooltip, TooltipContent, TooltipTrigger } from '@renderer/components/ui/tooltip'; import { getTeamColorSet } from '@renderer/constants/teamColors'; import { useDraftPersistence } from '@renderer/hooks/useDraftPersistence'; import { useStore } from '@renderer/store'; import { buildReplyBlock } from '@renderer/utils/agentMessageFormatting'; import { formatAgentRole } from '@renderer/utils/formatAgentRole'; import { getModifierKeyName } from '@renderer/utils/keyboardUtils'; import { buildMemberColorMap } from '@renderer/utils/memberHelpers'; import { Send, X } from 'lucide-react'; import type { MentionSuggestion } from '@renderer/types/mention'; import type { ResolvedTeamMember } from '@shared/types'; const MAX_COMMENT_LENGTH = 2000; interface TaskCommentInputProps { teamName: string; taskId: string; members: ResolvedTeamMember[]; replyTo: { author: string; text: string } | null; onClearReply: () => void; } export const TaskCommentInput = ({ teamName, taskId, members, replyTo, onClearReply, }: TaskCommentInputProps): React.JSX.Element => { const addTaskComment = useStore((s) => s.addTaskComment); const addingComment = useStore((s) => s.addingComment); const draft = useDraftPersistence({ key: `taskComment:${teamName}:${taskId}` }); const colorMap = useMemo(() => buildMemberColorMap(members), [members]); const mentionSuggestions = useMemo( () => members.map((m) => ({ id: m.name, name: m.name, subtitle: formatAgentRole(m.role) ?? formatAgentRole(m.agentType) ?? undefined, color: colorMap.get(m.name), })), [members, colorMap] ); const trimmed = draft.value.trim(); const remaining = MAX_COMMENT_LENGTH - trimmed.length; const canSubmit = trimmed.length > 0 && trimmed.length <= MAX_COMMENT_LENGTH && !addingComment; const handleSubmit = useCallback(async () => { if (!canSubmit) return; try { const text = replyTo ? buildReplyBlock(replyTo.author, replyTo.text, trimmed) : trimmed; await addTaskComment(teamName, taskId, text); draft.clearDraft(); onClearReply(); } catch { // Error is stored in addCommentError via store } }, [canSubmit, addTaskComment, teamName, taskId, trimmed, draft, replyTo, onClearReply]); return (
{replyTo ? (
Replying to{' '} { const rc = colorMap.get(replyTo.author); return rc ? getTeamColorSet(rc).text : 'var(--color-text-secondary)'; })(), }} > @{replyTo.author}
{replyTo.text}
Cancel reply
) : null}
void handleSubmit()} > Comment } footerRight={
{remaining < 200 ? ( {remaining} chars left ) : null} {draft.isSaved ? ( Draft saved ) : null}
} />
); };