Continues the build order past the Add-URL/File-Info/Progress dialog flow.
- OptionsDialog: General/Save To/Connection/Downloads/Proxy/Sounds tabs, every
control bound to a real settings.* key (contracts/schema/types/Settings.
schema.json). The spec's File Types and Site Logins tabs have no settings.*
backing (categories go through category.upsert, credentials through the
Secret Service) so they don't exist here — a tab either binds to a real key
or isn't shipped. diffChanged() sends only what actually changed, matching
settings.set's "changed[] names exactly what took effect" contract.
- SchedulerDialog: per-queue schedule (schedule.get/set) plus maxConcurrent/
onComplete (queue.upsert), Start Now/Stop. Queue.schema.json already carries
the schedule so queue.list alone seeds the window.
- SpeedLimiterDialog: the live global limiter (limiter.get/set) — a different
thing from Options' downloads.speedLimit* default. buildParams() enforces
the schema's "0 with enabled true must not be offered".
- BatchDialog: clipboard-blob and {start..end}-wildcard tabs sharing one
category/queue/start-mode footer into download.addBatch.
- GrabberWizard: 4-step QWizard (project label -> start URL/depth/filters ->
file-type filter -> review), grabber.start feeding a poll+event.grabber.
progress-driven review page, Finish = grabber.harvest for the checked files.
- TrayIcon: active-count tooltip, Show/Add URL/Pause All/Resume All/Speed
Limiter submenu/Quit. Quit only closes the GUI — there is no RPC to stop
veloxd itself, filed as a new gap in daemon-requests-m1.md. MainWindow now
also hides to tray instead of closing when general.minimizeToTray is set.
Every dialog's non-widget logic (diffChanged, buildSchedule, buildParams,
parseUrlBlob/expandWildcard/buildAddBatchParams, buildFileTypes/
buildStartParams/buildHarvestParams) is a static pure function with its own
test, same shape as FileInfoDialog::buildSpec from the previous round.
Verified end-to-end against a running mockd under ASan+UBSan: all five
surfaces render real data (settings.get values, queue.list's two seeded
queues, limiter.get, a live grabber.start/status crawl returning 3 files) with
no sanitizer reports. gui-check (non-ASan) and dev (ASan+UBSan) presets both
build the whole repo clean; all gui-labeled ctest targets pass.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NSCdCWFXBTSBBK3MzWtJiC
3.2 KiB
GUI → DAEMON requests (M1)
Filed by lane GUI, from independent verification of velox-gui against a real veloxd
(isolated HOME/XDG_RUNTIME_DIR/XDG_DATA_HOME, real tools/testserver transfer, GUI's
existing RPC client and model — no code changed for this check). Handshake, subscribe,
category.list/queue.list, the full event.task.state sequence, and batched
event.task.progress all match what DAEMON already reported. One gap, below.
TaskSummary.sizeBytes is never populated, even after complete
Repro:
download.add {"url": "http://127.0.0.1:<testserver>/throttled/file/8M", "segments": 4}
# ... wait for state: complete ...
download.get {"taskId": "<id>"}
Result's summary has no sizeBytes key at all (not null — absent) even once
downloadedBytes is 8388608 and state is complete. Same in the download.list item
and in every event.task.state / event.task.progress frame along the way.
This isn't a probe-order artifact on my end — I called download.add directly without a
prior download.probe, but the daemon has the size by the time the transfer finishes (it
wrote exactly 8388608 bytes) and download.get is documented as backing the progress
dialog with full detail, so the gap persists past the point where the daemon unambiguously
knows the answer.
Effect on the GUI: TaskSummary.sizeBytes is what DownloadTableModel uses for both
the Size column and the Status column's percentage — with it absent, Size renders — and
Status falls back to plain text ("Downloading" / "Complete") instead of the progress bar
with a percentage, for the entire life of every task. This isn't a rendering bug on this
end: ProgressDelegate and the model both do the documented right thing when size is
unknown (docs/03-gui-spec.md's screenshot shows a bar with a percentage — that needs a
byte count from somewhere). Screenshots from this run are attached to the session if useful
as a reference for what "no size" currently looks like end to end.
Not urgent — mockd always supplies sizeBytes, so this doesn't block M1 GUI work — but
worth knowing before the M1 GUI↔real-daemon integration pass, since the percentage bar is
the headline visual of the main table.
No method exists to stop veloxd itself
docs/03-gui-spec.md §5 describes the tray's Quit as asking "whether to also stop the
daemon". contracts/schema/methods/ has nothing for it — no daemon.stop/daemon.shutdown,
and Queue.onComplete's "shutdown" value is a system shutdown via
org.freedesktop.login1, a different thing entirely. This is a schema read, not something
that needed a live daemon to confirm — the method list is exhaustive and checkable
directly.
Effect on the GUI: TrayIcon's Quit is implemented as "quit the GUI only; downloads
continue under the Velox service" — accurate today, since nothing else is possible, but it
means the spec's described behaviour (offer to also stop the service) has no RPC to build
on. Not urgent for M1 — CLI/systemd already stop veloxd outside the GUI — but worth a
contracts/-only PR (new privileged UDS-only method, x-deadlineMs generous enough to
cover in-flight transfers being paused first) before that tray menu item claims to do more
than it does.