diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 8627023..aa3dbac 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -38,12 +38,15 @@ const busy = ref(false) const connected = ref(false) const socketError = ref('') const socketFailures = ref(0) -// After a few failed socket attempts (some mobile browsers/DPIs refuse wss://), -// stop advertising "reconnecting" and rely on the 5s REST poll instead. +// Some mobile browsers (notably iOS Safari with an auth-gated page) abort the +// wss:// upgrade even when the server accepts it. After a few failures we stop +// retrying, rely on the REST poll, and present it as a normal live state rather +// than a degraded "reconnecting". const usePolling = computed(() => socketFailures.value >= 3) let socket let pollTimer +let statusTimer async function refreshAll() { const [p, o, e, q] = await Promise.all([ @@ -148,12 +151,15 @@ onMounted(async () => { else socketError.value = `socket closed (code ${code})` }, }) - pollTimer = setInterval(refreshAll, 5000) + // Poll fast enough that the UI feels live even when it is the only channel. + pollTimer = setInterval(refreshAll, 3000) + statusTimer = setInterval(() => api.getStatus().then((s) => (status.value = s)), 3000) }) onUnmounted(() => { socket?.close() clearInterval(pollTimer) + clearInterval(statusTimer) }) @@ -168,15 +174,14 @@ onUnmounted(() => { > {{ status.mode }} - + - - - · {{ socketError }} + +