fix: read idleTimeoutMin from settings; clean up idle + splash canvas fixes

This commit is contained in:
frozenKelp
2026-06-09 15:04:18 +05:30
parent 294865fe9d
commit 9f6996dcdb
2 changed files with 53 additions and 3 deletions
@@ -290,6 +290,7 @@
if (logW <= 0 || logH <= 0) return if (logW <= 0 || logH <= 0) return
if (logW === lastLogW && logH === lastLogH && scale === lastScale) return if (logW === lastLogW && logH === lastLogH && scale === lastScale) return
lastLogW = logW; lastLogH = logH; lastScale = scale lastLogW = logW; lastLogH = logH; lastScale = scale
if (live) cleanup() // release old offscreen canvases before rebuilding at new size
const built = buildCards(logW, logH) const built = buildCards(logW, logH)
const stamps = built.cards.map(c => buildStamp(c, scale)) const stamps = built.cards.map(c => buildStamp(c, scale))
const vig = buildVignette(logW, logH, scale) const vig = buildVignette(logW, logH, scale)
@@ -339,10 +340,25 @@
function resume() { if (!paused) return; paused = false; raf = requestAnimationFrame(frame) } function resume() { if (!paused) return; paused = false; raf = requestAnimationFrame(frame) }
function onVis() { document.hidden ? pause() : resume() } function onVis() { document.hidden ? pause() : resume() }
// clears all canvas contexts and nulls live state so the GC can collect the offscreen bitmaps
function cleanup() {
if (live) {
live.stamps.forEach(canvas => {
const c = canvas.getContext('2d')
if (c) c.clearRect(0, 0, canvas.width, canvas.height)
})
const vigCtx = live.vignette.getContext('2d')
if (vigCtx) vigCtx.clearRect(0, 0, live.vignette.width, live.vignette.height)
}
ctx.clearRect(0, 0, el.width, el.height)
live = null
}
document.addEventListener('visibilitychange', onVis) document.addEventListener('visibilitychange', onVis)
raf = requestAnimationFrame(frame) raf = requestAnimationFrame(frame)
return () => { return () => {
cancelAnimationFrame(raf) cancelAnimationFrame(raf)
cleanup()
extraCleanup?.() extraCleanup?.()
document.removeEventListener('visibilitychange', onVis) document.removeEventListener('visibilitychange', onVis)
} }
+37 -3
View File
@@ -24,6 +24,7 @@
const POLL_MS = 1500 const POLL_MS = 1500
let pollTimer: ReturnType<typeof setTimeout> | null = null let pollTimer: ReturnType<typeof setTimeout> | null = null
let idleTimer: ReturnType<typeof setTimeout> | null = null
let polling = false let polling = false
async function pollLoop() { async function pollLoop() {
@@ -117,11 +118,14 @@
polling = true polling = true
pollLoop() pollLoop()
resetIdleTimer()
return () => { return () => {
polling = false polling = false
if (pollTimer !== null) { clearTimeout(pollTimer); pollTimer = null } if (pollTimer !== null) { clearTimeout(pollTimer); pollTimer = null }
if (discordInitialized) destroyRpc() if (idleTimer !== null) { clearTimeout(idleTimer); idleTimer = null }
platformService.destroy() if (discordInitialized) destroyRpc().catch(() => {})
platformService.destroy().catch(() => {})
} }
}) })
@@ -146,7 +150,37 @@
if (appState.status === 'booting') _splashDismissed = false if (appState.status === 'booting') _splashDismissed = false
}) })
function onIdleDismiss() { appState.idleSplash = false } $effect(() => {
if (appState.status === 'ready') resetIdleTimer()
})
$effect(() => {
if (appState.status !== 'ready') return
// capture phase so events from any component — including modals — reset the timer
const onActivity = () => resetIdleTimer()
document.addEventListener('mousemove', onActivity, true)
document.addEventListener('keydown', onActivity, true)
document.addEventListener('touchstart', onActivity, true)
document.addEventListener('click', onActivity, true)
return () => {
document.removeEventListener('mousemove', onActivity, true)
document.removeEventListener('keydown', onActivity, true)
document.removeEventListener('touchstart', onActivity, true)
document.removeEventListener('click', onActivity, true)
}
})
function resetIdleTimer() {
if (idleTimer) clearTimeout(idleTimer)
appState.idleSplash = false
// read the setting live so changes take effect without a restart
const timeoutMs = (settingsState.settings.idleTimeoutMin ?? 5) * 60_000
idleTimer = setTimeout(() => {
if (appState.status === 'ready') appState.idleSplash = true
}, timeoutMs)
}
function onIdleDismiss() { appState.idleSplash = false; resetIdleTimer() }
function onSplashRetry() { function onSplashRetry() {
import('$lib/state/boot.svelte').then(({ retryBoot }) => { import('$lib/state/boot.svelte').then(({ retryBoot }) => {