-
v0.3.20 Stable
released this
2026-06-17 00:42:51 -07:00 | 7 commits to main since this releasegotifyBoard v0.3.20
What's fixed
Toast window no longer lingers as a bare dark rectangle after the last card
Users intermittently reported that when a toast card finished exiting
(either auto-dismiss or user click), the toast window would remain on
screen as a featureless dark rectangle until the next notification
arrived. Most of the time it worked correctly. The pattern showed up
most often with short dismiss durations or when the user clicked X on
a card within ~200 ms of it appearing.Root cause. The visibility effect in
src/toast/ToastApp.tsxwas an async IIFE with no cancellation or
serialization guard. The show path has 4+ IPC awaits
(setSize,pickMonitor,get_monitor_work_area,setPosition,
show) — easily 10–250 ms of round-trips to the Rust backend. The
hide path is a single fastdismiss_toastinvoke. When effect A
(show, slow) was still mid-pipeline and effect B (hide, fast) ran
and completed first, effect A's finalwin.show()resolved last and
re-showed the window — by which pointToastAppwas renderingnull
because the stack was empty. The user saw the body's opaque
--gb-bgcolor (the toast window isn't OS-transparent), and the
state stuck untilstack.lengthchanged again (next notification).Fix. Every visibility effect run now chains off a shared
Promisequeue, so hide segments wait for prior show segments to
complete in order. The show segment also re-checks
latestStackLenRef.current(updated synchronously on every effect
entry) immediately before its finalwin.show()— if the desired
state has flipped to "hidden" while we were awaiting positioning IPC,
we bail before showing, and the queued hide segment that caused the
flip will run next.Files changed
src/toast/ToastApp.tsx— addedvisibilityOpsRefand
latestStackLenRef; wrapped the existing visibility effect body
inside a chained.then(async () => { ... }); added a
pre-win.show()guard that bails when the latest desired length
is 0.CHANGELOG.md— v0.3.20 entry.package.json,src-tauri/Cargo.toml,src-tauri/Cargo.lock,
src-tauri/tauri.conf.json— version bump to 0.3.20.docs/plans/phase-64-toast-window-stays-visible.md— approved
plan from Phase 64.
Verification
npm run typecheck,npm run lint,npm test— all green
(24 files, 221 tests).- Manual: with toast dismiss = 3 s on the Linux dev build, fired
notifications and either clicked X within ~200 ms or let them
auto-dismiss. The bare-dark-rectangle state did not appear. - Stacked behavior verified: 3 toasts in rapid succession, mixed
click-dismiss and auto-dismiss — window hides cleanly when the
last card exits.
Rollback
git revert v0.3.20and re-runscripts/patch-latest-json.mjswith
v0.3.19 URLs and signatures. v0.3.19 assets remain at tagv0.3.19
oneugene/gotifyboardandeuronvault/gotifyboard-updates. The
v0.3.19 toast countdown behaviour (= v0.3.15) returns; the intermittent
window-lingering bug returns with it.Downloads