Commit Graph
2 Commits
Author SHA1 Message Date
Palash Debnath 93025d9a81 fix(dictation): stop the widget stranding an empty square, repair the swept data dirs (#1398)
The dictation hotkey could leave a blank dark square stuck on the desktop with no way to dismiss it. Three defects compounded: the tray listener's effect depended on [state], so it detached across an await on every state change and a press landing in that gap was lost; an idle pill renders null, so the window Rust had already shown was empty; and the opaque chrome background made that empty window a hard-edged square. Nothing could hide it — dismiss() is only reachable from the X button, Esc, or a post-session timer, none of which exist for a session that never started.

Fixed at the invariant rather than the call sites: the listener subscribes once for the component's lifetime, the widget window's chrome background is transparent, and an idle-but-visible window reconciles itself to hidden. The reconcile is polled (a dropped press changes no React state, so there is nothing to key an effect off) and aborts if its effect is torn down mid-check, so it can never hide a dictation that has just started.

Also in scope:

- The rename sweep had repointed three data-dir literals at a brand-named directory that does not exist, so smoke-test.sh verified a directory the backend never writes and desktop-prod.sh silently stopped clearing backend state on Windows. Both invisible on macOS, where they are usually run. A guard test now pins the assignments specifically.
- The dictation model picker's download sizes were wrong for all seven models, in both directions — Parakeet TDT v3 (the recommended default) understated 180 MB against an actual 670 MB, while the low-RAM fallbacks were overstated threefold, discouraging exactly the choice that would have helped. Measured from the published repos and pinned by a test.
- The 0.6B Parakeet models now decode on more threads, capped by host cores and still overridable.
- uninstall.ps1 gained a UTF-8 BOM (Windows PowerShell 5.1 mis-decodes its non-ASCII output without one), and sponsor.yml lost its last OmniVoice references.
2026-08-07 05:39:41 +05:30
debpalash 08e19e0c1c feat(uninstall): opt-in, content-free app_uninstalled ping in the uninstall scripts
Before deleting anything, uninstall.sh / uninstall.ps1 now send ONE
best-effort `app_uninstalled` event — but only when the user opted in:
consent is read from the same prefs.json the app writes, AND the ping needs
the backend-written analytics_info.json (present only while analytics is
enabled — consent + build token — and removed on opt-out), because the
generic scripts ship no token of their own. Payload is content-free: app
version, OS name, random per-install id. 2-second timeout, silent failure,
one honest console line ('Sending anonymous uninstall ping (you opted in to
analytics).'); not opted in => nothing sent, nothing printed, and the
dry-run never sends either way.

Tested by exercising the bash script for real (fake $HOME + a curl shim
recording argv: consented/not-consented/dry-run/missing-info flows, plus
data-still-deleted-after-ping) and by static contract checks on the ps1
(consent gate, TimeoutSec 2, try/catch, no baked token). docs/install/
uninstall.md documents the behavior (docs-sync).
2026-07-16 19:59:19 +05:30