9.3 KiB
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
- 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.
- 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.
- 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.
- 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.
- 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 }](fromflatpak listmachine-readable columns).permissions <app-id>→{ summary: [human strings], raw: {...} }fromflatpak 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 verbunused-runtimeslists what--unusedwould remove, andclean-unusedremoves them — the Storage cleanup row uses these).catalog→ categories + entries fromsetup/packages/extras/*(same parser rules assetup/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./.cache), trash, flatpak-unused, dnf-cache (privileged).cleanables→[{ id, label, detail, bytes, privileged }]for: cache (clean <id>executes exactly one, refusing unknown ids; trash viagio trash --empty; cache via a guarded rm of ~/.cache/* (never follows symlinks out).scripts/panama-snapshots: retention already supported (set-retention); addset-retentionargument validation for the three horizons if not already split (hourly/daily/weekly numbers 0-50).
Services (A)
services/AppLibrary.qml(new): mergesDesktopEntries.applicationswith the flatpak metadata (id-matched via the entry's flatpak export), exposesapps: [{ entryId, name, icon, kind: flatpak|system, flatpakId, size }],permissionsFor(id)(cached),uninstall(flatpakId), catalog state (categories,entriesFor(cat),install(...)),busy/lastError, seamPANAMA_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 confirmingsetRetention'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 withsetup/lib/extras-catalogrules, 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-contractfamily 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.