Fix SW not ready: add registration + wait for controller
The service worker was never registered. Added registration in the base template. Upload logic now waits for the SW to claim the page instead of erroring, with a direct-fetch fallback if SW times out. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
0ce44383b5
commit
6c4c21591f
|
|
@ -161,6 +161,18 @@
|
||||||
{% block content %}{% endblock %}
|
{% block content %}{% endblock %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
if ('serviceWorker' in navigator) {
|
||||||
|
navigator.serviceWorker.register('/static/portal/sw.js').then(reg => {
|
||||||
|
// If the SW is installed but not yet controlling this page, reload once
|
||||||
|
if (reg.active && !navigator.serviceWorker.controller) {
|
||||||
|
navigator.serviceWorker.addEventListener('controllerchange', () => {
|
||||||
|
// Controller is now active, no need to reload
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
{% block extra_js %}{% endblock %}
|
{% block extra_js %}{% endblock %}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -404,9 +404,10 @@ async function uploadFile(file, action) {
|
||||||
// Store blob in IndexedDB so service worker can access it
|
// Store blob in IndexedDB so service worker can access it
|
||||||
await dbPut('uploads', { id, blob: file, filename: file.name });
|
await dbPut('uploads', { id, blob: file, filename: file.name });
|
||||||
|
|
||||||
// Tell service worker to upload
|
try {
|
||||||
if (navigator.serviceWorker.controller) {
|
// Wait for SW controller if not ready yet (first visit)
|
||||||
navigator.serviceWorker.controller.postMessage({
|
const ctrl = await getSWController();
|
||||||
|
ctrl.postMessage({
|
||||||
type: 'START_UPLOAD',
|
type: 'START_UPLOAD',
|
||||||
id,
|
id,
|
||||||
uploadUrl: UPLOAD_URL,
|
uploadUrl: UPLOAD_URL,
|
||||||
|
|
@ -414,12 +415,47 @@ async function uploadFile(file, action) {
|
||||||
filename: file.name,
|
filename: file.name,
|
||||||
action: action || null,
|
action: action || null,
|
||||||
});
|
});
|
||||||
} else {
|
} catch (e) {
|
||||||
// Fallback: no SW controller yet, upload directly
|
// SW not available — fall back to direct upload from page
|
||||||
showError(item, file.name, 'Service worker not ready — please refresh and try again');
|
directUpload(item, id, file, action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function directUpload(item, id, file, action) {
|
||||||
|
try {
|
||||||
|
const fd = new FormData();
|
||||||
|
fd.append('file', file, file.name);
|
||||||
|
fd.append('space', SPACE);
|
||||||
|
if (action) fd.append('action', action);
|
||||||
|
const resp = await fetch(UPLOAD_URL, { method: 'POST', body: fd });
|
||||||
|
const result = await resp.json();
|
||||||
|
await dbDelete('uploads', id);
|
||||||
|
if (resp.status === 409 && result.duplicate) {
|
||||||
|
showDuplicate(item, id, result, file.name);
|
||||||
|
} else if (resp.ok && result.success) {
|
||||||
|
showSuccess(item, result);
|
||||||
|
} else {
|
||||||
|
showError(item, file.name, result.error || 'Upload failed');
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
showError(item, file.name, err.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSWController() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (navigator.serviceWorker.controller) {
|
||||||
|
return resolve(navigator.serviceWorker.controller);
|
||||||
|
}
|
||||||
|
// Wait for the SW to claim this page (happens after first install)
|
||||||
|
const timeout = setTimeout(() => reject(new Error('SW timeout')), 10000);
|
||||||
|
navigator.serviceWorker.addEventListener('controllerchange', () => {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
resolve(navigator.serviceWorker.controller);
|
||||||
|
}, { once: true });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// --- Listen for messages from service worker ---
|
// --- Listen for messages from service worker ---
|
||||||
|
|
||||||
navigator.serviceWorker.addEventListener('message', (event) => {
|
navigator.serviceWorker.addEventListener('message', (event) => {
|
||||||
|
|
@ -468,9 +504,9 @@ navigator.serviceWorker.addEventListener('message', (event) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// On page load, ask SW for any completed results from background uploads
|
// On page load, ask SW for any completed results from background uploads
|
||||||
if (navigator.serviceWorker.controller) {
|
getSWController().then(ctrl => {
|
||||||
navigator.serviceWorker.controller.postMessage({ type: 'GET_RESULTS' });
|
ctrl.postMessage({ type: 'GET_RESULTS' });
|
||||||
}
|
}).catch(() => {});
|
||||||
|
|
||||||
function copyLink(btn, url) {
|
function copyLink(btn, url) {
|
||||||
navigator.clipboard.writeText(url).then(() => {
|
navigator.clipboard.writeText(url).then(() => {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue