Skip to content

Reset the plugin-update notifiers live after updates run - #408

Merged
epeicher merged 1 commit into
trunkfrom
fix/296-update-notifier-stale
Jul 24, 2026
Merged

Reset the plugin-update notifiers live after updates run#408
epeicher merged 1 commit into
trunkfrom
fix/296-update-notifier-stale

Conversation

@epeicher

@epeicher epeicher commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

Closes #296

What it does

After updating plugins (or themes) inside the desktop shell, the two update notifiers now reset live, with no hard refresh:

Both flows are covered: per-plugin "update now" links on plugins.php (Core's shiny AJAX updater) and the bulk "Update Plugins" run on the Updates screen. When the count reaches zero the admin-bar node disappears, exactly as a fresh server render would; if updates appear later on a shell that booted clean, the node is re-created in Core's slot order.

Rationale

Two gaps compounded:

  1. The chromeless bridge emits a fresh menu payload only on a full page load of plugins.php / themes.php / etc. Shiny updates run over AJAX with no navigation, so the shell never learned the counts changed — the dock badge went stale.
  2. Nothing ever repainted #wp-admin-bar-updates: it is static server HTML rendered at shell boot, so even a fresh payload could not fix it.

A third, related gap: the bulk updater nests a progress iframe (update-core.phpupdate.php?action=update-selected) whose iframe_footer() fires admin_footer after the upgrades ran — a perfectly fresh payload — but posted it to window.parent, i.e. the intermediate update-core.php page, which has no listener.

Implementation

Follows the existing live-refresh pattern (payload key + shell applier), no new mechanism:

  • includes/render/chromeless-bridge.php — a shiny-update watcher binds the jQuery events updates.js triggers on document (wp-plugin-update-success / -error, wp-plugin-delete-success, theme counterparts) and posts a payload-less desktop-mode-updates-changed nudge once wp.updates.queue is drained. Error events are included deliberately: wp_ajax_update_plugin calls wp_update_plugins() up front, which can mutate the transient even when the upgrade fails. The payload/signature emit now targets the top window instead of the immediate parent — identical for normal window iframes, and it lets the nested bulk-updater payload reach the shell.
  • includes/core/payload.php — the menu payload gains updateCounts (total, locale-formatted count, translated screen-reader text, update-core.php URL) from capability-aware wp_get_update_data(), prebuilt server-side so the client repaint stays locale-correct.
  • src/boot/menu-refresh.ts — handles the nudge with a 600 ms trailing debounce plus in-flight coalescing (a nudge landing mid-probe queues exactly one follow-up probe), then spends one existing refreshMenu() probe.
  • src/admin-bar-updates.ts (new, wired from src/menu-refresh-apply.ts) — mirrors updateCounts onto the admin-bar node: label + screen-reader text, hidden at zero, re-created mirroring Core's wp_admin_bar_updates_menu() markup when absent. Missing key (older payload) means "no change". The dock badge needs no new code — the probe's payload already recomputes it.

Docs updated in the same change: docs/javascript-reference.md (payload shape + new message), docs/api-index.md, and the payload key listing in AGENTS.md.

Testing instructions

npm run test:js    # includes 8 new cases for the admin-bar repaint + 2 payload-contract cases
npm run test:php -- --filter test_payload_carries_update_counts

Manual repro (mirrors the issue):

  1. Install outdated plugins, e.g. wp plugin install classic-editor --version=1.6.5 and wp plugin install akismet --version=5.3, then wp eval 'wp_update_plugins();'.
  2. Load the desktop shell — top-left shows the circle-arrows count, the dock Plugins tile shows a badge.
  3. Update the plugins from the Plugins window ("update now" links) — the count steps down live and both notifiers disappear at zero.
  4. Repeat via the Updates screen with "Update Plugins" (bulk) — same live reset when the run completes.

Verified end-to-end on wp-env: counter stepped 3→2→1→hidden with per-plugin updates, and the bulk run cleared both notifiers the moment "All updates have been completed" appeared. Full suites green: 2178 vitest tests, 1333 PHPUnit tests, typecheck, ESLint, PHPCS (no new violations).

Open WordPress Playground Preview

Core's shiny updater applies plugin/theme updates over AJAX, so the
chromeless bridge's load-time payload emit never re-fired and both the
admin-bar circle-arrows count and the dock Plugins badge kept their
boot-time numbers until a hard refresh.

The bridge now watches updates.js completion events and nudges the
shell (desktop-mode-updates-changed), posts payload/signature to the
top window so the bulk updater's nested update.php iframe reaches the
shell, and the payload carries aggregate updateCounts that the shell
mirrors onto #wp-admin-bar-updates via one debounced refreshMenu()
probe.
@epeicher
epeicher merged commit 6fde2d1 into trunk Jul 24, 2026
5 checks passed
@epeicher
epeicher deleted the fix/296-update-notifier-stale branch July 24, 2026 08:18
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.

Plugin update notifier does not reset

1 participant