diff options
| author | Danilo M. <danix@danix.xyz> | 2026-10-19 11:20:12 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-10-19 11:20:12 +0200 |
| commit | c1fc2001219eb9aa349439b3007b57e1ced25335 (patch) | |
| tree | 900e3fbc9da3a58d8f4e08f68040dd080c75ef84 /desktop/assistant/Card.qml | |
| parent | 5ce0cdf77d19e74d85de8674e88b25db213e8534 (diff) | |
| download | quickshell-c1fc2001219eb9aa349439b3007b57e1ced25335.tar.gz quickshell-c1fc2001219eb9aa349439b3007b57e1ced25335.zip | |
assistant: a mic button asks by voice
Each recording is a pw-record Process of its own, made from a Component
like the Do row's runs, so a stopped recording's late exit cannot be
read as the next one's. Stopping sets running to false (SIGTERM), which
lets pw-record write the WAV header; the audio ask goes out from the
process's exit, not from the click.
Recording stops itself at 59 s: the daemon refuses over 60 s by file
size, and the stop lands a little after the tick. Escape cancels a
recording before it does anything else, and closing the card or losing
the daemon cancels it too. A pw-record that ends on its own says
"recording failed".
Checked: a scratch harness saw transcribing, thinking, idle for a 2 s
recording; by hand, every case in the spec passed with no pw-record
left behind, a desktop shell reload mid-recording included.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'desktop/assistant/Card.qml')
| -rw-r--r-- | desktop/assistant/Card.qml | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/desktop/assistant/Card.qml b/desktop/assistant/Card.qml index 4c76e64..d8826fa 100644 --- a/desktop/assistant/Card.qml +++ b/desktop/assistant/Card.qml @@ -431,10 +431,30 @@ Rectangle { } } + // nf-fa-microphone, checked in Inconsolata Nerd Font. Every state, + // entry included: SUPER+Home opens the card and the mic is one click away. + Button { + id: mic + anchors { bottom: parent.bottom; left: attach.right; leftMargin: attach.visible ? 8 : 0 } + height: box.height + icon: "" + text: card.canvas.recording + ? `${Math.floor(card.canvas.micSecs / 60)}:${String(card.canvas.micSecs % 60).padStart(2, "0")}` + : "" + danger: card.canvas.recording + enabled: card.canvas.connected && (card.canvas.recording + || (!card.canvas.busy && !card.canvas.opRunning && !card.canvas.blocked)) + onClicked: { + if (card.canvas.recording) card.canvas.endRecording(true); + else card.canvas.record(); + input.forceActiveFocus(); + } + } + Rectangle { id: box anchors { - bottom: parent.bottom; left: attach.right; leftMargin: attach.visible ? 8 : 0 + bottom: parent.bottom; left: mic.right; leftMargin: 8 right: history.left; rightMargin: 8 } // Grows with the text up to six lines, then scrolls. @@ -483,6 +503,8 @@ Rectangle { visible: input.text === "" elide: Text.ElideRight text: !card.canvas.connected ? "assistant not running" + : card.canvas.recording ? "Listening… click the mic to send" + : card.canvas.state === "transcribing" ? "Transcribing…" : card.mode === "entry" ? "How can I help you?" : card.canvas.staged.length ? `Ask about ${card.canvas.staged[0].name}…` : "Message the assistant" |
