From bb9442a07cebe70c3492cca31f31a8270bb83134 Mon Sep 17 00:00:00 2001 From: "Danilo M." Date: Fri, 16 Oct 2026 16:52:45 +0200 Subject: fix(assistant): review of the Do row and fileops The canvas: a To .md ended any other way than its own Stop (the footer Stop, a question, a drop, a daemon restart, an older daemon refusing the command) left the card at Working forever. The footer Stop goes through stopOp(), asking and dropping end the operation first, a disconnect ends it, and an error while nothing else runs is taken as its outcome. Each fileops run gets its own Process, so a stopped run's late answer is never read as the next one's. To .md takes one PDF, as one file is written. Compress... no longer flips back when file(1) refines a kind, long errors are elided, and a desktop with no documents folder gets Documents/Assistant rather than ~/Assistant. fileops: an animated GIF to PNG or JPEG left one file per frame under names the rename never found; the first frame is taken. JPEG flattens transparency onto white. Zipping a folder holding the output folder read its own growing archive without end; only regular files outside it are added, which also skips FIFOs and dangling links. qpdf warnings no longer fail a merge. A folder's free name keeps its dots, a lone .gz or .xz is decompressed rather than refused, and a dotfile's archive is not hidden. Tools die with fileops even when it is killed outright, a killed run's leftovers are swept on the next run, a stop between fork and bookkeeping cannot miss the child, and a late stop cannot add a second answer. Error lines lose bsdtar's doubled prefix and its delayed-exit noise. Co-Authored-By: Claude Opus 5.5 --- desktop/assistant/Card.qml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'desktop/assistant/Card.qml') diff --git a/desktop/assistant/Card.qml b/desktop/assistant/Card.qml index 069d3a0..f4dc71d 100644 --- a/desktop/assistant/Card.qml +++ b/desktop/assistant/Card.qml @@ -310,7 +310,10 @@ Rectangle { // Do: local operations (Ops.js, run by fileops or the daemon's write). // Compress… swaps the group for its formats. Hidden while one runs. property bool compressing: false - Connections { target: card.canvas; function onStagedChanged() { card.compressing = false; } } + // Only a different set of files resets it: refine() re-assigns staged + // when file(1) answers, which is not a change of files. + readonly property string stagedPaths: card.canvas.staged.map(f => f.path).join("\n") + onStagedPathsChanged: card.compressing = false Group { id: dos @@ -341,6 +344,9 @@ Rectangle { Text { anchors.verticalCenter: parent.verticalCenter + // Bounded: an error can run to 300 characters. + width: Math.min(implicitWidth, card.width - 28 - status.spacing * 3 - 220) + elide: Text.ElideRight text: status.c.opRunning ? (status.c.opDaemon && status.c.opChars ? `${status.c.opLabel}… ${(status.c.opChars / 1000).toFixed(1)}k characters` @@ -501,7 +507,8 @@ Rectangle { danger: card.canvas.busy enabled: card.canvas.connected && (card.canvas.busy || !card.canvas.blocked) onClicked: { - if (card.canvas.busy) card.canvas.send({ type: "stop" }); + if (card.canvas.opRunning) card.canvas.stopOp(); + else if (card.canvas.busy) card.canvas.send({ type: "stop" }); else if (card.canvas.ask(input.text)) input.text = ""; input.forceActiveFocus(); } -- cgit v1.2.3