Skip to content

auto-update on macOS steals focus from other apps on restart #3529

@louis030195

Description

@louis030195

Repro

  1. Enable auto-update (settings → general → autoUpdate: true).
  2. Be working in another app (browser, editor, etc.) when a new version is published.
  3. Screenpipe silently downloads the update, fires a macOS notification, then ~30s later the Screenpipe window jumps to the foreground, interrupting whatever you were doing.

Root cause

The auto-update flow ends with an unconditional app.restart(), and the freshly-spawned process re-activates the dock icon — which on macOS pulls the window in front of whatever app the user is currently focused on.

Sequence:

  1. Background check finds an update and downloads it.
  2. Notification fires: "v{x} downloaded — restarting now"apps/screenpipe-app-tauri/src-tauri/src/updates.rs:498-514.
  3. update-restarting event emitted, sleep 30s, then self.app.restart()apps/screenpipe-app-tauri/src-tauri/src/updates.rs:516-535.
  4. New process boots and runs set_activation_policy(Regular) unconditionally — apps/screenpipe-app-tauri/src-tauri/src/main.rs:1964-1965apps/screenpipe-app-tauri/src-tauri/src/window/panel.rs:91.
  5. Switching AccessoryRegular re-registers the dock icon and Tauri re-shows the main webview, stealing focus.

There is no "is the user focused elsewhere?" check before calling app.restart(), and no set_focus() / requestUserAttention() elsewhere in the update code — the focus-steal is purely a side effect of restarting the process while the user is in another app.

Secondary bug

After the restart, the "Restart to update v{x}" banner often still shows even though the new process is already on v{x}. The useUpdateBanner zustand store appears to persist across restarts and isn't cleared after the install completes (apps/screenpipe-app-tauri/components/update-banner.tsx).

Proposed fixes

  • (a) Defer app.restart() until Screenpipe is frontmost, or until the user explicitly quits — fall back to "restart on next launch" if they never come back to the app.
  • (b) Drop the blind 30s timer in favor of Tauri's "install on next launch" updater flow.
  • (c) Clear the persisted update-banner state once app.restart() is about to fire (or on setup() if package_info().version already matches the pending version).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions