Skip to content

User Prompts

Gil Burns edited this page Jun 7, 2026 · 2 revisions

User Prompts

Third Party Patcher uses swiftDialog for all user-facing UI during patching. There are five distinct prompt moments across the lifecycle of a patch cycle, each serving a different purpose.


Prerequisites

swiftDialog must be installed at /usr/local/bin/dialog. Use patcher ensure to install or update it:

sudo /usr/local/bin/tpp/patcher ensure swiftdialog

If swiftDialog is not installed and SwiftDialogEnabled is true, the apply phase falls back to silent behavior: blocking processes are handled per BlockingProcessAction without any user interaction.

patcher always runs as root. swiftDialog always runs as the console user, launched via launchctl asuser <uid> so dialogs appear in the user's session.


Enabling and Disabling Prompts

Key Default Description
SwiftDialogEnabled true Show interactive apply dialogs. Set to false for fully silent operation.
ShowScanCheckProgressDialog true Show the mini progress window when scan/check/stage phases are triggered from PatcherMenu.

When SwiftDialogEnabled is false, all apply dialog moments are skipped. Blocking processes are handled per BlockingProcessAction without any user interaction.


Progress Windows (Scan, Check, Stage)

When scan, check, or stage phases are triggered from PatcherMenu (or via the --user-initiated flag from the command line), a small mini progress window appears to let the user know the operation is running.

These windows are non-interactive — the user cannot cancel or defer from them. They auto-close when the phase completes.

Scan progress window

Scan progress window

  • Appears in the position set by DialogScreenProgressPosition (default: bottom-right corner).
  • Shows the title, a message like "Scanning N applications for available updates…", a progress bar, and the current label being scanned.
  • The icon updates per-label to show the app currently being scanned (the app's .app icon or a synced metadata icon if available). The overlay icon is restored when the loop finishes.
  • When complete: shows a summary ("N updates available to download." or "No updates available."), holds for 5 seconds, then auto-closes.

Check progress window

  • Same layout and position as the scan window.
  • Shows "Checking N applications for available updates…" and updates the current app icon as each app is checked.
  • Completion summary matches scan.

Stage progress window

  • Same layout, same position.
  • Shows "Downloading N updates…".
  • While each file downloads, the progress bar switches to indeterminate (spinning) mode. When the download completes, it advances to a determinate bar.
  • Completion summary shows how many updates are staged and ready.

Stage progress window — downloading


Dialog 1 — Deferral Prompt

Before any installations begin, the user is shown a prompt telling them that updates are ready. This is the primary opportunity to defer. The dialog is blocking — patcher waits for the user's choice (or the countdown timer) before proceeding.

Deferral prompt

What it shows

  • Title: AppTitle preference.
  • Message: "You have N software updates that are ready to be installed." Additional lines appear based on context:
    • If updates have been pending for more than 0 days: "These updates have been pending for N day(s)."
    • If the hard deadline has been reached: "Installation is required — the maximum deferral deadline has been reached."
  • Info box (side panel): Shows the current deferral status — days pending and how many times deferred so far.
  • Countdown timer: DeferralCountdownSeconds (default: 300 s). When it reaches zero, DeferralAutomaticAction fires.
  • Defer button (left): Visible unless the hard deadline has been reached. If DeferralTimerMenu is set, a "Defer for" dropdown appears with the configured time options. If DeferralTimerMenu is empty, the button label shows the default duration, e.g. "Defer (4 hours)".
  • Continue button (right): Proceeds immediately to the progress dialog.

Deferral prompt — hard deadline reached

Deferral time options

The "Defer for" dropdown is populated from DeferralTimerMenu. Each value is a number of minutes, formatted for display (e.g. 5 → "5 minutes", 60 → "1 hour", 1440 → "1 day"). The selected value from DeferralTimerDefault is pre-selected.

Key Default Description
DeferralTimerMenu "5,30,60,120,240,480,1440" Comma-separated list of deferral durations (in minutes) shown in the dropdown
DeferralTimerDefault 240 Pre-selected duration in the dropdown, and the duration used when no menu is shown
DeferralCountdownSeconds 300 Seconds before the countdown timer fires the automatic action
DeferralAutomaticAction "defer" Action when the countdown expires: "defer" auto-defers for DeferralTimerDefault minutes; "continue" proceeds

Hard deadline behavior

When DeadlineDaysHard days have elapsed since updates were first staged, the Defer button and dropdown are removed. The message states that installation is required. The user can only click Continue (or wait for the countdown), and the update proceeds regardless.

Aggressive patch day deferral

When AggressivePatchDayDeferral is true (the default), the available deferral options in the dropdown are progressively capped as the deadline approaches. On the final patch day, long deferral options are removed and eventually the Defer button itself disappears — leaving only Continue. See Deferral and Deadlines for the full capping schedule.

User-initiated (PatcherMenu) behavior

When apply is triggered directly from PatcherMenu, patcher receives the --user-initiated flag and skips the deferral prompt entirely, proceeding straight to the progress dialog. The intent is that if the user is explicitly asking to install updates now, offering to defer is unnecessary.


Dialog 2 — Apply Progress Dialog

Once the user clicks Continue (or the countdown auto-proceeds), the full-size progress dialog launches. patcher does not wait for it to be ready — it begins installing and drives the dialog through a command file that swiftDialog watches.

Apply progress dialog — in progress

What it shows

  • Title: AppTitle.

  • Info box (side panel): App title, update count, and "These updates are being applied".

  • List: One row per app being updated. Each row shows the app icon, app name, and a status indicator:

    Status Icon Text
    Not started yet Pending "Waiting"
    Currently installing Spinner "Installing…"
    Successfully installed Checkmark (green) "→ 1.2.3" (new version)
    Installation failed X (red) "Failed"
    Skipped (blocking process) Warning "Skipped" or reason
  • Progress bar: advances as each app completes.

  • Progress text: "[current/total] Installing AppName…"

  • Updating… button (disabled while installs are running) → Done button when complete.

  • ? help button: opens the support info panel (see below).

Completion state

When all apps have finished, the dialog transitions to a completion summary:

  • Info box updates to: "All waiting updates have been applied."
  • Progress bar fills completely.
  • Progress text shows the summary: "N update(s) applied successfully" or "N updated · M skipped · P failed".
  • The Done button is enabled and brought to focus.

Apply progress dialog — complete

Auto-dismiss

When UnattendedExit is true (the default), patcher sends a quit: command to swiftDialog after UnattendedExitSeconds seconds (default: 60) if the user has not clicked Done. The dialog closes automatically.

Set UnattendedExit to false to require the user to explicitly click Done before the dialog closes.

Key Default Description
UnattendedExit true Auto-close the progress dialog after completion
UnattendedExitSeconds 60 Seconds to wait before auto-closing

Help panel

Clicking the ? button opens a help panel in the progress dialog. It shows:

  • Support team name, phone, email, and website (from the SupportTeam* preferences).
  • Computer serial number.
  • The timestamp when the apply phase started.
  • Version information: Third Party Patcher, Installomator, swiftDialog, macOS.

Apply progress dialog — help panel


Dialog 3 — Blocking Process Prompt

During the apply phase, patcher checks each label's blockingProcesses list before installing. If a blocking process is found to be running, BlockingProcessAction determines what happens next.

ignore — install immediately

The blocking process check is skipped entirely. The installer runs even if the blocking app is open. Use this when the installer handles open files gracefully.

kill — force-quit silently

The blocking process is terminated with pkill -x without any user notification. Installation proceeds immediately. The app is not relaunched afterward.

defer — skip silently

The label is skipped this cycle. No dialog is shown. The update will be retried on the next apply cycle. This is counted as a deferral for deadline purposes.

notify — notification banner, then skip

A brief notification banner is shown:

  • Title: "Update Pending: AppName"
  • Message: "[AppName] needs to be quit to apply an update. Please close it when convenient."
  • Icon: caution, with the blocking app's icon as overlay.

The banner auto-dismisses. The label is then skipped for this cycle. Useful for a softer touch than prompt when the update is not yet urgent.

Blocking process notify banner

prompt (default) — interactive dialog

A separate swiftDialog window appears, pausing the progress dialog while waiting for the user's choice.

Blocking process prompt

What it shows:

  • Title: "[AppName] Update Paused"
  • Message: "[AppName] needs to be updated, but [processName] is currently running. Please save your work and quit [processName] before the timer expires, or click Skip Update to postpone this update."
  • Icon: caution, with the blocking app's icon as overlay.
  • Countdown timer: BlockingProcessCountdownSeconds (default: 120 s).
  • Skip Update button (left): Skips this label for this cycle.
  • Quit [processName] button (right): Force-quits the blocking process and proceeds with the install.

Outcomes:

Exit condition What happens
User clicks "Skip Update" Label skipped; counted as a deferral
Timer expires (exit 4) Blocking process is force-quit; installation proceeds
User clicks "Quit [App]" Blocking process is force-quit; installation proceeds; app is relaunched after install
Key Default Description
BlockingProcessAction "prompt" One of: ignore, kill, defer, notify, prompt
BlockingProcessCountdownSeconds 120 Seconds shown on the blocking process prompt countdown

Silent Apply (applyQuiet)

applyQuiet is a separate subcommand used by the scheduler when QuietApplyEnabled is true. It runs with no dialogs of any kind. Labels whose blocking process is currently running are silently skipped — they are not counted as deferrals and will appear in the next interactive apply pass. This lets patcher opportunistically install updates in the background between scheduled interactive apply cycles.


Focus / DND: No Prompt Shown

When FocusCheckEnabled is true (the default) and Focus mode, Do Not Disturb, or a display assertion (e.g. screen sharing, presentation software) is active, patcher skips all dialog moments and defers silently for DeferralTimerFocus minutes. Focus deferrals do not increment the deferral counter and do not advance the deadline.

The Focus check is disabled after DeadlineDaysFocus days of pending updates (default: 4 days), so a Focus deferral cannot be used indefinitely to avoid a hard deadline.

Key Default Description
FocusCheckEnabled true Respect Focus / DND / display assertions
DeferralTimerFocus 60 Minutes to defer automatically when Focus is detected

See Deferral and Deadlines for when Focus deferrals are disabled.


Visual Customization

All dialogs share a consistent appearance controlled by these preferences:

Key Default Description
AppTitle "Third Party Patcher" Title shown in all dialog windows
DialogIcon (empty) Path to a custom .png or .icns, or an SF=<symbolName> string. When empty, patcher generates a hardware-accurate computer icon with a red arrow badge and caches it at Config/dialog_icon.png.
UseOverlayIcon true Show a small MDM or management agent badge on the dialog icon
OverlayIcon (empty) Path to the overlay image. When empty, auto-detected from known MDM agent paths (Jamf, Intune, Company Portal, Kandji, Workspace ONE, Addigy, FileWave, App Store)
DialogOnTop true Keep dialog windows above all other windows
DialogScreenPosition "center" Position of the deferral and progress dialogs. Options: center, top, bottom, topleft, topright, bottomleft, bottomright
DialogScreenProgressPosition "bottomright" Position of the mini scan/check/stage progress windows

Auto-generated dialog icon

When DialogIcon is not set, patcher composes a 512×512 PNG from the system's hardware-accurate computer image (NSImage.computerName — renders the correct Mac model: MacBook, iMac, Mac mini, Mac Pro, etc.) with a red download arrow overlaid at the top center. The result is cached at /Library/Application Support/Patcher/Config/dialog_icon.png after the first run. To force a refresh, delete that file.


Support Team Branding

Contact information appears in the ? help panel of the apply progress dialog so users know who to contact if they have questions.

Key Default Description
SupportTeamName "IT Support Team" Team name heading
SupportTeamEmail "support@company.com" Email address (shown as plain text)
SupportTeamPhone "None" Phone number; omitted if set to "None"
SupportTeamWebsite "None" Website URL; omitted if set to "None" or empty

Progress dialog help panel showing support contact

Clone this wiki locally