|
160 | 160 | let files = []; |
161 | 161 | let params = {}; |
162 | 162 |
|
| 163 | + // Message queue for storing messages while generating |
| 164 | + let messageQueue: { id: string; prompt: string; files: any[] }[] = []; |
| 165 | +
|
163 | 166 | $: if (chatIdProp) { |
164 | 167 | navigateHandler(); |
165 | 168 | } |
166 | 169 |
|
167 | 170 | const navigateHandler = async () => { |
168 | 171 | loading = true; |
169 | 172 |
|
| 173 | + // Save current queue to sessionStorage before navigating away |
| 174 | + if (messageQueue.length > 0 && $chatId) { |
| 175 | + sessionStorage.setItem(`chat-queue-${$chatId}`, JSON.stringify(messageQueue)); |
| 176 | + } |
| 177 | +
|
170 | 178 | prompt = ''; |
171 | 179 | messageInput?.setText(''); |
172 | 180 |
|
173 | 181 | files = []; |
| 182 | + messageQueue = []; |
174 | 183 | selectedToolIds = []; |
175 | 184 | selectedFilterIds = []; |
176 | 185 | webSearchEnabled = false; |
|
187 | 196 |
|
188 | 197 | await tick(); |
189 | 198 |
|
| 199 | + // Restore queue from sessionStorage |
| 200 | + const storedQueueData = sessionStorage.getItem(`chat-queue-${chatIdProp}`); |
| 201 | + if (storedQueueData) { |
| 202 | + try { |
| 203 | + const restoredQueue = JSON.parse(storedQueueData); |
| 204 | + |
| 205 | + if (restoredQueue.length > 0) { |
| 206 | + sessionStorage.removeItem(`chat-queue-${chatIdProp}`); |
| 207 | + // Check if there are pending tasks (still generating) |
| 208 | + const hasPendingTask = taskIds !== null && taskIds.length > 0; |
| 209 | + if (!hasPendingTask) { |
| 210 | + // No pending tasks - process the queue |
| 211 | + files = restoredQueue.flatMap((m) => m.files); |
| 212 | + await tick(); |
| 213 | + const combinedPrompt = restoredQueue.map((m) => m.prompt).join('\n\n'); |
| 214 | + await submitPrompt(combinedPrompt); |
| 215 | + } else { |
| 216 | + // Has pending tasks - show as queued (chatCompletedHandler will process) |
| 217 | + messageQueue = restoredQueue; |
| 218 | + } |
| 219 | + } |
| 220 | + } catch (e) {} |
| 221 | + } |
| 222 | +
|
190 | 223 | if (storageChatInput) { |
191 | 224 | try { |
192 | 225 | const input = JSON.parse(storageChatInput); |
|
1209 | 1242 | } |
1210 | 1243 |
|
1211 | 1244 | taskIds = null; |
| 1245 | +
|
| 1246 | + // Process message queue - combine all queued messages and submit at once |
| 1247 | + if (messageQueue.length > 0) { |
| 1248 | + const combinedPrompt = messageQueue.map((m) => m.prompt).join('\n\n'); |
| 1249 | + const combinedFiles = messageQueue.flatMap((m) => m.files); |
| 1250 | + messageQueue = []; |
| 1251 | +
|
| 1252 | + // Set the files and submit |
| 1253 | + files = combinedFiles; |
| 1254 | + await tick(); |
| 1255 | + await submitPrompt(combinedPrompt); |
| 1256 | + } |
1212 | 1257 | }; |
1213 | 1258 |
|
1214 | 1259 | const chatActionHandler = async (_chatId, actionId, modelId, responseMessageId, event = null) => { |
|
1606 | 1651 | return; |
1607 | 1652 | } |
1608 | 1653 |
|
| 1654 | + // Check if there are pending tasks (more reliable than lastMessage.done) |
| 1655 | + if (taskIds !== null && taskIds.length > 0) { |
| 1656 | + // Tasks pending - queue the message instead of blocking |
| 1657 | + const _files = JSON.parse(JSON.stringify(files)); |
| 1658 | + messageQueue = [ |
| 1659 | + ...messageQueue, |
| 1660 | + { |
| 1661 | + id: uuidv4(), |
| 1662 | + prompt: userPrompt, |
| 1663 | + files: _files |
| 1664 | + } |
| 1665 | + ]; |
| 1666 | + // Clear input |
| 1667 | + messageInput?.setText(''); |
| 1668 | + prompt = ''; |
| 1669 | + files = []; |
| 1670 | + return; |
| 1671 | + } |
| 1672 | +
|
1609 | 1673 | if (history?.currentId) { |
1610 | 1674 | const lastMessage = history.messages[history.currentId]; |
1611 | | - if (lastMessage.done != true) { |
1612 | | - // Response not done |
1613 | | - return; |
1614 | | - } |
1615 | 1675 |
|
1616 | 1676 | if (lastMessage.error && !lastMessage.content) { |
1617 | 1677 | // Error in response |
|
2568 | 2628 | {stopResponse} |
2569 | 2629 | {createMessagePair} |
2570 | 2630 | {onUpload} |
| 2631 | + {messageQueue} |
| 2632 | + onQueueSendNow={async (id) => { |
| 2633 | + const item = messageQueue.find((m) => m.id === id); |
| 2634 | + if (item) { |
| 2635 | + // Remove from queue |
| 2636 | + messageQueue = messageQueue.filter((m) => m.id !== id); |
| 2637 | + // Stop current generation first |
| 2638 | + await stopResponse(); |
| 2639 | + await tick(); |
| 2640 | + // Set files and submit |
| 2641 | + files = item.files; |
| 2642 | + await tick(); |
| 2643 | + await submitPrompt(item.prompt); |
| 2644 | + } |
| 2645 | + }} |
| 2646 | + onQueueEdit={(id) => { |
| 2647 | + const item = messageQueue.find((m) => m.id === id); |
| 2648 | + if (item) { |
| 2649 | + // Remove from queue |
| 2650 | + messageQueue = messageQueue.filter((m) => m.id !== id); |
| 2651 | + // Set files and restore prompt to input |
| 2652 | + files = item.files; |
| 2653 | + messageInput?.setText(item.prompt); |
| 2654 | + } |
| 2655 | + }} |
| 2656 | + onQueueDelete={(id) => { |
| 2657 | + messageQueue = messageQueue.filter((m) => m.id !== id); |
| 2658 | + }} |
2571 | 2659 | onChange={(data) => { |
2572 | 2660 | if (!$temporaryChatEnabled) { |
2573 | 2661 | saveDraft(data, $chatId); |
|
0 commit comments