Allow stalled chat uploads to be cancelled

This commit is contained in:
pewdiepie-archdaemon
2026-06-29 02:06:39 +00:00
parent b419caf9f7
commit e2c8b8eb37
2 changed files with 56 additions and 1 deletions
+12
View File
@@ -292,6 +292,9 @@ import { wireArrowUpRecall, getLastUserMessageFromChatHistory } from './composer
// If currently streaming, stop it
if (isStreaming) {
if (fileHandlerModule.isUploading && fileHandlerModule.isUploading()) {
fileHandlerModule.cancelUpload && fileHandlerModule.cancelUpload();
}
// Cancel server-side research if in progress
const _cancelSid = sessionModule.getCurrentSessionId();
if (_cancelSid && _researchingStreamIds.has(_cancelSid)) {
@@ -687,6 +690,15 @@ import { wireArrowUpRecall, getLastUserMessageFromChatHistory } from './composer
} catch(e) {
console.error('upload failed', e);
}
if (_pendingAttachInfo && !ids.length && !(_pendingRegenAttachments && _pendingRegenAttachments.length)) {
if (_userMsgEl && _userMsgEl.parentNode) _userMsgEl.remove();
if (fileHandlerModule.wasLastUploadCancelled && !fileHandlerModule.wasLastUploadCancelled()) {
uiModule.showError && uiModule.showError('Upload failed. Attachment kept so you can retry.');
}
updateSubmitButton('idle', submitBtn);
_releaseSendFlag();
return;
}
// Carry over the original message's file-ids on a regenerate so the new
// send still references the same photos / docs (and picks up the user's
+44 -1
View File
@@ -15,6 +15,9 @@ let uploaded = [];
let _lastUploadedMeta = [];
let API_BASE = '';
let _uploadSpinners = [];
let _uploadAbortCtrl = null;
let _uploading = false;
let _lastUploadCancelled = false;
const _previewUrls = new WeakMap();
const MAX_FILES = 10;
@@ -130,6 +133,7 @@ function _createChip(f, idx) {
* Remove a pending file by index
*/
export function removePending(idx) {
if (_uploading) cancelUpload();
_revokePreviewUrl(pendingFiles[idx]);
pendingFiles.splice(idx, 1);
renderAttachStrip();
@@ -140,6 +144,7 @@ export function removePending(idx) {
*/
export async function uploadPending() {
if (pendingFiles.length === 0) return [];
_lastUploadCancelled = false;
// The message bubble is shown immediately, but the upload can take a moment —
// dim the chips and overlay a whirlpool so it's clear the files are still
@@ -164,11 +169,19 @@ export async function uploadPending() {
const fd = new FormData();
pendingFiles.forEach(f => fd.append('files', f, f.name || 'paste.png'));
_uploadAbortCtrl = new AbortController();
_uploading = true;
const timeoutId = setTimeout(() => {
if (_uploadAbortCtrl && !_uploadAbortCtrl.signal.aborted) {
try { _uploadAbortCtrl.abort(); } catch (_) {}
}
}, 120000);
try {
const res = await fetch(`${API_BASE}/api/upload`, {
method: 'POST',
body: fd
body: fd,
signal: _uploadAbortCtrl.signal,
});
if (!res.ok) {
// Surface the failure instead of swallowing it. Previously a non-OK
@@ -193,7 +206,18 @@ export async function uploadPending() {
// returned shape as `ids` for backward-compatibility with existing call sites.
_lastUploadedMeta = uploaded;
return uploaded.map(x => x.id);
} catch (e) {
if (e && e.name === 'AbortError') {
_lastUploadCancelled = true;
_showToast('Upload cancelled');
return [];
}
_showToast('Upload failed: ' + (e?.message || 'network error'));
return [];
} finally {
clearTimeout(timeoutId);
_uploading = false;
_uploadAbortCtrl = null;
_uploadSpinners.forEach(sp => { try { sp.stop && sp.stop(); } catch (_) {} });
_uploadSpinners = [];
if (strip) strip.classList.remove('attach-uploading');
@@ -266,6 +290,7 @@ export function getPendingInfo() {
* Clear all pending files
*/
export function clearPending() {
if (_uploading) cancelUpload();
pendingFiles.forEach(_revokePreviewUrl);
pendingFiles = [];
renderAttachStrip();
@@ -276,6 +301,21 @@ export function getLastUploadedMeta() {
return _lastUploadedMeta;
}
export function isUploading() {
return _uploading;
}
export function wasLastUploadCancelled() {
return _lastUploadCancelled;
}
export function cancelUpload() {
_lastUploadCancelled = true;
if (_uploadAbortCtrl && !_uploadAbortCtrl.signal.aborted) {
try { _uploadAbortCtrl.abort(); } catch (_) {}
}
}
var escapeHtml = uiModule.esc;
const fileHandlerModule = {
@@ -290,6 +330,9 @@ const fileHandlerModule = {
getPendingRaw,
clearPending,
getLastUploadedMeta,
isUploading,
wasLastUploadCancelled,
cancelUpload,
};
export default fileHandlerModule;