142 lines
9.3 KiB
Markdown
142 lines
9.3 KiB
Markdown
# Applications, Storage & Snapshots redesign
|
||
|
||
Approved mock: `home-mocks/applications.html` (scratchpad, :8642). Spec wins over mock on
|
||
conflict. Scope: the Applications *tab* (Gaming and Screen Intelligence untouched) plus the
|
||
System category's Storage and Snapshots tabs, folded into this phase by decision.
|
||
|
||
## Goals
|
||
|
||
1. **Applications becomes an app manager**: searchable installed list (DesktopEntries +
|
||
flatpak metadata), flatpak uninstall, honest system-package rows, permission summaries,
|
||
autostart toggle per app, jump chips to the app's rules elsewhere.
|
||
2. **The panama apps catalog goes native**: category chips → entries with installed state,
|
||
installing through the same dnf/flatpak paths (polkit prompts). Same files as the CLI.
|
||
3. **Defaults modernized**: role dropdowns replace the hand-rolled accordion; a single-file-type
|
||
override ("One file type") for when a role's family is too broad.
|
||
4. **Storage**: proportional breakdown bar with honest captions; folder bars share ONE scale;
|
||
"Clean up, honestly" — itemized, sized, click-each, nothing pre-selected, nothing nags
|
||
(the anti-racket rules are contract-pinned); the duplicate container affordances merge.
|
||
5. **Snapshots**: retention becomes editable (wire the caller-less `Snapshots.setRetention`);
|
||
the file browser becomes its own card that opens regardless of source-card state (fixes the
|
||
collapsed-card bug); rollback stays absent (contract).
|
||
|
||
Non-goals: dnf package removal from Settings (honest refusal row instead), full flatpak
|
||
permission *editing* (summary + Open Flatseal when installed), per-app storage classification
|
||
beyond the flatpak sizes, portal-grant editing, snapshot space measurement (quotas honesty
|
||
stays).
|
||
|
||
## New helper: `scripts/panama-applications` (pinned verbs)
|
||
|
||
House discipline (validated inputs, JSON out, mutations return fresh state, bounded timeouts):
|
||
- `flatpaks` → `[{ id, name, size, origin }]` (from `flatpak list` machine-readable columns).
|
||
- `permissions <app-id>` → `{ summary: [human strings], raw: {...} }` from `flatpak info
|
||
--show-permissions` — curated buckets: Camera, Microphone, Full file system access, Home
|
||
folder, Network, Devices; unknown keys summarized honestly, never dropped silently.
|
||
- `uninstall <app-id>` → `flatpak uninstall --noninteractive` (app only; a second verb
|
||
`unused-runtimes` lists what `--unused` would remove, and `clean-unused` removes them —
|
||
the Storage cleanup row uses these).
|
||
- `catalog` → categories + entries from `setup/packages/extras/*` (same parser rules as
|
||
`setup/lib/extras-catalog`: `flatpak:<id> | Label`, bare dnf names, indented continuations),
|
||
each entry `{ id, label, kind: flatpak|dnf, installed }` (installed via flatpak info / rpm -q).
|
||
- `install <category> <entry-id>` → flatpak: `flatpak install --noninteractive flathub <id>`;
|
||
dnf: `pkexec dnf install -y <pkg>`. Refuses ids not present in the catalog files (no
|
||
arbitrary package installation through this surface — contract-pinned).
|
||
|
||
## Extended helpers
|
||
|
||
- `scripts/panama-default-apps`: `search-types <query>` → matching MIME types with their
|
||
current handler + candidate apps; `set-type <mime> <desktop-id>` → `xdg-mime default`
|
||
(validated against installed desktop entries). Role behavior untouched.
|
||
- `scripts/panama-disks`: `breakdown` → segments `{ home, applications, caches, system, free }`
|
||
in bytes — home = the scan targets under ~ minus caches, applications = flatpak app+runtime
|
||
sizes (user-readable sums), caches = ~/.cache, system = used − the others ("System &
|
||
everything else" caption — honest arithmetic remainder), free from the fs. `cleanables` →
|
||
`[{ id, label, detail, bytes, privileged }]` for: cache (~/.cache), trash, flatpak-unused,
|
||
dnf-cache (privileged). `clean <id>` executes exactly one, refusing unknown ids; trash via
|
||
`gio trash --empty`; cache via a guarded rm of ~/.cache/* (never follows symlinks out).
|
||
- `scripts/panama-snapshots`: retention already supported (`set-retention`); add
|
||
`set-retention` argument validation for the three horizons if not already split
|
||
(hourly/daily/weekly numbers 0-50).
|
||
|
||
## Services (A)
|
||
|
||
- **`services/AppLibrary.qml`** (new): merges `DesktopEntries.applications` with the flatpak
|
||
metadata (id-matched via the entry's flatpak export), exposes `apps: [{ entryId, name, icon,
|
||
kind: flatpak|system, flatpakId, size }]`, `permissionsFor(id)` (cached),
|
||
`uninstall(flatpakId)`, catalog state (`categories`, `entriesFor(cat)`, `install(...)`),
|
||
`busy/lastError`, seam `PANAMA_APPLICATIONS_HELPER`.
|
||
- **`services/DefaultApps.qml`**: `searchTypes(query)`, `setType(mime, desktopId)` wrappers.
|
||
- **`services/Disks.qml`**: `breakdown`, `cleanables`, `clean(id)` wrappers; cleanables
|
||
refresh after any clean.
|
||
- **`services/Snapshots.qml`**: nothing new needed beyond confirming `setRetention`'s shape
|
||
matches three-horizon editing; adjust if it takes a single string.
|
||
|
||
## UI (B)
|
||
|
||
**ApplicationsPage.qml** rebuilt: Installed applications card (search field filters name +
|
||
id; rows: letter/icon tile, name + source badge, subtitle id·size or "Installed by the system
|
||
package manager"; expanded: Permissions row (+ Open Flatseal when installed), Start with the
|
||
session (autostart toggle — creates/toggles the autostart entry for that app), "Elsewhere in
|
||
Settings" jump chips (shown only where a rule exists: Notifs.appRule customized/present →
|
||
notifications; app in AudioDevices applications → sound; PrivacyPage relevance is static —
|
||
link when the app id appears in its rules if cheaply knowable, else omit), Uninstall (flatpak,
|
||
two-stage danger) or the honest dnf refusal row with the exact command). Browse-the-catalog
|
||
card (category chips, entry rows, Install with polkit caption for dnf entries, INSTALLED
|
||
badge). Default applications card: role dropdowns via OptionPickerRow-style (candidates from
|
||
the existing role matching; keep all 10 roles + family-count details), then the "One file
|
||
type" row expanding to a search field over `searchTypes` with per-type app pickers. Autostart
|
||
card: existing rows restyled with the standardized confirm; compositor autostart row kept
|
||
read-only. The Search card stays but the hardcoded "Super+Space" is replaced by a live
|
||
`Keybinds` lookup (launcher description match, literal fallback).
|
||
|
||
**StoragePage.qml**: breakdown stack bar + legend at top (honest captions; "System &
|
||
everything else" for the remainder); Folders card bars share one scale (the disk, or the
|
||
largest — pick the DISK so it's comparable to the free-space bar, with a note); "Clean up,
|
||
honestly" card from `cleanables` (row per item: label, honest cost detail, size, Clear… with
|
||
two-stage confirm; privileged rows carry the password caption; zero-byte rows render inert
|
||
with "nothing to do"); the "Unused container images" kitty-terminal row is REMOVED (the
|
||
Containers card below already routes properly — one affordance, not two). Drive/Filesystems/
|
||
Removable/Swap cards kept.
|
||
|
||
**SnapshotsPage.qml**: per-config Keep row becomes three dropdowns (hourly/daily/weekly →
|
||
setRetention); the browser moves OUT of the volume card into its own card rendered whenever
|
||
browsing state is set (opening from a collapsed card now works — this is the bug fix);
|
||
timeline/preview/expander kept; Space card kept with its honesty.
|
||
|
||
## Search & docs (C)
|
||
|
||
New entries: Installed applications, Uninstall an application, Application permissions,
|
||
Install applications (catalog), Autostart, File associations → applications; Clean up storage,
|
||
Application caches → storage; Snapshot retention → snapshots. Docs regen only if schema
|
||
changes (none expected — verify).
|
||
|
||
## Contracts (C — write, never run)
|
||
|
||
- `applications-settings-contract`: reconcile with the rebuilt page (role labels, card
|
||
titles, AutostartAppPicker, the bun matcher extraction).
|
||
- NEW `app-library-contract`: fixture-driven (stub flatpak/rpm): catalog parser agreement
|
||
with `setup/lib/extras-catalog` rules, install refuses off-catalog ids, uninstall argv
|
||
shape, permissions summary buckets, dnf never invoked for removal anywhere in the helper.
|
||
- `disks-contract`: extend — breakdown arithmetic honesty (segments sum ≤ used, remainder
|
||
labeled), cleanup rules: every cleanable itemized with bytes, nothing auto-selected, no
|
||
cleanable executes without its id being explicitly passed, cache rm is guarded, trash via
|
||
gio. Pin the anti-racket copy stance (no urgency language).
|
||
- `snapshots-contract`: extend — setRetention wired from the page, browser renders
|
||
independent of the volume card's open state, rollback still absent.
|
||
- `default-apps-contract` family rules untouched; new needles for set-type validation.
|
||
- Backlog: Phase 10. README count line if count changes.
|
||
|
||
## Agent ownership (parallel)
|
||
|
||
- **A**: `scripts/panama-applications` (new), `scripts/panama-default-apps`,
|
||
`scripts/panama-disks`, `scripts/panama-snapshots` (only if retention args need splitting),
|
||
`services/AppLibrary.qml` (new), `services/DefaultApps.qml`, `services/Disks.qml`,
|
||
`services/Snapshots.qml`.
|
||
- **B**: `modules/settings/ApplicationsPage.qml`, `StoragePage.qml`, `SnapshotsPage.qml`,
|
||
new components + qmldir.
|
||
- **C**: `services/SettingsSearch.qml`, contracts above, backlog, README count line.
|
||
|
||
Hard rules for everyone: no live mutations (no flatpak install/uninstall, no dnf, no rm, no
|
||
gio trash, no snapper writes, no xdg-mime writes) — read-only probes and stub fixtures only;
|
||
no test runs; valid QML/Python at every save. B programs against the pinned APIs.
|