fix: recover mobile workspace loading in place (Closes #1124)
CI / lint (pull_request) Successful in 2m50s
CI / build-release (pull_request) Successful in 6s
CI / browser-journey (pull_request) Successful in 3m1s
CI / release-candidate (pull_request) Has been skipped

This commit is contained in:
timmy committed 2026-08-19 10:10:52 +00:00
1 parent db85bfa5f9
commit 9252807364
4 files changed
+187 -75

No files matched your search

+1
View File
@@ -314,6 +314,7 @@
<div class="small" id="notification-page-status" aria-live="polite"></div>
<button class="load-more-notifications" id="load-more-notifications" type="button" hidden>Load older updates</button>
<div class="small" id="my-work-action-status" aria-live="assertive"></div>
<button class="retry-work-route" id="retry-workspace" type="button" hidden>Retry workspace</button>
<button class="release-receipt-launcher" id="release-receipt-launcher" type="button" hidden>Merged · tracking release</button>
<button class="retry-work-route" id="retry-unfiled-draft-sync" type="button" hidden>Retry Draft sync</button>
<div class="small" id="today-sync-status" aria-live="polite">Today is saved on this device.</div>
+61 -27
View File
@@ -1,41 +1,75 @@
async function loadWorkspace({ document, window = null, createLoader = createFeatureLoader }) {
async function loadWorkspace({
document,
window = null,
createLoader = createFeatureLoader,
schedule = callback => setTimeout(callback,750),
}) {
let cameOnline = false;
let replayed = false;
let retryInFlight = null;
const captureOnline = () => { cameOnline = true; };
window?.addEventListener('online', captureOnline);
const status = document.querySelector('#my-work-action-status');
const retryButton = document.querySelector('#retry-workspace');
const url = document.querySelector(
'meta[name="stackchain-feature-today-timer"]'
)?.content || '';
const loader = createLoader({
document,
urls: { 'today-timer': url },
});
if (status) status.textContent = 'Starting workspace…';
try {
await loader.load('today-timer');
if (status) status.textContent = '';
return {
replayOnline(callback) {
if (replayed) return;
replayed = true;
window?.removeEventListener('online', captureOnline);
if (cameOnline) callback();
},
const urls = {'today-timer':url};
const loader = createLoader({document, urls});
let attempts = 0;
const load = () => {
if (attempts++) urls['today-timer'] = url + '?retry=' + attempts;
return loader.load('today-timer');
};
const waitForRecovery = () => new Promise(resolve => {
if (status) status.textContent = 'Workspace unavailable. Reconnect or retry.';
if (retryButton) {
retryButton.hidden = retryButton.disabled = false;
}
const recover = () => {
if (retryInFlight) return retryInFlight;
if (retryButton) retryButton.disabled = true;
retryInFlight = load().then(() => {
window?.removeEventListener('online', recover);
resolve();
}).catch(() => {
if (status) status.textContent = 'Workspace unavailable. Reconnect or retry.';
if (retryButton) retryButton.disabled = false;
}).finally(() => {
retryInFlight = null;
});
return retryInFlight;
};
} catch (error) {
window?.removeEventListener('online', captureOnline);
if (window?.location?.reload) {
if (cameOnline) window.location.reload();
else window.addEventListener('online', () => window.location.reload(), { once: true });
window?.addEventListener('online', recover);
retryButton?.addEventListener('click', recover);
});
try {
await load();
} catch {
await new Promise(resolve => schedule(resolve));
try {
await load();
} catch {
await waitForRecovery();
}
if (status) {
status.textContent = window
? 'Workspace could not load. Reconnect to retry automatically, or reload now.'
: 'Workspace could not load. Check your connection, then reload to retry.';
}
throw error;
}
window?.removeEventListener('online', captureOnline);
if (retryButton) retryButton.hidden = true;
if (status) status.textContent = '';
return {
replayOnline(callback) {
if (replayed) return;
replayed = true;
window?.removeEventListener('online', captureOnline);
if (cameOnline) callback();
},
};
}
if (typeof module !== 'undefined' && module.exports) module.exports = loadWorkspace;
if (typeof module !== 'undefined' && module.exports) module.exports = loadWorkspace;