index
A modern GTK4/libadwaita system update frontend for Bluefin and Universal Blue
Finupdate provides a graphical interface for running system updates on Bluefin and Universal Blue systems. It orchestrates bootc, flatpak, brew, and distrobox directly β no uupd required. It's the first app in the Bluefin utility suite and serves as a reference implementation for future apps.
Featuresβ
- One-click system updates β orchestrates
bootc,flatpak,brew, anddistroboxvia a single pkexec elevation - Live log streaming β real-time stdout/stderr from each update module
- Elapsed timer β shows how long the update has been running
- Copy log β clipboard integration for sharing output
- Cancel support β gracefully cancel a running update
- Desktop notifications β GNotification when update completes/fails
- Reboot prompt β confirmation dialog to restart after updates
- Window close guard β prevents accidental close during active updates
- Last update time β shows when
uupdlast ran successfully - Keyboard shortcuts β Ctrl+Q (quit), Ctrl+? (shortcuts window)
- About dialog β accessible via hamburger menu
- Flatpak sandbox aware β uses
flatpak-spawn --hostwhen sandboxed - Dark mode β automatic via libadwaita (follows system preference)
- GNOME HIG compliant β symbolic icons, proper spacing, accessibility
Screenshotsβ
The app has four states:
| Idle | Updating | Complete | Error |
|---|---|---|---|
| Status page with "Check for Updates" button | Progress bar + live log + timer | Success page with reboot option | Error page with retry |
Requirementsβ
Runtimeβ
- GTK 4.16+ (GNOME 47+)
- libadwaita 1.7+
bootcorrpm-ostreeon the host systemflatpak,brew,distroboxβ optional; each module is skipped if the tool is absentuupdβ optional; if present, enables the "Automatic background updates" toggle in Preferences
Buildβ
- Rust 1.85+ (edition 2024)
- Meson 0.59+
- GTK4 and libadwaita development headers
Installingβ
Released builds are published to the TunaOS Flatpak remote for x86_64 and aarch64:
flatpak remote-add --if-not-exists tuna-os https://tunaos.org/flatpak/tuna-os.flatpakrepo
flatpak install tuna-os org.tunaos.finupdate
The remote is an OCI index backed by ghcr.io/tuna-os/finupdate; see
tuna-os/flatpak-index. Builds are
pushed by .github/workflows/publish-flatpak.yml on every push to main.
Buildingβ
Option A: Flatpak (recommended for testing)β
# One-time: install the GNOME SDK and Rust extension
flatpak install flathub org.gnome.Sdk//50 org.gnome.Platform//50
flatpak install flathub org.freedesktop.Sdk.Extension.rust-stable//25.08
flatpak install flathub org.flatpak.Builder
# Build and install locally
flatpak run org.flatpak.Builder --user --install --force-clean _flatpak \
build-aux/org.tunaos.finupdate.Devel.json
# Run
flatpak run org.tunaos.finupdate.Devel
Option B: Native Meson buildβ
Requires GTK4 and libadwaita dev packages installed:
# Fedora/Bluefin:
sudo dnf install gtk4-devel libadwaita-devel meson cargo
# Build
meson setup _build
meson compile -C _build
# Run
./_build/src/finupdate
Option C: Cargo only (dev iteration)β
If you have GTK4/libadwaita headers available (e.g., in a devcontainer):
cargo build # Debug
cargo build --release # Release
./target/release/finupdate
Developmentβ
Architectureβ
src/
βββ main.rs # Entry: logging + relm4 app launch
βββ config.rs # Build-time constants (APP_ID, VERSION)
βββ config.rs.in # Meson template β config.rs
βββ app.rs # Top-level component (window, state machine, actions)
βββ update_worker.rs # Async subprocess (tokio + mpsc streaming)
βββ ui/
βββ mod.rs # Module declarations
βββ status_view.rs # State-driven content switcher (gtk::Stack)
βββ log_view.rs # Scrollable monospace text output
State Machineβ
Idle ββ[StartUpdate]βββ Updating ββ[Complete]βββ Complete ββ[Dismiss]βββ Idle
β β
βββββββ[Error]βββ Error ββββββ[Retry/Dismiss]βββ
β
βββββββ[Cancel]βββ Idle
Component Treeβ
App (AdwApplicationWindow)
βββ AdwToolbarView
β βββ AdwHeaderBar (menu button + cancel button)
β βββ AdwToastOverlay (transient notifications)
β βββ StatusView (gtk::Stack)
β βββ "idle" β AdwStatusPage
β βββ "updating" β AdwToastOverlay
β β βββ ProgressBar + LogView + BottomBar
β βββ "complete" β AdwStatusPage
β βββ "error" β AdwStatusPage
βββ LogView (gtk::TextView in ScrolledWindow)
Key Design Decisionsβ
- relm4 over raw gtk4-rs β Component model with message passing prevents callback spaghetti
- Tokio in a separate thread β GTK owns the main thread; async I/O needs its own runtime
- mpsc channels (not callbacks) β Decouples worker from UI; enables isolated unit testing
- gtk::Stack (not show/hide) β Built-in crossfade transitions, no manual visibility management
- Imperative widget construction β Some complex widgets built in
init()when the view! macro can't express them
Flatpak Sandbox Notesβ
When running in Flatpak, the app uses flatpak-spawn --host to execute commands on the host:
- Requires
--talk-name=org.freedesktop.Flatpakin Flatpak manifest - Detection: checks for
/.flatpak-infofile - All host commands (uupd, systemctl) are automatically wrapped
Environment Variablesβ
| Variable | Effect |
|---|---|
RUST_LOG=finupdate=debug | Enable debug logging |
RUST_LOG=trace | Full trace output |
GTK_DEBUG=interactive | GTK Inspector |
Contributingβ
See CONTRIBUTING.md for development workflow and guidelines.
Reusable Patternsβ
See PATTERNS.md for documented architectural patterns that should be used by all future Bluefin utility apps.
Licenseβ
MIT β see Cargo.toml
Relatedβ
- Project Bluefin β the desktop OS this is built for
- GNOME HIG β the design guidelines we follow
- uupd β optional host daemon; if installed, its timer can be toggled from Preferences