(messageIndex: number, newText: string)
| 939 | } |
| 940 | |
| 941 | const handleEditMessage = async (messageIndex: number, newText: string) => { |
| 942 | const isProcessing = status === "streaming" || status === "submitted" |
| 943 | if (isProcessing) return |
| 944 | |
| 945 | const message = messages[messageIndex] |
| 946 | if (!message || message.role !== "user") return |
| 947 | |
| 948 | // Get the saved XML snapshot for this user message |
| 949 | const savedXml = xmlSnapshotsRef.current.get(messageIndex) |
| 950 | if (!savedXml) { |
| 951 | console.error( |
| 952 | "No saved XML snapshot for message index:", |
| 953 | messageIndex, |
| 954 | ) |
| 955 | return |
| 956 | } |
| 957 | |
| 958 | // Get previous XML and restore diagram state |
| 959 | const previousXml = getPreviousXml(messageIndex) |
| 960 | restoreDiagramFromSnapshot(savedXml) |
| 961 | |
| 962 | // Clean up snapshots for messages after the user message (they will be removed) |
| 963 | cleanupSnapshotsAfter(messageIndex) |
| 964 | |
| 965 | // Create new parts with updated text |
| 966 | const newParts = message.parts?.map((part: any) => { |
| 967 | if (part.type === "text") { |
| 968 | return { ...part, text: newText } |
| 969 | } |
| 970 | return part |
| 971 | }) || [{ type: "text", text: newText }] |
| 972 | |
| 973 | // Remove the user message AND assistant message onwards (sendMessage will re-add the user message) |
| 974 | // Use flushSync to ensure state update is processed synchronously before sending |
| 975 | const newMessages = messages.slice(0, messageIndex) |
| 976 | flushSync(() => { |
| 977 | setMessages(newMessages) |
| 978 | }) |
| 979 | |
| 980 | // Check all quota limits |
| 981 | if (!checkAllQuotaLimits()) return |
| 982 | |
| 983 | // Now send the edited message after state is guaranteed to be updated |
| 984 | sendChatMessage(newParts, savedXml, previousXml, sessionId) |
| 985 | // Token count is tracked in onFinish with actual server usage |
| 986 | } |
| 987 | |
| 988 | // Collapsed view (desktop only) |
| 989 | if (!isVisible && !isMobile) { |
nothing calls this directly
no test coverage detected