Skip to content

Open configured after a live activation in OpenStation - #10

Merged
AllTerrainDeveloper merged 1 commit into
AllTerrainDeveloper:mainfrom
epeicher:fix/live-activation-window-assets
Sep 17, 2026
Merged

AllTerrainDeveloper merged 1 commit into
AllTerrainDeveloper:mainfrom
epeicher:fix/live-activation-window-assets

Conversation

@epeicher

@epeicher epeicher commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

What it does

Photo Editor opens with the editor rendered after being activated from the OpenStation Plugins window, without a page reload. Previously the window opened empty until an F5.

Rationale

The app in apps/photo-editor/photo-editor.os.php declared only its client view. That view mounts the editor but does not contain it: the editor is the lienzo script handle, which only reached the page through lienzo_enqueue_in_shell() on openstation_mode_init, a hook that fires while the shell page renders at boot. A plugin activated mid-session never saw it, so mountEditor() polled for window.lienzo.renderDesktopWindow for MAIN_BUNDLE_WAIT_MS and gave up.

Deactivating and reactivating in one session did not reproduce it, because the bundle printed at boot was still in the page. A fresh install is the case that failed.

Two more things were attached at the wrong moment, inside lienzo_enqueue_editor(): the window.lienzoConfig inline and the lienzo stylesheet. OpenStation harvests a handle's inline data off the registered handle when it builds a window payload, so data added only at enqueue time was invisible on the live path.

Implementation

The app window now names the bundle and its stylesheet through openstation_app_window_args, the seam OpenStation exposes for riding registered handles on an app window:

function lienzo_app_window_args( $args, $id ) {
	if ( 'lienzo' !== $id ) {
		return $args;
	}
	$args['scripts'] = array_merge( array( 'lienzo' ), (array) ( $args['scripts'] ?? array() ) );
	$args['styles']  = array_merge( (array) ( $args['styles'] ?? array() ), array( 'lienzo' ) );
	return $args;
}

The script is prepended so window.lienzo exists before the client view's first mount attempt rather than its first poll. The poll stays as a safety net.

The wp_add_inline_script() call moves from lienzo_enqueue_editor() into lienzo_register_assets() on init, right after wp_register_script( 'lienzo', … ). The "already enqueued" guard in lienzo_enqueue_editor() is gone: the inline is on the handle once per request regardless of how many times it is enqueued. This is the same pattern AllTerrain Forms uses for its config handle.

lienzo_enqueue_in_shell() is unchanged. A normal boot still gets the bundle up front, and WordPress prints an enqueued handle once, so a boot that takes both paths does not inject lienzo.js twice.

Follow-up to WordPress/openstation#825 (WordPress/openstation#825), which makes a window's companion scripts carry their declared dependencies and inline data on a live activation. That PR fixed the shell-side gap; this one fixes Photo Editor's own reason for failing, which is that it never told the shell about its main bundle. On an older shell this change is harmless but does not fix the bug.

Testing instructions

npx wp-env start
npm run test:php:install
npm run test:php

135 tests pass, 6 of them new: the config is on the registered handle before any enqueue, repeated enqueues print it once, and lienzo_app_window_args prepends the script, appends the style, and leaves other apps alone.

For the live path, with OpenStation at or after WordPress/openstation#825:

  1. Deactivate Photo Editor, then load the shell at admin.php?page=openstation.
  2. Activate Photo Editor from the Plugins window. Do not reload.
  3. Open it from the dock tile or desktop icon.

The editor should render. In the console, window.lienzo.renderDesktopWindow is a function, window.lienzoConfig is defined, and document.querySelectorAll('script[src*="lienzo.js"]').length is 1.

  1. Reload and open it again. The boot path should still work with one lienzo.js script tag, one lienzo.css stylesheet, and one inline config.

… configured

Activating Photo Editor from the OpenStation Plugins window and opening it
without a reload showed a blank window. The app declared only its client
view; the editor itself, the `lienzo` handle, reached the page solely through
the boot-time enqueue on `openstation_mode_init`, which a plugin activated
mid-session never saw.

The app window now names the `lienzo` script and stylesheet through
`openstation_app_window_args`, so the shell loads them with the window on
first open. The `window.lienzoConfig` inline moves from enqueue time to
registration on `init`, where the shell harvests it when it builds the
window payload. The boot-time enqueue stays and prints the same handle once.

Needs OpenStation at or after #825, which replays a lazily loaded bundle's
declared dependencies and inline data on a live activation.
@AllTerrainDeveloper
AllTerrainDeveloper merged commit 9557e80 into AllTerrainDeveloper:main Sep 17, 2026
AllTerrainDeveloper added a commit that referenced this pull request Oct 8, 2026
Dropping a photo saved to the OpenStation desktop onto the editor's
wallpaper icon was rejected. The window read `desktop-file` drags, but the
icon only handled `attachment` and `shortcut` payloads. The icon now
registers a `desktop-file` handler. A desktop upload is added to the Media
Library on drop, and Media Library items and posts placed on the desktop
open directly. The window and the icon share one resolver.

#10 made the app window load the bundle on first open after a live
activation. Until that first open, the jobs the bundle does before any
window exists did nothing: the icon drop, the file opener, the media
modal's open requests. A payload built in a chromeless request, which is
the one that announces an activation, now asks the shell to preload the
bundle. The shell page enqueues it anyway, and a window the shell already
knows ignores the flag.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

2 participants