6.3 KiB
TASK 17 — Keyboard (stevia) + dictation polish
Status: shipped-partial; daily dictation use confirmed 2026-08-07. The phone went from NO on-screen keyboard to a working patched stevia with a mic key and live dictation in one session. What shipped works; the follow-ons are UX/layout polish.
What shipped (2026-07-21)
- 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.
Follow-ons (the polish that remains)
-
Dictation UX: the mic key spawns the CLI fire-and-forget — no in-keyboard recording indicator (the CLI sends a notify-send "Listening…" toast, which is coarse). A pressed/recording state on the key itself (stevia has
--statuswired:souveraine-stt --status→ idle|recording) would be the honest tell. Needs a stevia patch to poll status and restyle the key, OR drive it off the notify path.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
Keyboard usable in every app; mic key dictates real speech into the focused field (verified 2026-07-21: "Hello, can you hear me?" end-to-end); pill dismisses without eating key taps; number row, layout switcher, Hunspell suggestions and compact arrows work in the daily layout; a recording indicator makes the mic key's state obvious.
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.