Skip to content

feat(flatpak): in-app updates through the Flatpak portal - #898

Merged
kdroidFilter merged 1 commit into
nucleus-3.0from
feat/flatpak-updates
Nov 1, 2026
Merged

kdroidFilter merged 1 commit into
nucleus-3.0from
feat/flatpak-updates

Conversation

@kdroidFilter

@kdroidFilter kdroidFilter commented Nov 1, 2026 •

Copy link
Copy Markdown
Collaborator

What

New flatpak module (nucleus.flatpak), the Flathub counterpart of MicrosoftStore.updates, over org.freedesktop.portal.Flatpak (Rust JNI bridge on zbus, Linux only, Kotlin-only Unsupported elsewhere).

Flatpak.updates.status.collect { status ->
    when (status) {
        is FlatpakUpdateStatus.Available -> Flatpak.updates.install(parent).collect { show(it) }
        is FlatpakUpdateStatus.Installed -> Flatpak.updates.restart()
        is FlatpakUpdateStatus.UpToDate -> Unit
    }
}
API Portal
status: Flow<FlatpakUpdateStatus> (Available / Installed / UpToDate) CreateUpdateMonitor + UpdateAvailable
install(parent): Flow<FlatpakUpdateProgress> UpdateMonitor.Update + Progress
restart(arguments) SingleInstanceManager.releaseForHandoff(), then Spawn with FLATPAK_SPAWN_FLAGS_LATEST_VERSION, then exit
openStorePage(parent) OpenURI appstream://<app id>

Design notes (from the portal's source)

  • No "check now": the portal polls every monitor on one timer (30 min by default), so status is a Flow, not a check().
  • Permission dialog: the first Update shows "Update ?". The answer is stored (permission table flatpak, id updates), and a refusal maps to UpdateDenied.
  • Error mapping: the portal's messages are translated, so errors are mapped by D-Bus name only. NotSupported raised while planning means NewPermissionsRequired; raised before planning, it means PortalMissing.
  • Cancellation: closing a monitor cancels its update, so cancelling the install collection interrupts it.
  • Spawn is always given fds 0–2. Without any, the portal hands the environment to flatpak run on fd 0, which rejects it (--env-fd: Cannot use reserved file descriptor 0, 1 or 2), and nothing starts after the app already quit. flatpak-spawn always passes its stdio, which is why this isn't widely known.

Lab

The new system.flatpak-updates probe (Linux) supports deep-link flags ?watch&install&restart, which run the whole update without a click.

Verification

End to end, from a local Flatpak repository with the real flatpak-portal (polled every 10 s) and the Lab as a native image:

  • Detection: 1.0.3 → 1.0.4 detected.
  • Dialog: the portal dialog was accepted by hand, and the answer was stored.
  • Install: progress went 0 → 100 % and ended with status 2.
  • Restart after a background flatpak update (1.0.5 → 1.0.6): a single instance came back on the new commit.
  • Full in-app path (1.0.6 → 1.0.7): watch → install → restart, again a single instance on the new commit.
  • Checks: :flatpak:check (19 tests, detekt, ktlint), apiCheck, :examples:lab:probes:system:check, cargo clippy with 0 warnings.

Checked by hand on Ubuntu GNOME (Lab 1.0.8, Wayland): the dialog opens attached to the Lab window, "Deny" fails install() with UpdateDenied, and openStorePage opens GNOME Software.

CI: one build step and the verify entries in build-natives.yaml, plus the 2 Linux paths in publish-maven.yaml.

New `flatpak` module, the Flathub counterpart of MicrosoftStore.updates,
over org.freedesktop.portal.Flatpak (Rust JNI bridge on zbus):

- `status`: the portal's update monitor, as Available / Installed /
  UpToDate. The portal has no "check now" (it polls every 30 min), so
  this is a Flow, not a check()
- `install`: UpdateMonitor.Update with progress; the first one shows the
  portal's "Update <app>?" dialog over the parent window
- `restart`: hands the single-instance lock over and Spawns the latest
  commit, then exits
- `openStorePage`: appstream://<app id> through the OpenURI portal

Spawn is always given fds 0-2: without any, the portal hands the
environment to `flatpak run` on fd 0, which it rejects, and nothing
starts after the app already quit.

The Lab's system.flatpak-updates probe drives it, deep-link flags
included (?watch&install&restart). Verified end to end from a local
Flatpak repository: detection, the dialog, install, restart after an
in-app and after a background update.
@kdroidFilter
kdroidFilter changed the base branch from feat/flathub-lab to nucleus-3.0 November 1, 2026 14:17
@kdroidFilter
kdroidFilter merged commit a9f10b9 into nucleus-3.0 Nov 1, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant