Extension: surface a disconnected-tablet warning instead of silent success
A push can succeed server-side (session created) with nowhere to actually deliver to — the backend's pushNavigate() already distinguishes this via a delivered:false return (see device-stream.js), but nothing in the extension read it: every surface just said "Sent" regardless. Confirmed live on the dev stack 2026-10-01 — the registered dev tablet hadn't heartbeated in a month, so a push looked successful but nothing happened. Now every send path (injected buttons' fast path + manual picker, popup's fast path + manual picker) shows an amber "tablet isn't connected right now" warning when delivered is false. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
db6ffb7aa4
commit
4aeca15281
3 changed files with 28 additions and 7 deletions
|
|
@ -107,7 +107,12 @@ async function pushBooking(bookingId, deviceId) {
|
||||||
// from other failures — used by content-script.js's default-tablet
|
// from other failures — used by content-script.js's default-tablet
|
||||||
// fast-path to decide whether to fall back to the device picker.
|
// fast-path to decide whether to fall back to the device picker.
|
||||||
if (!res.ok) return { ok: false, status: res.status, error: body.error || `HTTP ${res.status}` };
|
if (!res.ok) return { ok: false, status: res.status, error: body.error || `HTTP ${res.status}` };
|
||||||
return { ok: true, status: res.status };
|
// delivered: false means the push landed server-side (a session was
|
||||||
|
// created, the tablet will pick it up if it reconnects) but there's no
|
||||||
|
// live SSE connection for that device right now — e.g. its kiosk tab
|
||||||
|
// isn't open, or its WiFi dropped. Passed through so callers can warn
|
||||||
|
// honestly instead of claiming success a disconnected tablet never saw.
|
||||||
|
return { ok: true, status: res.status, delivered: body.delivered };
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return { ok: false, error: err.message };
|
return { ok: false, error: err.message };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -131,8 +131,13 @@ async function handleSendClick(anchorBtn, bookingId, guestName, variant) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (result?.ok) {
|
if (result?.ok) {
|
||||||
status.textContent = 'Sent — the tablet should navigate now.';
|
if (result.delivered === false) {
|
||||||
status.style.color = '#166534';
|
status.textContent = 'Sent, but that tablet isn’t connected right now — it’ll pick this up if it reconnects.';
|
||||||
|
status.style.color = '#b45309';
|
||||||
|
} else {
|
||||||
|
status.textContent = 'Sent — the tablet should navigate now.';
|
||||||
|
status.style.color = '#166534';
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (result?.status === 409) {
|
if (result?.status === 409) {
|
||||||
|
|
@ -256,7 +261,10 @@ async function togglePanel(anchorBtn, bookingId, guestName, variant = 'block', n
|
||||||
action: 'tcpPush', bookingId, deviceId: select.value,
|
action: 'tcpPush', bookingId, deviceId: select.value,
|
||||||
});
|
});
|
||||||
if (result?.ok) {
|
if (result?.ok) {
|
||||||
panel.textContent = 'Sent — the tablet should navigate now.';
|
panel.textContent = result.delivered === false
|
||||||
|
? 'Sent, but that tablet isn’t connected right now — it’ll pick this up if it reconnects.'
|
||||||
|
: 'Sent — the tablet should navigate now.';
|
||||||
|
panel.style.color = result.delivered === false ? '#b45309' : '#1e293b';
|
||||||
} else {
|
} else {
|
||||||
panel.textContent = `Failed: ${result?.error || 'unknown error'}`;
|
panel.textContent = `Failed: ${result?.error || 'unknown error'}`;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,11 @@ function renderBooking(el, bookingId, devices, defaultDeviceId, baseUrl, apiKey)
|
||||||
if (!msgEl) return; // "Send to a different tablet" was clicked before this resolved
|
if (!msgEl) return; // "Send to a different tablet" was clicked before this resolved
|
||||||
|
|
||||||
if (result.ok) {
|
if (result.ok) {
|
||||||
setMsg(msgEl, 'Sent — the tablet should navigate now.', 'ok');
|
if (result.delivered === false) {
|
||||||
|
setMsg(msgEl, 'Sent, but that tablet isn’t connected right now — it’ll pick this up if it reconnects.', 'warn');
|
||||||
|
} else {
|
||||||
|
setMsg(msgEl, 'Sent — the tablet should navigate now.', 'ok');
|
||||||
|
}
|
||||||
} else if (result.status === 409) {
|
} else if (result.status === 409) {
|
||||||
// Default went busy in the moment between loading the popup and
|
// Default went busy in the moment between loading the popup and
|
||||||
// sending — fall back to the manual picker rather than leaving the
|
// sending — fall back to the manual picker rather than leaving the
|
||||||
|
|
@ -172,7 +176,11 @@ function renderPicker(el, bookingId, devices, defaultDeviceId, baseUrl, apiKey,
|
||||||
setMsg(msgEl, 'Sending…', 'warn');
|
setMsg(msgEl, 'Sending…', 'warn');
|
||||||
const result = await sendPush(bookingId, deviceSelect.value, baseUrl, apiKey);
|
const result = await sendPush(bookingId, deviceSelect.value, baseUrl, apiKey);
|
||||||
if (result.ok) {
|
if (result.ok) {
|
||||||
setMsg(msgEl, 'Sent — the tablet should navigate now.', 'ok');
|
if (result.delivered === false) {
|
||||||
|
setMsg(msgEl, 'Sent, but that tablet isn’t connected right now — it’ll pick this up if it reconnects.', 'warn');
|
||||||
|
} else {
|
||||||
|
setMsg(msgEl, 'Sent — the tablet should navigate now.', 'ok');
|
||||||
|
}
|
||||||
} else if (result.status === 409) {
|
} else if (result.status === 409) {
|
||||||
setMsg(msgEl, result.error || 'That tablet is busy with another guest right now.', 'warn');
|
setMsg(msgEl, result.error || 'That tablet is busy with another guest right now.', 'warn');
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -191,7 +199,7 @@ async function sendPush(bookingId, deviceId, baseUrl, apiKey) {
|
||||||
});
|
});
|
||||||
const body = await res.json().catch(() => ({}));
|
const body = await res.json().catch(() => ({}));
|
||||||
if (!res.ok) return { ok: false, status: res.status, error: body.error || `HTTP ${res.status}` };
|
if (!res.ok) return { ok: false, status: res.status, error: body.error || `HTTP ${res.status}` };
|
||||||
return { ok: true };
|
return { ok: true, delivered: body.delivered };
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return { ok: false, status: 0, error: err.message };
|
return { ok: false, status: 0, error: err.message };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue