Aggregate progress from every browser tab via BroadcastChannel
Extends the existing crossTab coordination so a "manager" tab can subscribe to progress + state events from every sibling tab. The aggregator tab doesn't need its own uploader - it just listens via MultipleUpload.subscribeAllTabs() and renders rows for each active tab. Genuinely unique vs Uppy / FilePond / Dropzone / FineUploader: none expose cross-tab progress aggregation.
Live aggregator (this tab acts as manager):
Also-acts-as-uploader in this tab:
Try it:
- Open this demo in 2 or 3 separate tabs.
- Pick files in one tab, hit upload.
- Watch the dashboard at the top - it shows progress rows for every tab, including the others.
- Close one of the tabs; the dashboard auto-removes its row on the
tabByeevent.
API surface
// Subscribe - no uploader needed in this tab
const unsub = MultipleUpload.subscribeAllTabs((msg) => {
switch (msg.type) {
case 'tabHello': console.log('Tab joined:', msg.tabId); break;
case 'tabBye': console.log('Tab left:', msg.tabId); break;
case 'progress': updateProgressRow(msg); break;
case 'taskState': updateStateRow(msg); break;
}
}, 'my-app-channel');
// Convenience widget (renders into any DOM target):
const dashboard = MultipleUpload.createMultiTabDashboard('#manager-view', {
channel: 'my-app-channel',
keepCompleted: false, // remove finished rows after dismissMs
dismissMs: 4000
});
// Cleanup:
unsub();
dashboard.destroy();Broadcast message shapes
// On task progress (throttled 250ms per task):
{ type: 'progress', tabId, taskId, fileName, fileSize, uploadedBytes,
progress, speed, eta, status, ts }
// On task state change (added / paused / completed / failed / cancelled):
{ type: 'taskState', tabId, taskId, fileName, fileSize, status, prevStatus, ts }
// On tab open / close:
{ type: 'tabHello', tabId, ts }
{ type: 'tabBye', tabId, ts }How it works
- Same channel as crossTab lock coordination: reuses the existing BroadcastChannel; just adds new message types alongside
lock/unlock/probe. - Throttled progress: uploaders emit at most 1 progress broadcast per task per 250ms - keeps the channel quiet even on chunked uploads.
- Listen-only tabs work: a dashboard tab without its own uploader still receives messages - the static listener manages its own BroadcastChannel.
- Same-origin only: BroadcastChannel is sandboxed to a single origin - cross-app leakage isn't possible.
- tabHello on init: uploaders announce themselves the moment they boot, so the dashboard sees them even if no uploads have started yet.
- tabBye on unload: the existing pagehide / beforeunload handler now broadcasts a goodbye message so dashboards drop the row instantly.
Use cases
- Admin / monitoring dashboards: show every active user upload across tabs.
- "Don't close that tab" warnings: a manager tab can detect a user closing their upload-in-flight tab and warn them.
- Federated progress UI: aggregate progress from background-tab uploads into the foreground tab's nav bar.
- Test harnesses: open N tabs all uploading; aggregator-tab confirms throughput / failure rates.