From a456a856e6fcb149dfb7c276721e90df363544f6 Mon Sep 17 00:00:00 2001 From: digital-garbage <133010426+digital-garbage@users.noreply.github.com> Date: Tue, 22 Sep 2026 18:48:47 +0300 Subject: [PATCH] fix: upload progress was rebuilding the whole media panel per tick The previous fix (67b1324) put mediaUpload straight into the mediabrowser zone's fingerprint, so every XHR progress tick did a full rebuild of the media grid, thumbnails, and project list -- and closed any open ) on every tick. Mutate quietly and let mediabrowser.js patch its own bar/percent + // in place instead. + function updateMediaUploadProgress(patch) { + if (!state.mediaUpload) return; + Object.assign(state.mediaUpload, patch); + try { window.dispatchEvent(new CustomEvent("funpack-media-upload-progress", { detail: state.mediaUpload })); } catch (_) {} + } function get() { return state; } function _promptPreviewKey(project) { @@ -4427,19 +4437,15 @@ // uploading over a slow connection just looked like nothing was happening. async function uploadMedia(files) { const list = [...files]; - let lastNotify = 0; for (let i = 0; i < list.length; i++) { const f = list[i]; + // A full notify() here (once per file) is what builds the "uploading" drop zone in the + // first place -- see fpMediabrowser in view_bus.js. Progress WITHIN a file goes through + // updateMediaUploadProgress instead, which never touches the store's subscribers. set({ mediaUpload: { current: i + 1, total: list.length, name: f.name, loaded: 0, size: f.size } }); - lastNotify = Date.now(); try { await API.uploadMedia(f, (loaded, total) => { - state.mediaUpload = { ...state.mediaUpload, loaded, size: total || f.size }; - // XHR fires this many times a second -- notify() rebuilds the whole media grid, - // so this throttles to a still-smooth ~8fps instead of hammering a full re-render - // on every tick. The final `loaded === total` (upload done) always gets through. - const now = Date.now(); - if (now - lastNotify >= 120 || loaded >= total) { lastNotify = now; notify(); } + updateMediaUploadProgress({ loaded, size: total || f.size }); }); } catch (e) { console.error("upload failed", e); } } diff --git a/movie_editor/frontend/view_bus.js b/movie_editor/frontend/view_bus.js index b42dd160..36a9d197 100644 --- a/movie_editor/frontend/view_bus.js +++ b/movie_editor/frontend/view_bus.js @@ -176,10 +176,15 @@ projects: st.projects?.length, media: st.mediaBin?.length, mediaPreview: st.mediaPreviewId, - // The upload progress bar/percent live in this zone and change on every XHR - // progress tick without touching mediaBin's length -- without this the drop - // zone never repaints and looks stale for the whole upload. - upload: st.mediaUpload, + // Only the file boundary (which file, 1-of-how-many) belongs in the fingerprint -- + // that's rare enough to justify a full rebuild, which is what creates the "uploading" + // drop zone in the first place. `loaded` ticks many times a second and is deliberately + // left out: a full rebuild on every tick would tear down and rebuild the whole bin + // (thumbs, project list, any open