scaffold: project structure, wire contract, roadmap and agent briefs
Lays out Velox Download Manager (IDM-class download manager for Ubuntu 26.04) as a monorepo ready for parallel lane development. No implementation code by design. - docs/: architecture, roadmap M0-M7, IDM-parity GUI spec, engine design, Firefox extension spec, risks/spikes, packaging - contracts/: wire-contract skeleton (JSON Schema + fixture templates) — the single synchronization point between lanes - docs/agents/: one brief per lane (PROTO, CORE, DAEMON, GUI, EXT, PKG/QA) with owned directories, build order and definition of done - CLAUDE.md: rules of engagement — lane ownership, layering, non-negotiables - CMake scaffolding with dev/tsan/release/ci presets Two environment findings shape the design: Firefox here is the Mozilla snap (native-messaging risk, so the extension carries a loopback-WebSocket fallback), and Wayland forbids passive clipboard monitoring (so clipboard capture is explicit-action-first). Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
# 03 — GUI specification (IDM parity)
|
||||
|
||||
Owner: lane **GUI**. Qt 6 Widgets, C++23.
|
||||
|
||||
> **Legal note, stated once:** replicating IDM's *layout, workflow and feature set* is
|
||||
> fine — UI ideas aren't protectable. Copying its *icons, artwork, sounds or exact
|
||||
> logo/branding* is not. Ship an original icon set (a Papirus/Breeze-derived set under a
|
||||
> compatible licence is the cheap route) laid out in the same positions. That gives users
|
||||
> the muscle memory without shipping someone else's assets.
|
||||
|
||||
## 1. Main window
|
||||
|
||||
```
|
||||
┌─ Velox Download Manager ─────────────────────────────────────────────── ─ □ ✕ ┐
|
||||
│ Tasks File Downloads View Help │
|
||||
├───────────────────────────────────────────────────────────────────────────────┤
|
||||
│ [+] [▶] [⏸] [⏹] [🗑] [🗑✓] [🗓] [⚙] [🌐] │
|
||||
│ Add URL Resume Pause Stop All Delete Del.Compl Scheduler Options Grabber│
|
||||
├──────────────────┬────────────────────────────────────────────────────────────┤
|
||||
│ ▼ All Downloads │ File Name │Q│ Size │ Status │Time Left│ Speed │Date│
|
||||
│ Unfinished │ ubuntu.iso │1│ 5.8GB │ 47.2 % │ 00:03:11│ 28MB/s│... │
|
||||
│ Finished │ report.pdf │ │ 2.1MB │Complete │ │ │... │
|
||||
│ ▼ Categories │ track.flac │2│ 38MB │ Queued │ │ │... │
|
||||
│ Compressed │ film.mkv │ │ 1.4GB │ Paused │ │ │... │
|
||||
│ Documents │ │
|
||||
│ Music │ │
|
||||
│ Programs │ │
|
||||
│ Video │ │
|
||||
│ ▼ Queues │ │
|
||||
│ Main Queue │ │
|
||||
│ Sync Queue │ │
|
||||
├──────────────────┴────────────────────────────────────────────────────────────┤
|
||||
│ 4 downloads, 1 active ↓ 28.4 MB/s Limit: off Queue: running ● Connected│
|
||||
└───────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Columns** (reorderable, resizable, hideable, persisted): File Name · Q · Size · Status ·
|
||||
Time Left · Transfer Rate · Last Try Date · Description. Sort on any column, ascending and
|
||||
descending, sort state persisted.
|
||||
|
||||
**Implementation:** `QTreeView` + `DownloadTableModel : QAbstractItemModel` fed by
|
||||
`event.task.progress` deltas. Never rebuild the model on an event — apply a row patch and
|
||||
emit `dataChanged` for the touched columns only. Progress bar drawn by a `QStyledItemDelegate`
|
||||
in the Status column. Coalesce progress events on a 250 ms timer; at 20 active downloads
|
||||
you get 4 repaints/sec, not 400.
|
||||
|
||||
**Row context menu:** Open · Open With · Open Folder · Move/Rename · Redownload ·
|
||||
Refresh Download Address · Resume · Pause · Delete · Add to Queue ▸ · Properties ·
|
||||
Copy Download URL.
|
||||
|
||||
**Category tree:** counts per node, drag a row onto a category to re-file it (moves the
|
||||
file on disk and updates the DB in one RPC).
|
||||
|
||||
## 2. Download File Info dialog (appears when a URL is added)
|
||||
|
||||
IDM's signature dialog. Populated from `download.probe`.
|
||||
|
||||
```
|
||||
File Name: [ ubuntu-26.04-desktop-amd64.iso ]
|
||||
Save As: [ /home/sami/Downloads/Programs/ ] [ Browse… ]
|
||||
Category: [ Programs ▾ ] Size: 5.8 GB Resume capability: Yes
|
||||
Description:[ ]
|
||||
Connections:[ 8 ▾ ] Buffer: [ 4 MiB ▾ ] ☐ Remember for this file type
|
||||
|
||||
[ Download Now ] [ Download Later ] [ Add to Queue ▾ ] [ Cancel ]
|
||||
```
|
||||
|
||||
"Download Later" = `startMode: "later"` (sits in the list as `PAUSED_MANUAL`).
|
||||
Probe runs async: show the dialog immediately with a spinner in Size/Resume, fill in when
|
||||
the reply lands, and never block the UI thread.
|
||||
|
||||
## 3. Download progress dialog
|
||||
|
||||
```
|
||||
┌ ubuntu-26.04-desktop-amd64.iso ──────────────────────────────── ─ □ ✕ ┐
|
||||
│ URL https://releases.ubuntu.com/26.04/ubuntu-26.04-…iso │
|
||||
│ Status Receiving data… File size 5.80 GB │
|
||||
│ Downloaded 2.74 GB (47.24 %) Transfer rate 28.41 MB/s │
|
||||
│ Time left 00:03:11 Resume capability Yes │
|
||||
├────────────────────────────────────────────────────────────────────────┤
|
||||
│ 1 ████████████░░░░░ Receiving 3.9 MB/s │ 5 ██████████░░░░ 3.2 MB/s │
|
||||
│ 2 ██████████░░░░░░░ Receiving 3.4 MB/s │ 6 ███████████░░░ 3.6 MB/s │
|
||||
│ 3 █████████████░░░░ Receiving 4.1 MB/s │ 7 ████████░░░░░░ 2.9 MB/s │
|
||||
│ 4 ███████████░░░░░░ Receiving 3.7 MB/s │ 8 ████████████░░ 3.5 MB/s │
|
||||
├────────────────────────────────────────────────────────────────────────┤
|
||||
│ [speed graph, 60 s rolling window, filled area, 1 Hz] │
|
||||
├────────────────────────────────────────────────────────────────────────┤
|
||||
│ ☐ Close dialog when done On completion: [ Do nothing ▾ ] │
|
||||
│ [ Pause ] [ Cancel ] [ Hide ] │
|
||||
└────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
Per-segment bars come from `TaskDetail.segments[]`. "On completion" offers: Do nothing /
|
||||
Open file / Open folder / Exit Velox / Shut down (the last one via
|
||||
`org.freedesktop.login1`, and it must confirm).
|
||||
|
||||
## 4. Options dialog — tabs
|
||||
|
||||
| Tab | Contents |
|
||||
|---|---|
|
||||
| **General** | Launch on login · minimize to tray · show floating drop target · confirm on exit · language · check for updates |
|
||||
| **File Types** | Per-category extension lists (the auto-capture table the extension mirrors) · "Automatically start downloading these types" · MIME overrides |
|
||||
| **Save To** | Default download directory · per-category folders · temp folder · **file-exists policy** (ask / rename / overwrite / resume) · "create subfolder per site" |
|
||||
| **Connection** | Connection type preset · **max connections per download (1–32)** · **write buffer per connection** · global max concurrent downloads · timeout · retries · per-host connection overrides |
|
||||
| **Downloads** | Speed limiter default · virus-scan command · post-download command hook · duplicate-URL policy · integrity check (MD5/SHA-256) |
|
||||
| **Proxy** | System / manual HTTP / HTTPS / SOCKS5 / PAC · per-host bypass list |
|
||||
| **Site Logins** | Host → username/password, stored in the **Secret Service** (gnome-keyring), never in SQLite |
|
||||
| **Sounds** | Per-event sound toggles (download complete, queue complete, error) |
|
||||
|
||||
Everything on this dialog maps 1:1 onto `settings.get`/`settings.set` keys. The settings
|
||||
key list lives in `contracts/schema/types/Settings.schema.json` — the GUI must not invent
|
||||
a key that isn't in the schema.
|
||||
|
||||
## 5. Other windows
|
||||
|
||||
- **Scheduler** — per-queue: start time, stop time, days of week, one-time vs periodic,
|
||||
"hang up/exit when done", max concurrent per queue.
|
||||
- **Site Grabber wizard** — 4 steps (project template → start URL + depth + filters →
|
||||
file-type filter → review found files, check what to download).
|
||||
- **Batch download from clipboard** — parse a pasted blob of URLs, dedupe, assign category.
|
||||
- **Batch download with wildcards** — `http://host/img{1..50}.jpg` expansion with preview.
|
||||
- **Speed limiter** — off / limit to N KB/s, with a "apply to running downloads now" button.
|
||||
- **Floating drop target** — frameless always-on-top `QWidget`, accepts dropped links,
|
||||
right-click menu, position remembered. IDM's drop box, minus the branding.
|
||||
- **Tray icon** — active count in tooltip, menu: Show · Add URL · Pause All · Resume All ·
|
||||
Speed limiter ▸ · Quit (Quit asks whether to also stop the daemon).
|
||||
|
||||
## 6. Clipboard capture
|
||||
|
||||
`QClipboard::dataChanged` → if the text is a URL whose extension is in the monitored list,
|
||||
show a toast: "Download this link? [Download] [Ignore]".
|
||||
|
||||
⚠ **Under Wayland this does not work the way it does on X11** — a Wayland client is not
|
||||
notified of clipboard changes made by other applications. This is the #2 risk in
|
||||
`docs/06-risks-and-spikes.md` and has a dedicated spike. The design must therefore treat
|
||||
clipboard monitoring as *best-effort* and ship these as the real paths:
|
||||
1. The extension's context menu ("Download with Velox") — covers the browser case, which
|
||||
is the overwhelming majority.
|
||||
2. A global shortcut (via `org.freedesktop.portal.GlobalShortcuts`) that reads the
|
||||
clipboard *on demand* — an explicit user action, which the portal does allow.
|
||||
3. "Add URL" dialog, pre-filled from the clipboard when it opens (also an explicit action).
|
||||
|
||||
## 7. Theming
|
||||
|
||||
`gui/resources/qss/idm-like.qss` plus a `dark.qss`. Follow the system light/dark preference
|
||||
via `QStyleHints::colorScheme()`. Keep every colour in one variables block at the top of
|
||||
the QSS; no hard-coded hex scattered through widget code.
|
||||
|
||||
## 8. Accessibility & i18n (M5, not optional)
|
||||
|
||||
Keyboard-reachable everything, `Qt::AccessibleName` on custom widgets, `tr()` from the
|
||||
first commit, `.ts` files under `gui/i18n/`, RTL layout verified with Arabic.
|
||||
Reference in New Issue
Block a user