fix(ui): on-screen error overlay so companion crashes are visible without a console
chrome://inspect isn't always reachable on the Android companion WebView, so the real error stayed invisible. Add a plain-DOM, screenshot-able overlay (built without Vue so it survives a crash in Vue itself) that shows the captured error message + stack and a Copy button for the full window.__archyErrors buffer. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
0ab160b5c3
commit
242baf5deb
@ -45,6 +45,52 @@ interface ArchyErrorEntry { when: string; source: string; message: string; info?
|
||||
const errorLog: ArchyErrorEntry[] = []
|
||||
;(window as unknown as { __archyErrors?: ArchyErrorEntry[] }).__archyErrors = errorLog
|
||||
|
||||
// On-screen, screenshot-able error overlay. Built with plain DOM (not a Vue
|
||||
// component) so it still appears when the crash is in Vue itself or in a runtime
|
||||
// with no dev console (the Android companion WebView — chrome://inspect isn't
|
||||
// always reachable). The user can read/screenshot the real error and the stack
|
||||
// straight off the device, and "Copy" puts the full ring buffer on the clipboard.
|
||||
function showErrorOverlay() {
|
||||
const id = 'archy-error-overlay'
|
||||
let box = document.getElementById(id)
|
||||
if (!box) {
|
||||
box = document.createElement('div')
|
||||
box.id = id
|
||||
box.style.cssText = [
|
||||
'position:fixed', 'left:8px', 'right:8px', 'bottom:8px', 'z-index:2147483647',
|
||||
'max-height:45vh', 'overflow:auto', 'background:rgba(20,0,0,0.92)', 'color:#ffd7d7',
|
||||
'font:12px/1.4 ui-monospace,SFMono-Regular,Menlo,monospace', 'padding:10px 12px',
|
||||
'border:1px solid #ff5a5a', 'border-radius:10px', 'white-space:pre-wrap',
|
||||
'word-break:break-word', '-webkit-user-select:text', 'user-select:text',
|
||||
].join(';')
|
||||
document.body.appendChild(box)
|
||||
}
|
||||
const latest = errorLog[errorLog.length - 1]
|
||||
const dump = errorLog
|
||||
.map((e) => `[${e.source}] ${e.message}${e.info ? ` (${e.info})` : ''}${e.stack ? `\n${e.stack.split('\n').slice(0, 4).join('\n')}` : ''}`)
|
||||
.join('\n──\n')
|
||||
box.innerHTML = ''
|
||||
const bar = document.createElement('div')
|
||||
bar.style.cssText = 'display:flex;gap:8px;justify-content:space-between;align-items:center;margin-bottom:6px'
|
||||
const title = document.createElement('b')
|
||||
title.textContent = `⚠ App error (${errorLog.length}) — screenshot or Copy`
|
||||
title.style.color = '#ff8a8a'
|
||||
const btns = document.createElement('div')
|
||||
const mkBtn = (label: string, fn: () => void) => {
|
||||
const b = document.createElement('button')
|
||||
b.textContent = label
|
||||
b.style.cssText = 'margin-left:6px;background:#ff5a5a;color:#1a0000;border:0;border-radius:6px;padding:3px 9px;font-weight:700'
|
||||
b.onclick = fn
|
||||
return b
|
||||
}
|
||||
btns.appendChild(mkBtn('Copy', () => { navigator.clipboard?.writeText(JSON.stringify(errorLog, null, 2)) }))
|
||||
btns.appendChild(mkBtn('Dismiss', () => { box?.remove() }))
|
||||
bar.appendChild(title); bar.appendChild(btns)
|
||||
const body = document.createElement('div')
|
||||
body.textContent = latest ? dump : 'no error captured'
|
||||
box.appendChild(bar); box.appendChild(body)
|
||||
}
|
||||
|
||||
function recordError(source: string, err: unknown, info?: string) {
|
||||
const e = err as { message?: string; stack?: string } | undefined
|
||||
const message = (e?.message ?? String(err)) || 'unknown error'
|
||||
@ -58,6 +104,8 @@ function recordError(source: string, err: unknown, info?: string) {
|
||||
try {
|
||||
useToast().error(`Something went wrong: ${short}`)
|
||||
} catch { /* toast itself failed — the console + ring buffer still have it */ }
|
||||
// Always show the on-device overlay so the error is visible without a console.
|
||||
try { showErrorOverlay() } catch { /* overlay is best-effort */ }
|
||||
}
|
||||
|
||||
app.config.errorHandler = (err, _instance, info) => recordError('Vue Error', err, info)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user