Files
driftwood/docs/plans/2026-02-27-feature-roadmap-design.md
lashman 5ef3789c7d Add feature roadmap design for 25 new features
Comprehensive design doc covering discovery-to-uninstall lifecycle:
- System modification tracking for clean reversible uninstalls
- Sorted by complexity from quick wins to major features
- Covers FUSE wizard, autostart, MIME types, catalog browser,
  portable mode, batch operations, and more
2026-02-27 23:24:34 +02:00

27 KiB

Driftwood Feature Roadmap - Design Document

Goal: Add 26 features to make Driftwood the definitive AppImage manager for Linux newcomers coming from Windows, covering the full lifecycle from discovery to clean uninstall.

Architecture: All features build on the existing GTK4/libadwaita/Rust stack. Every system modification (desktop files, icons, MIME associations, autostart entries) is tracked in a central system_modifications table and fully reversed on app removal. Features are ordered from simplest to most complex.

Tech Stack: Rust, gtk4-rs, libadwaita-rs, rusqlite, gio, notify crate, pkexec/polkit for privileged operations, XDG specs (Desktop Entry, Autostart, MIME Applications), AppImage feed.json catalog.


Core Architecture: System Modification Tracking

Every feature that touches system files MUST use this tracking system. No exceptions.

New Database Table

CREATE TABLE IF NOT EXISTS system_modifications (
    id              INTEGER PRIMARY KEY AUTOINCREMENT,
    appimage_id     INTEGER REFERENCES appimages(id) ON DELETE CASCADE,
    mod_type        TEXT NOT NULL,
    file_path       TEXT NOT NULL,
    previous_value  TEXT,
    created_at      TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX IF NOT EXISTS idx_system_mods_appimage
    ON system_modifications(appimage_id);

mod_type values: desktop_file, icon, autostart, mime_default, mime_entry, system_desktop, system_icon, system_binary

Core Functions (src/core/integrator.rs)

pub fn register_modification(db: &Database, appimage_id: i64, mod_type: &str, file_path: &str, previous_value: Option<&str>) -> Result<()>
pub fn undo_modification(db: &Database, mod_id: i64) -> Result<()>
pub fn undo_all_modifications(db: &Database, appimage_id: i64) -> Result<()>

Uninstall Flow

  1. Query system_modifications for the appimage_id
  2. For each modification (in reverse order):
    • desktop_file / autostart / icon: delete the file
    • mime_default: restore previous_value via xdg-mime default {previous_value} {mime_type}
    • system_*: delete via pkexec rm
  3. Run update-desktop-database ~/.local/share/applications/
  4. Run gtk-update-icon-cache ~/.local/share/icons/hicolor/ (if icons were removed)
  5. Optionally delete app data paths (with user confirmation)
  6. Delete the AppImage file
  7. Delete DB record (CASCADE handles system_modifications rows)

CLI Purge Command

driftwood purge - removes ALL system modifications for ALL managed apps, for when Driftwood itself is being removed from the system.


Feature Specifications (Sorted: Easiest to Most Complex)


F1. Auto-Set Executable Permission on Existing Files

Complexity: Trivial (15 min) Problem: Files already in scan directories skip chmod during drag-and-drop. Non-executable AppImages found during scan aren't fixed. Files: src/ui/drop_dialog.rs, src/core/discovery.rs

Changes:

  • drop_dialog.rs: In the in_scan_dir branch of register_dropped_files(), add permission check and fix:
    if !std::os::unix::fs::PermissionsExt::mode(&metadata.permissions()) & 0o111 != 0 {
        std::fs::set_permissions(&final_path, std::fs::Permissions::from_mode(0o755))?;
    }
    
  • discovery.rs: After scan finds a non-executable AppImage, auto-fix permissions and log it

F2. Move-or-Copy Option for Drag-and-Drop (+ Keep in Place)

Complexity: Easy (30 min) Problem: Always copies file, wasting disk. No option to keep in place. Files: src/ui/drop_dialog.rs

Changes:

  • Replace 3-button dialog with 4 response options:
    • "cancel" - Cancel
    • "keep-in-place" - Keep in place (register at current location, set executable, no copy)
    • "copy-only" - Copy to Applications (current "Just add" behavior)
    • "copy-and-integrate" - Copy & add to menu (current "Add to app menu", suggested/default)
  • register_dropped_files() receives a new copy_mode enum: KeepInPlace, CopyOnly, CopyAndIntegrate
  • KeepInPlace: set executable on original path, register in DB at original location, optionally integrate
  • Dialog text updated: "Where should this AppImage live?"

F3. Version Rollback

Complexity: Easy (1 hr) Problem: No way to go back if an update breaks things. Files: src/core/updater.rs, src/ui/detail_view.rs, src/core/database.rs

Changes:

  • New DB column: previous_version_path TEXT on appimages
  • In updater.rs update flow: before replacing, rename old to {path}.prev and store path in previous_version_path
  • Detail view system tab: "Rollback to previous version" button (visible only when previous_version_path is set)
  • Rollback: swap current and .prev files, update DB fields, re-run analysis
  • Cleanup: delete .prev file when user explicitly confirms or after configurable retention

F4. Source Tracking

Complexity: Easy (1 hr) Problem: Users can't tell where an AppImage was downloaded from. Files: src/ui/detail_view.rs, src/core/database.rs, src/ui/drop_dialog.rs

Changes:

  • New DB column: source_url TEXT on appimages
  • Auto-detect from update_info field (already stored): parse GitHub/GitLab URLs
  • Display "Source: github.com/obsidianmd/obsidian" on detail view overview tab
  • Drop dialog: optional "Where did you download this?" text field (pre-filled if detected)
  • Catalog installs (F26): automatically set source_url from catalog entry

F5. Launch Statistics Dashboard

Complexity: Easy (1-2 hrs) Problem: Launch data is tracked but never shown. Files: src/ui/dashboard.rs, src/core/database.rs

Changes:

  • New DB queries:
    • get_top_launched(limit: i32) -> Vec<(String, u64)> - most launched apps
    • get_launch_count_since(since: &str) -> u64 - total launches since date
    • get_recent_launches(limit: i32) -> Vec<(String, String)> - recent launch events with timestamps
  • Dashboard: new "Activity" section showing:
    • Top 5 most-launched apps with launch counts
    • "X launches this week" summary stat
    • "Last launched: AppName, 2 hours ago"

F6. Batch Operations

Complexity: Medium (2-3 hrs) Problem: Can't select multiple AppImages for bulk actions. Files: src/ui/library_view.rs, src/ui/app_card.rs, src/window.rs

Changes:

  • Library view header: "Select" toggle button
  • When active: app cards show checkboxes, bottom action bar slides up
  • Action bar buttons: "Integrate" / "Remove Integration" / "Delete" / "Export"
  • Each action confirms with count: "Integrate 5 AppImages?"
  • Delete uses the full uninstall flow (F14/system_modifications cleanup)
  • Selection state stored in a HashSet<i64> of record IDs on the LibraryView

F7. Automatic Desktop Integration on Scan

Complexity: Easy (30 min) Problem: Users forget to integrate after scanning. Files: src/window.rs, src/ui/preferences.rs

Changes:

  • GSettings key auto-integrate already exists (default false)
  • Wire it up: after scan completes in window.rs, if setting is true, iterate newly discovered apps and call integrator::integrate() for each
  • Register all created files via register_modification()
  • Preferences: add toggle in Behavior page (already may be there, verify)

F8. Autostart Manager

Complexity: Medium (2 hrs) Problem: No way to set AppImages to start at login. Spec: XDG Autostart - .desktop file in ~/.config/autostart/ Files: src/core/integrator.rs, src/ui/detail_view.rs, src/core/database.rs

Changes:

  • New DB column: autostart INTEGER NOT NULL DEFAULT 0
  • New functions in integrator.rs:
    pub fn enable_autostart(db: &Database, record: &AppImageRecord) -> Result<PathBuf>
    pub fn disable_autostart(db: &Database, record_id: i64) -> Result<()>
    
  • enable_autostart: creates ~/.config/autostart/driftwood-{id}.desktop with:
    [Desktop Entry]
    Type=Application
    Name={app_name}
    Exec={appimage_path}
    Icon={icon_path}
    X-GNOME-Autostart-enabled=true
    X-Driftwood-AppImage-ID={id}
    
  • Registers modification with mod_type autostart
  • Detail view system tab: "Start at login" switch row
  • disable_autostart: deletes the file, removes from system_modifications
  • Uninstall flow: handled by undo_all_modifications()

F9. System Notification Integration

Complexity: Medium (2 hrs) Problem: Toasts vanish, important events get missed. Files: src/core/notification.rs, src/window.rs

Changes:

  • Use gio::Application::send_notification(id, notification) for:
    • App crash on launch (high priority)
    • Updates available after background check (normal priority)
    • Security vulnerabilities found (high priority if critical/high severity)
  • Keep toasts for minor confirmations (copied, integrated, etc.)
  • Notification click opens Driftwood and navigates to relevant view
  • notification.rs already has the logic for CVE notifications - extend to use gio::Notification instead of/in addition to libnotify

F10. Storage Dashboard per App

Complexity: Medium (2 hrs) Problem: Users don't know total disk usage per app. Files: src/ui/detail_view.rs, src/core/footprint.rs, src/core/database.rs

Changes:

  • footprint.rs: new function get_total_footprint(db: &Database, record_id: i64) -> FootprintSummary
    pub struct FootprintSummary {
        pub binary_size: u64,
        pub config_size: u64,
        pub cache_size: u64,
        pub data_size: u64,
        pub state_size: u64,
        pub total_size: u64,
    }
    
  • Detail view storage tab: visual breakdown with labeled size bars
  • Each category shows path and size: "Config (~/.config/MyApp) - 12 MB"
  • "Clean cache" button per category (deletes cache paths only)
  • Library list view: optional "Total size" column

F11. Background Update Checks

Complexity: Medium (2-3 hrs) Problem: No automatic update awareness. Files: src/window.rs, src/ui/dashboard.rs, src/ui/library_view.rs, GSettings schema

Changes:

  • New GSettings key: update-check-interval-hours type i, default 24, range 1-168
  • New GSettings key: last-update-check type s, default ''
  • On startup: if auto-check-updates is true and enough time has passed, spawn background check
  • Background check: iterate all apps with update_info, call check_appimage_for_update() per app
  • Results: update update_available column in DB, send gio::Notification if updates found
  • Dashboard: show "X updates available" with timestamp "Last checked: 2h ago"
  • Library view: badge on apps with updates
  • Preferences: toggle + interval dropdown

F12. One-Click Update All

Complexity: Medium (3-4 hrs) Problem: Can only update one app at a time. Files: src/ui/dashboard.rs, new src/ui/batch_update_dialog.rs, src/core/updater.rs

Changes:

  • Dashboard: "Update All (N)" button when updates are available
  • Opens batch update dialog showing list of apps to update with checkboxes
  • Progress: per-app progress bar, overall progress bar
  • Each update: download new version, save old as .prev (F3 rollback), replace, re-analyze
  • On completion: summary toast "Updated 5 apps successfully, 1 failed"
  • Failed updates: show error per app, keep old version
  • Cancel: stops remaining updates, already-updated apps stay updated

F13. Full Uninstall with Data Cleanup

Complexity: Medium (3 hrs) Problem: Deleting AppImage leaves config/cache/data behind. Files: src/ui/detail_view.rs, new confirmation dialog logic, src/core/footprint.rs

Changes:

  • Delete button in detail view triggers new uninstall flow:
    1. Show dialog with FootprintSummary (from F10):
      • "Delete MyApp?" with breakdown:
      • AppImage file (245 MB)
      • Configuration (~/.config/MyApp) - 12 MB
      • Cache (~/.cache/MyApp) - 89 MB
      • Data (~/.local/share/MyApp) - 1.2 GB
      • Total: 1.5 GB will be freed
    2. All checked by default, user can uncheck to keep data
    3. On confirm:
      • Call undo_all_modifications() (removes .desktop, icons, autostart, MIME defaults)
      • Delete selected data paths
      • Delete the AppImage file
      • Remove DB record
  • Batch delete (F6) uses same flow with aggregated summary

F14. Theme/Icon Preview in Drop Dialog

Complexity: Medium (2 hrs) Problem: Users don't see what the app looks like before integrating. Files: src/ui/drop_dialog.rs, src/core/inspector.rs

Changes:

  • New function in inspector: extract_icon_fast(path: &Path) -> Option<PathBuf>
    • Runs unsquashfs -l to find icon file, then extracts just that one file
    • Much faster than full inspection
  • Drop dialog: after registration, show preview card:
    • App icon (from fast extraction)
    • App name (from filename initially, updated after full analysis)
    • "This is how it will appear in your app menu"
  • If icon extraction fails, show default AppImage icon

F15. FUSE Fix Wizard

Complexity: Significant (4-5 hrs) Problem: #1 support issue - FUSE not installed, AppImages won't run. Files: src/core/fuse.rs, new src/ui/fuse_wizard.rs, src/ui/dashboard.rs, new data/app.driftwood.Driftwood.policy

Changes:

  • New distro detection in fuse.rs:
    pub struct DistroInfo {
        pub id: String,         // "ubuntu", "fedora", "arch", etc.
        pub id_like: Vec<String>,
        pub version_id: String,
    }
    pub fn detect_distro() -> Option<DistroInfo>  // parses /etc/os-release
    pub fn get_fuse_install_command(distro: &DistroInfo) -> Option<String>
    
  • Install commands by distro family:
    • Debian/Ubuntu: apt install -y libfuse2t64 (24.04+) or apt install -y libfuse2 (older)
    • Fedora/RHEL: dnf install -y fuse-libs
    • Arch/Manjaro: pacman -S --noconfirm fuse2
    • openSUSE: zypper install -y libfuse2
  • Polkit policy file (data/app.driftwood.Driftwood.policy):
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE policyconfig PUBLIC
     "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
     "https://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
    <policyconfig>
      <action id="app.driftwood.Driftwood.install-fuse">
        <description>Install FUSE library for AppImage support</description>
        <message>Authentication is required to install the FUSE library</message>
        <defaults>
          <allow_any>auth_admin</allow_any>
          <allow_inactive>auth_admin</allow_inactive>
          <allow_active>auth_admin</allow_active>
        </defaults>
      </action>
    </policyconfig>
    
  • Wizard dialog (NavigationPage-style multi-step):
    1. "FUSE is not installed" - explanation of what FUSE is and why it's needed
    2. "We detected {distro}. Install with: {command}" - shows exact command
    3. "Install now" button runs pkexec sh -c "{command}" and shows output
    4. Re-check: calls detect_system_fuse() and shows success/failure
  • Dashboard: yellow banner when FUSE is missing with "Fix now" button

F16. File Type Association Manager

Complexity: Significant (4 hrs) Problem: AppImages don't register MIME types, so files don't open with them. Spec: XDG MIME Applications - ~/.local/share/applications/mimeapps.list Files: src/core/integrator.rs, src/ui/detail_view.rs

Changes:

  • inspector.rs already extracts desktop entry content including MimeType= field
  • New function: parse_mime_types(desktop_entry: &str) -> Vec<String> - extracts MimeType= values
  • When integrating: include MimeType= in generated .desktop file
  • Detail view overview tab: "Supported file types" section listing MIME types
  • Per-type toggle: "Set as default for .png files"
  • Setting default:
    1. Query current default: xdg-mime query default {mime_type}
    2. Store in system_modifications with previous_value = current default
    3. Set new: xdg-mime default driftwood-{id}.desktop {mime_type}
  • Removing: restore previous default from previous_value
  • Uninstall: handled by undo_all_modifications()

F17. Taskbar/Panel Icon Fix (StartupWMClass)

Complexity: Significant (3 hrs) Problem: Running AppImages show wrong/generic icon in taskbar. Files: src/core/integrator.rs, src/core/wayland.rs, src/ui/detail_view.rs

Changes:

  • During inspection: extract StartupWMClass= from embedded .desktop entry
  • Store in new DB column: startup_wm_class TEXT
  • When generating .desktop file for integration, include StartupWMClass if available
  • After launch + Wayland analysis: read /proc/{pid}/environ for GDK_BACKEND, check window list via xdotool or xprop for WM_CLASS
  • If WM_CLASS doesn't match StartupWMClass: log warning, offer to patch .desktop file
  • Detail view system tab: show detected WM_CLASS, allow manual override

F18. Download Verification Helper

Complexity: Significant (4 hrs) Problem: No way to verify AppImage authenticity. Files: New src/core/verification.rs, src/ui/detail_view.rs, src/ui/drop_dialog.rs

Changes:

  • AppImage signature spec: GPG signature embedded at offset stored in ELF section
  • New module verification.rs:
    pub enum VerificationStatus {
        SignedValid { signer: String },
        SignedInvalid { reason: String },
        Unsigned,
        ChecksumMatch,
        ChecksumMismatch,
        NotChecked,
    }
    pub fn check_embedded_signature(path: &Path) -> VerificationStatus
    pub fn verify_sha256(path: &Path, expected: &str) -> VerificationStatus
    
  • check_embedded_signature: runs unsquashfs -l to check for .sha256 or signature files, or uses the AppImage --appimage-signature flag
  • Drop dialog: after adding, show verification badge
  • Detail view: "Verification: Signed by ..." or "Unsigned - verify manually"
  • Manual verification: paste SHA256 hash, compare with computed hash
  • New DB column: verification_status TEXT on appimages

F19. First-Run Permission Summary

Complexity: Medium (3 hrs) Problem: Users don't know what an AppImage can access before running it. Files: New src/ui/permission_dialog.rs, src/ui/detail_view.rs

Changes:

  • Before first launch of any AppImage (check launch_events count = 0):
    1. Show permission dialog:
      • "MyApp will run with full access to your files and system"
      • Icon + app name
      • If has_firejail(): offer sandbox options
        • "Run without restrictions" (default for now)
        • "Run in Firejail sandbox (recommended)"
      • "Don't show this again" checkbox (stored per-app in DB)
    2. If user chooses Firejail: set sandbox_mode = 'firejail' in DB
  • New DB column: first_run_prompted INTEGER NOT NULL DEFAULT 0
  • Skip dialog if first_run_prompted = 1
  • Preferences: global toggle to disable first-run prompts

F20. Default App Selector

Complexity: Medium (3 hrs) Problem: Can't set AppImage as default browser, mail client, etc. Files: src/ui/detail_view.rs, src/core/integrator.rs

Changes:

  • Detect app capabilities from categories:
    • WebBrowser -> can be default web browser
    • Email -> can be default email client
    • FileManager -> can be default file manager
    • TerminalEmulator -> can be default terminal
  • Detail view overview tab: "Set as default" section (only shown for applicable categories)
  • Setting defaults:
    • Browser: xdg-settings set default-web-browser driftwood-{id}.desktop
    • Email: xdg-mime default driftwood-{id}.desktop x-scheme-handler/mailto
    • File manager: xdg-mime default driftwood-{id}.desktop inode/directory
  • Before setting: query current default, store in system_modifications with previous_value
  • Uninstall: restore previous defaults via undo_all_modifications()
  • Requirements: app must be integrated first (needs .desktop file)

F21. Multi-User / System-Wide Install

Complexity: Significant (4 hrs) Problem: Can't install for all users on a shared computer. Files: src/core/integrator.rs, src/ui/detail_view.rs, polkit policy

Changes:

  • Reuses polkit policy from F15 (add new action app.driftwood.Driftwood.system-install)
  • "Install system-wide" option in detail view (requires app to be integrated first)
  • Flow:
    1. pkexec cp {appimage} /opt/driftwood-apps/{filename}
    2. pkexec chmod 755 /opt/driftwood-apps/{filename}
    3. Generate system .desktop in /usr/share/applications/driftwood-{id}.desktop
    4. pkexec cp {desktop_file} /usr/share/applications/
    5. Copy icon to /usr/share/icons/hicolor/ via pkexec
    6. pkexec update-desktop-database /usr/share/applications/
  • Register all paths as system_desktop, system_icon, system_binary in system_modifications
  • Uninstall system-wide: pkexec rm for each tracked path
  • DB flag: system_wide INTEGER NOT NULL DEFAULT 0

F22. CLI Enhancements

Complexity: Medium (3 hrs) Problem: Missing install-from-URL and update-all commands. Files: src/cli.rs

New commands:

  • driftwood install <url> - Download from URL, validate, move to ~/Applications, set executable, register, optionally integrate
  • driftwood update --all - Check all apps, download and apply available updates
  • driftwood autostart <path> --enable/--disable - Toggle autostart for an AppImage
  • driftwood purge - Remove ALL system modifications for all managed apps (for Driftwood removal)
  • driftwood verify <path> - Check embedded signature or compare SHA256

F23. Portable Mode / USB Drive Support

Complexity: Major (6-8 hrs) Problem: Can't manage AppImages on removable media. Files: New src/core/portable.rs, src/ui/library_view.rs, src/window.rs, src/core/database.rs

Changes:

  • New GSettings key: watch-removable-media type b, default false
  • portable.rs:
    pub fn detect_removable_mounts() -> Vec<MountInfo>
    pub fn scan_mount_for_appimages(mount: &MountInfo) -> Vec<DiscoveredAppImage>
    pub fn is_path_on_removable(path: &Path) -> bool
    
  • Detection: parse /proc/mounts for removable media (type vfat, exfat, ntfs on /media/ or /run/media/)
  • Alternative: use gio::VolumeMonitor to watch for mount/unmount events
  • DB changes:
    • New column: is_portable INTEGER DEFAULT 0
    • New column: mount_point TEXT
  • Library view: "Portable" filter/section showing apps on removable media
  • When drive unmounts: grey out those apps, mark as unavailable
  • When drive mounts: re-scan and refresh
  • Portable apps skip the "copy to ~/Applications" step - they stay on the drive
  • Integration: .desktop files use the full path (may break when unmounted - show warning)

F24. "Similar to..." Recommendations

Complexity: Medium (3 hrs, depends on F26) Problem: No app discovery within the tool. Files: src/ui/detail_view.rs, src/core/database.rs

Changes:

  • Requires catalog data from F26 (catalog_apps table populated)
  • New DB query: find_similar_apps(categories: &[String], exclude_id: i64, limit: i32) -> Vec<CatalogApp>
  • Matches on shared categories, weighted by specificity
  • Detail view overview tab: "You might also like" section at the bottom
  • Shows up to 5 catalog apps with icon, name, one-line description
  • Click opens catalog detail page (F26)
  • Falls back to nothing if catalog is empty

F25. AppImageHub In-App Catalog Browser

Complexity: Major (8-12 hrs) Problem: No way to discover and install new AppImages from within the app. Data source: https://appimage.github.io/feed.json (~1500 apps) Files: New src/ui/catalog_view.rs, new src/ui/catalog_detail.rs, src/core/database.rs, src/window.rs

Architecture:

Data Layer

  • Fetch feed.json and parse into catalog_apps table (already exists in DB schema)
  • Store in catalog_sources as source record
  • Fields mapped from feed.json:
    • name -> name
    • description -> description
    • categories -> categories (joined with ;)
    • authors[0].name -> author
    • license -> license
    • links (type=GitHub) -> repository_url
    • links (type=Download) -> download_url
    • icons[0] -> icon_url (prefix with https://appimage.github.io/database/)
    • screenshots -> screenshots (JSON array)
  • Refresh: on first open, then daily if enabled
  • New GSettings key: catalog-last-refreshed type s, default ''

Catalog Browse View (NavigationPage)

  • Header: search bar + category filter chips
  • Categories from feed: AudioVideo, Development, Education, Game, Graphics, Network, Office, Science, System, Utility
  • Grid of catalog app cards (reuse app_card pattern):
    • Icon (fetched from URL, cached locally)
    • App name
    • Short description (first line)
    • Category badge
  • Pagination: load 50 at a time, "Load more" button
  • Search: filters by name and description (client-side, data is local)

Catalog App Detail (NavigationPage pushed on click)

  • App icon (large)
  • Name, author, license
  • Full description
  • Screenshots carousel (if available)
  • "Install" button (suggested style)
  • Source link (opens GitHub/website in browser)

Install Flow

  1. User clicks "Install"
  2. Resolve download URL:
    • If download_url points to GitHub releases page: fetch latest release via GitHub API (https://api.github.com/repos/{owner}/{repo}/releases/latest), find .AppImage asset
    • If direct link: use as-is
  3. Download with progress bar (reqwest or gio file download)
  4. Validate: check AppImage magic bytes
  5. Move to ~/Applications, set executable
  6. Register in DB with source_url set
  7. Run full analysis pipeline
  8. Optionally integrate (based on auto-integrate setting)
  9. Navigate to the app's detail view in library

Navigation

  • Main sidebar/navigation: add "Catalog" entry alongside Dashboard and Library
  • Or: floating action button on library view "Browse catalog"

New GSettings Keys Summary

Key Type Default Range/Choices Feature
update-check-interval-hours i 24 1-168 F11
last-update-check s '' - F11
catalog-last-refreshed s '' - F25
watch-removable-media b false - F23
show-first-run-prompt b true - F19

New Database Columns Summary

Table Column Type Default Feature
appimages previous_version_path TEXT NULL F3
appimages source_url TEXT NULL F4
appimages autostart INTEGER 0 F8
appimages startup_wm_class TEXT NULL F17
appimages verification_status TEXT NULL F18
appimages first_run_prompted INTEGER 0 F19
appimages system_wide INTEGER 0 F21
appimages is_portable INTEGER 0 F23
appimages mount_point TEXT NULL F23

New Files Summary

File Feature Purpose
src/ui/fuse_wizard.rs F15 FUSE installation wizard dialog
src/ui/batch_update_dialog.rs F12 Batch update progress dialog
src/ui/permission_dialog.rs F19 First-run permission summary
src/ui/catalog_view.rs F25 Catalog browse/search page
src/ui/catalog_detail.rs F25 Catalog app detail page
src/core/verification.rs F18 Signature and checksum verification
src/core/portable.rs F23 Removable media detection and management
data/app.driftwood.Driftwood.policy F15, F21 Polkit policy for privileged operations

Implementation Order

The features are numbered F1-F25 in order of complexity. Implement sequentially - some later features depend on earlier ones:

  • F25 (Catalog) depends on nothing but is largest
  • F24 (Similar to) depends on F25
  • F12 (Update All) depends on F11 (Background checks)
  • F13 (Full Uninstall) depends on system_modifications table (core architecture)
  • F20 (Default App) depends on F16 (MIME associations)

Critical path: Core architecture (system_modifications) -> F1-F7 quick wins -> F8-F14 medium features -> F15-F22 significant features -> F23-F25 major features