7.4 KiB
TASK 17 — Keyboard (stevia) + dictation polish
Status: Squeekboard replacement source authored 2026-08-11; parser tests green, full package build and glass proof pending. Stevia remains the active fallback until the new Squeekboard package is installed and survives repeated dismiss/reopen cycles.
Current decision (2026-08-11)
One keyboard owns the phone: Squeekboard. The daily layout has a permanent number row plus Fn/numpad; the terminal hint selects the compact terminal layout. Both expose the same first-party dictation action. The old Stevia/Squeekboard switcher and drag-up keyboard swap retire only after the replacement is proven on glass.
Pixel3Arch/pkgs/squeekboard now carries:
- a
dictatelayout action that spawns packaged/usr/bin/souveraine-stt; - daily and terminal layouts with the mic available from their base rows;
- a Cairo-drawn, state-honest mic: restrained violet at idle, three breathing violet bubbles while recording, a rotating broken ring while transcribing, and a red-violet error mark;
- animation driven by
$XDG_RUNTIME_DIR/souveraine-stt/state, polled only while the keyboard widget is mapped.
No bitmap was imported and no Stevia completion code was reused. Native Squeekboard word completion remains the next layer after the single-keyboard path is stable.
Earlier Stevia path (historical, currently installed)
- stevia is the OSK, patched to run under Hyprland. Upstream stevia
hard-requires
zphoc_device_state_v1(phoc-private) before creating a keyboard surface, so under Hyprland it sat "Wayland not yet ready" forever and the phone had NO keyboard. Patched optional.Pixel3Arch/pkgs/stevia(0.56.0-3), builds native on-device. Squeekboard retired (SouveraineOS/blueline/squeekboard/kept as layout reference only). - Mic/dictation key on every layout's bottom row (patch 0002): spawns
souveraine-stt, a record→transcribe→type toggle CLI. Config (endpoint, enable) lives in Config.options.speech, surfaced in the new Settings → Speech page (souveraine402e887), with a live /health probe. STT hits Casey's VPN faster-whisper box (see whisper-stt-server memory). - Terminal arrow keys (patch 0002): the terminal layout's bottom row gained ← ↓ ↑ → (the shortcuts bar always had them but sat under the pill).
- Nav pill fix: the SystemGestureRail was lifting the pill 315px (a
stale squeekboard height) which stacked it OVER the keys and stevia's
upward-opening layout menu — "keyboard selection not working" was this.
Now lifts to stevia's real 200px top edge; pill stays visible as the
dismiss handle, clear of the keys (souveraine
5e5bf04). - souveraine-stt error honesty (
67aeb25): distinguishes server 5xx / 4xx / unreachable from a genuine empty transcript. The old "didn't catch that" on any no-text result masked a whole server outage as a mic bug.
Historical follow-ons and retained evidence
-
Dictation UX: the earlier Stevia implementation established the state contract. Squeekboard now renders that contract directly in the mic key; package and glass proof remain.
2026-07-30 progress:
souveraine-sttnow writes a 3-state file$XDG_RUNTIME_DIR/souveraine-stt/state(idle|recording|transcribing|error) and--statusreads it (with reconciliation). notify toasts fire at every transition. Deployed on the phone.- Real "last word didn't type" cause found + fixed: whisper wraps output
in embedded
\n, andydotool typetyped\nas Enter — chopping/ submitting the dictation mid-stream. The CLI now collapses newlines→spaces (+--key-delay) before typing. - stevia patch 0006 (
pkgs/stevia/0006-dictate-key-status-animation.patch, Pixel3Arche9320be, pkgrel 2): polls the state file frompos-osk-widgetand swaps the dictation key's icon by state (recording = mic pulse, transcribing = content-loading, error = warning). Written, applies clean, NOT YET BUILT — archdev's aarch64 GTK3 sysroot + cross-file aren't set up wherebuild-cross.shexpects; building 0.56.0-2 is the remaining step (thenpacman -U+systemctl --user restart souveraine-stevia, verify with grim).
-
Size: Casey settled on
gsettings set mobi.phosh.osk scaling "[]"(200px, no auto-scale). The taller auto value is['auto-portrait','auto-landscape'](348px). Applies live, no restart. Not a bug — just record the chosen default so a reflash keeps it. -
Layouts: the vendored squeekboard
us+apple(iOS-style) andus+hackerdesigns are the target feel; stevia uses its own JSON layout format (src/layouts/*.jsonin the stevia tree). Porting the iOS layout to stevia is open design work — start from the squeekboard header notes inSouveraineOS/blueline/squeekboard/. The target is now explicit: iOS-like letter geometry, a permanent number row, Hunspell completion retained, working language/layout switcher, mic retained, and compact arrows available outside the terminal-only layout. The parkedsurfaces/quickshell/assets/keyboard/us.jsonnumber-row draft is input, not acceptance. -
Hyprland key safety: Pixel3Arch
a5fdbf6ships stevia 0.56.0-5 with high virtual eventcodes plus zeroed fallback modifiers. Keep the compositor-collision hammer test (bound letters/digits must never dispatch Hyprland actions or shutdown) in every later layout patch. -
TTS:
no serverunblocked 2026-07-28.souveraine-speechservesPOST /audio/speechat10.10.20.123:7863(chatterbox.cpp on ArchDev's RX 560), deliberately API-compatible with the retired VibeVoice route. Config.options.speech.tts and the Settings field are ready — this is now filling in a URL, not building a service.
Context
- Patches:
Pixel3Arch/pkgs/stevia/0001-make-zphoc-device-state-optional.patch(Hyprland compat, upstream candidate) and0002-dictation-key-terminal-arrows.patch(mic key + arrows). - CLI:
Pixel3Arch/rootfs-overlay/usr/local/bin/souveraine-stt. - Shell:
souveraine/surfaces/quickshell/modules/settings/SpeechConfig.qml,modules/common/Config.qml(speech block),settings-phone.qml. - The OSK D-Bus plumbing (sm.puri.OSK0 SetVisible, GlobalStates.oskOpen, the "osk" IPC target) is unchanged from squeekboard — stevia's unit claims the same bus name, so shell chrome tracking needed no changes.
Acceptance
Squeekboard raises from ordinary and terminal inputs, types letters/numbers,
and survives at least five dismiss/reopen cycles. Its mic key dictates real
speech into the focused field and visibly traverses idle → recording →
transcribing → idle; the error state is also forced once. The AI side panels
must not dismiss or strand it. Only after that proof may Stevia,
souveraine-osk-switch, and the shell's keyboard-swap gesture be removed.
Native word completion is a following acceptance step, not a blocker for the
single-keyboard cutover.
Connects to
whisper-stt-server (the STT backend), TASK-15 (dictation is a network
fetcher the idle coordinator must wake for), the stevia patches are
upstream candidates (Hyprland compat especially). Under viewtop the OSK's
z-order is structurally enforced by the compositor (ad2b6cb, TASK-43) — a
layer derived from the surface's furniture role, not a layerrule — so the
layer-collision class this task fought in quickshell does not arise there.