PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 1.1.12
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v1.1.12
1.1.12 1.1.11 1.1.10 1.1.9 1.1.8 1.1.7 1.1.6 1.1.5 1.1.4 1.1.3 1.1.2 1.1.1 1.1.0 1.0.1 1.0.0 0.9.8 0.9.7 0.9.6 0.9.4 0.9.5 0.9.3 0.9.2 0.9.1 0.9.0 0.8.9 All 36 releases
← All changes | includes/assets.php +344 -183 0.9.5 → 1.1.12 View file →
@@ -1,12 +1,12 @@
1 1 <?php
2 2 /**
3 - * Desktop Mode asset registration.
3 + * OpenStation asset registration.
4 4 *
5 - * Registers all desktop-mode CSS and JS handles with WordPress so they can
5 + * Registers all openstation CSS and JS handles with WordPress so they can
6 6 * be enqueued from anywhere in the plugin (or by third parties).
7 7 *
8 - * @package WPDesktopMode
8 + * @package OpenStation
9 9 */
10 10
11 11 defined( 'ABSPATH' ) || exit;
12 12
@@ -16,16 +16,14 @@
16 16 * Sub-sheet URLs carry no `?ver=` of their own, so the parent's stamp is
17 17 * the only cache key the browser ever sees for the subtree — it must
18 18 * move when any member changes.
19 19 *
20 - * @since 0.9.4
21 - *
22 20 * @param string $relative Stylesheet path relative to the plugin dir.
23 21 * @param string $fallback Version to use when the file is missing.
24 22 * @return string Version string.
25 23 */
26 -function desktop_mode_css_subtree_version( $relative, $fallback ) {
27 - $root = DESKTOP_MODE_DIR . $relative;
24 +function openstation_css_subtree_version( $relative, $fallback ) {
25 + $root = OPENSTATION_DIR . $relative;
28 26 if ( ! file_exists( $root ) ) {
29 27 return (string) $fallback;
30 28 }
31 29 $max = (int) filemtime( $root );
@@ -50,18 +48,16 @@
50 48 return (string) $max;
51 49 }
52 50
53 51 /**
54 - * Registers the desktop mode CSS and JS handles.
55 - *
56 - * @since 0.1.0
52 + * Registers the OpenStation CSS and JS handles.
57 53 */
58 -function desktop_mode_register_assets() {
59 - $version = DESKTOP_MODE_VERSION;
60 - $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
54 +function openstation_register_assets() {
55 + $version = OPENSTATION_VERSION;
56 + $suffix = openstation_asset_suffix();
61 57
62 58 // `filemtime`-stamped version for built bundles. The plugin-wide
63 - // `DESKTOP_MODE_VERSION` is bumped per release, but the bundles
59 + // `OPENSTATION_VERSION` is bumped per release, but the bundles
64 60 // iterate faster — without a per-file mtime stamp, two clients
65 61 // loading the same `?ver=…` URL can be served different bytes
66 62 // (whichever build was on disk at upload time). Stamping with the
67 63 // file's modification time guarantees the URL changes whenever the
@@ -68,68 +64,176 @@
68 64 // file does, so "is my fix deployed?" is answerable from the
69 65 // network tab. Falls back to `$version` when the file is missing
70 66 // (test envs that import this file before the build runs).
71 67 $built_version = static function ( $relative ) use ( $version ) {
72 - $path = DESKTOP_MODE_DIR . $relative;
68 + $path = OPENSTATION_DIR . $relative;
73 69 return file_exists( $path ) ? (string) filemtime( $path ) : $version;
74 70 };
75 71
76 -
77 72 // Styles.
73 + // `filemtime`-stamped, NOT the plugin-wide `$version`. This file
74 + // is the token catalogue every other sheet resolves `var()`s
75 + // against, and it changes whenever the palette does — which is a
76 + // lot more often than the plugin version is bumped. With a static
77 + // stamp the browser holds the old palette until a hard reload,
78 + // and the symptom is maddening: a themed shell where some
79 + // surfaces update and others don't.
78 80 wp_register_style(
79 - 'desktop-mode-variables',
80 - DESKTOP_MODE_URL . 'assets/css/variables.css',
81 + 'os-variables',
82 + OPENSTATION_URL . 'assets/css/variables.css',
81 83 array(),
82 - $version
84 + $built_version( 'assets/css/variables.css' )
83 85 );
84 86 // `filemtime`-stamped so the `<link rel="stylesheet">` URL matches the
85 87 // `<link rel="preload" as="style">` hint emitted by
86 - // `desktop_mode_print_preload_hints()` (which stamps with filemtime).
88 + // `openstation_print_preload_hints()` (which stamps with filemtime).
87 89 // Registering this with the plain `$version` instead produced two
88 90 // different `?ver=` query strings for the same file, so the browser
89 91 // never matched the preload to the stylesheet and logged "preloaded
90 92 // but not used within a few seconds from the window's load event".
91 93 wp_register_style(
92 - 'desktop-mode',
93 - DESKTOP_MODE_URL . 'assets/css/desktop.css',
94 - array( 'desktop-mode-variables' ),
94 + 'openstation',
95 + OPENSTATION_URL . 'assets/css/desktop.css',
96 + array( 'os-variables' ),
95 97 $built_version( 'assets/css/desktop.css' )
96 98 );
97 - // `filemtime`-stamped — window-chrome iteration (drop overlays,
98 - // new drag affordances, third-party-plugin compat) lands faster
99 - // than plugin version bumps. Without an mtime stamp the browser
100 - // keeps `?ver=<plugin-version>` valid for the whole release cycle
101 - // and the user keeps seeing yesterday's CSS even after a hard
102 - // reload.
103 - //
104 - // The stamp covers the whole `@import` SUBTREE, not just the parent
105 - // file: `windows.css` imports `window-chrome.css`,
106 - // `os-settings.css`, … and those sub-sheet URLs carry no `?ver=` of
107 - // their own. Stamping only the parent meant an edit to a sub-sheet
108 - // never changed any URL the browser knew about, so users kept
109 - // yesterday's rules until an unrelated parent edit came along
110 - // (exactly how the wallpaper-description card shipped with stale
111 - // layout). The subtree max-mtime busts the parent whenever ANY
112 - // sub-sheet changes; the re-parsed parent then re-requests the
113 - // sub-sheets, whose fresh mtimes fail heuristic-cache reuse.
99 +
100 + /*
101 + * Window styles — one handle per sheet, chained by dependency.
102 + *
103 + * These used to be `@import url( … )`ed from `windows.css` under
104 + * the single `os-windows` handle. That was a standing
105 + * cache bug: an `@import` URL carries no `?ver=`, so a changed
106 + * sub-sheet had no URL for the browser to invalidate. Stamping the
107 + * PARENT with the subtree's max mtime (which is what
108 + * `openstation_css_subtree_version()` was for) made the browser
109 + * re-fetch `windows.css` and then request each sub-sheet at an
110 + * unchanged URL — free to be served from its heuristic cache. The
111 + * result was edits not landing until a hard refresh, and rules
112 + * being relocated into `windows.css` purely to dodge it.
113 + *
114 + * Now every sheet is separately registered with its own
115 + * `filemtime` stamp, so each has a real cache key.
116 + *
117 + * THE DEPENDENCY CHAIN IS LOAD-BEARING. WordPress prints
118 + * dependencies before dependents, so chaining each sheet to the
119 + * previous one reproduces the order the `@import` block had, and
120 + * `os-windows` (which depends on the last link) still
121 + * prints after them and still wins ties:
122 + *
123 + * window-chrome → window-states → effects → window-links
124 + * → windows
125 + *
126 + * `window-overview` is deliberately NOT in this chain — it is
127 + * registered below, after `os-windows`, so it can load deferred.
128 + * Adding a sheet here means splicing it into the chain, not
129 + * appending an unrelated dependency: order is the contract.
130 + * (The Preferences window's sheet is not here at all: it rides
131 + * the `apps/os-settings/` app as a first-open companion style.)
132 + */
133 + $window_sheets = array(
134 + 'os-window-chrome' => 'assets/css/window-chrome.css',
135 + 'os-window-states' => 'assets/css/window-states.css',
136 + 'os-effects' => 'assets/css/effects.css',
137 + 'os-window-links' => 'assets/css/window-links.css',
138 + );
139 + $previous = array( 'os-variables', 'dashicons' );
140 + foreach ( $window_sheets as $handle => $relative ) {
141 + wp_register_style(
142 + $handle,
143 + OPENSTATION_URL . $relative,
144 + $previous,
145 + $built_version( $relative )
146 + );
147 + $previous = array( $handle );
148 + }
149 +
150 + // Entry point. Depends on the tail of the chain above, so
151 + // enqueuing this one handle still pulls in every critical window
152 + // sheet — the behaviour callers had when they were `@import`s.
114 153 wp_register_style(
115 - 'desktop-mode-windows',
116 - DESKTOP_MODE_URL . 'assets/css/windows.css',
117 - array( 'desktop-mode-variables', 'dashicons' ),
118 - desktop_mode_css_subtree_version( 'assets/css/windows.css', $version )
154 + 'os-windows',
155 + OPENSTATION_URL . 'assets/css/windows.css',
156 + $previous,
157 + $built_version( 'assets/css/windows.css' )
119 158 );
159 + // Loads DEFERRED (see `openstation_defer_non_critical_styles()`):
160 + // the UI it styles — the window overview — is lazy-loaded JS that
161 + // can never be on screen at first paint, so its CSS has no
162 + // business blocking render. It depends on `os-windows` so it
163 + // prints after it, preserving the cascade position it had as an
164 + // `@import`.
120 165 wp_register_style(
121 - 'desktop-mode-dock',
122 - DESKTOP_MODE_URL . 'assets/css/dock.css',
123 - array( 'desktop-mode-variables', 'dashicons' ),
124 - $version
166 + 'os-window-overview',
167 + OPENSTATION_URL . 'assets/css/window-overview.css',
168 + array( 'os-windows' ),
169 + $built_version( 'assets/css/window-overview.css' )
125 170 );
171 + // Solo mode — one window, no desk around it. Loads last so it can
172 + // hide surfaces the sheets above declared, and only enqueues on a
173 + // solo request, so a normal shell never pays for it.
126 174 wp_register_style(
127 - 'desktop-mode-dock-peek',
128 - DESKTOP_MODE_URL . 'assets/css/dock-peek.css',
129 - array( 'desktop-mode-dock' ),
130 - $version
175 + 'os-solo',
176 + OPENSTATION_URL . 'assets/css/solo.css',
177 + array( 'os-windows' ),
178 + $built_version( 'assets/css/solo.css' )
131 179 );
180 + wp_register_style(
181 + 'os-dock',
182 + OPENSTATION_URL . 'assets/css/dock.css',
183 + array( 'os-variables', 'dashicons' ),
184 + $built_version( 'assets/css/dock.css' )
185 + );
186 + wp_register_style(
187 + 'os-dock-peek',
188 + OPENSTATION_URL . 'assets/css/dock-peek.css',
189 + array( 'os-dock' ),
190 + $built_version( 'assets/css/dock-peek.css' )
191 + );
192 + // The phone layer. Every rule is scoped to
193 + // `html[data-os-mode="mobile"]`, so the sheet is inert on a
194 + // desktop and the first paint on a phone is already right (the
195 + // head stamp writes the attribute before any stylesheet applies).
196 + // Depends on the dock and window sheets because it overrides them.
197 + wp_register_style(
198 + 'os-mobile',
199 + OPENSTATION_URL . 'assets/css/mobile.css',
200 + array( 'os-variables', 'dashicons', 'os-dock', 'os-windows' ),
201 + $built_version( 'assets/css/mobile.css' )
202 + );
203 + // The workspace wizard. Scoped to `.os-workspace-wizard`, so it is
204 + // inert until the user opens it from the overview bar's `+` or a
205 + // tile's Edit. Those controls are styled with the rest of the bar
206 + // in `window-overview.css`.
207 + wp_register_style(
208 + 'os-workspaces',
209 + OPENSTATION_URL . 'assets/css/workspaces.css',
210 + array( 'os-variables', 'dashicons' ),
211 + $built_version( 'assets/css/workspaces.css' )
212 + );
213 + // Keyboard-shortcuts window. Scoped to `.os-shortcuts`, so it is
214 + // inert until the System menu opens the window, and unconditional
215 + // for the same reason the layout sheet is: the window can be
216 + // opened at any moment and a deferred sheet would paint it raw.
217 + wp_register_style(
218 + 'os-shortcuts',
219 + OPENSTATION_URL . 'assets/css/shortcuts.css',
220 + array( 'os-variables' ),
221 + $built_version( 'assets/css/shortcuts.css' )
222 + );
223 + // The OpenStation desktop layout — the core/plugin seam on the rail
224 + // plus the constellation hover-submenu flyout. Both surfaces are
225 + // scoped (`[data-os-layout="openstation"]` / `.os-constellation`),
226 + // so the sheet is inert in every other layout and is loaded
227 + // unconditionally rather than gated on the user's current pick:
228 + // the layout is switchable live from OpenStation Preferences, and a
229 + // conditional enqueue would leave the first switch unstyled.
230 + wp_register_style(
231 + 'os-openstation-layout',
232 + OPENSTATION_URL . 'assets/css/openstation-layout.css',
233 + array( 'os-dock' ),
234 + $built_version( 'assets/css/openstation-layout.css' )
235 + );
132 236 // `filemtime`-stamped — the chromeless overrides iterate faster
133 237 // than the plugin-wide version bumps (per-page compat shims and
134 238 // page-title-action exceptions land in patches), and a stale
135 239 // cached copy means the user sees yesterday's rules. Without the
@@ -135,11 +239,11 @@
135 239 // cached copy means the user sees yesterday's rules. Without the
136 240 // stamp, the browser keeps `?ver=0.8.1` valid for the whole
137 241 // release cycle.
138 242 wp_register_style(
139 - 'desktop-mode-chromeless',
140 - DESKTOP_MODE_URL . 'assets/css/chromeless.css',
141 - array( 'desktop-mode' ),
243 + 'os-chromeless',
244 + OPENSTATION_URL . 'assets/css/chromeless.css',
245 + array( 'openstation' ),
142 246 $built_version( 'assets/css/chromeless.css' )
143 247 );
144 248
145 249 // `filemtime`-stamped — the AI assistant surface (error states,
@@ -148,71 +252,94 @@
148 252 // valid for the whole release cycle and the user keeps seeing
149 253 // yesterday's CSS even after a hard reload.
150 254 wp_register_style(
151 255 'desktop-mode-ai-assistant',
152 - DESKTOP_MODE_URL . 'assets/css/ai-assistant.css',
153 - array( 'desktop-mode-variables' ),
256 + OPENSTATION_URL . 'assets/css/ai-assistant.css',
257 + array( 'os-variables' ),
154 258 $built_version( 'assets/css/ai-assistant.css' )
155 259 );
156 260
157 261 wp_register_style(
158 262 'desktop-mode-bug-report',
159 - DESKTOP_MODE_URL . 'assets/css/bug-report.css',
160 - array( 'desktop-mode-variables' ),
161 - $version
263 + OPENSTATION_URL . 'assets/css/bug-report.css',
264 + array( 'os-variables' ),
265 + $built_version( 'assets/css/bug-report.css' )
162 266 );
163 267
164 268 // `filemtime` instead of the plugin-wide `$version` for the
165 269 // recycle-bin CSS — this file iterates faster than the bundle
166 270 // and we never want a stale CSS cache to mask a real fix.
167 - $recycle_bin_css = DESKTOP_MODE_DIR . 'assets/css/recycle-bin.css';
271 + $recycle_bin_css = OPENSTATION_DIR . 'assets/css/recycle-bin.css';
168 272 wp_register_style(
169 273 'desktop-mode-recycle-bin',
170 - DESKTOP_MODE_URL . 'assets/css/recycle-bin.css',
171 - array( 'desktop-mode-variables', 'dashicons' ),
274 + OPENSTATION_URL . 'assets/css/recycle-bin.css',
275 + array( 'os-variables', 'dashicons' ),
172 276 file_exists( $recycle_bin_css ) ? (string) filemtime( $recycle_bin_css ) : $version
173 277 );
174 278
175 - // `filemtime` for the native Posts window CSS — same rationale as
176 - // the recycle-bin CSS: bundle iterates faster than the plugin
177 - // version and stale caches are worse than the cost of a 304.
178 - $posts_window_css = DESKTOP_MODE_DIR . 'assets/css/posts-window.css';
279 + // Files-on-the-Desktop tile + layer styles. `filemtime` for the
280 + // same reason as the recycle-bin CSS: this file
281 + // iterates faster than the plugin version, and a stale cache
282 + // would mask a real fix.
283 + $desktop_files_css = OPENSTATION_DIR . 'assets/css/desktop-files.css';
179 284 wp_register_style(
180 - 'desktop-mode-posts-window',
181 - DESKTOP_MODE_URL . 'assets/css/posts-window.css',
182 - array( 'desktop-mode-variables', 'dashicons' ),
183 - file_exists( $posts_window_css ) ? (string) filemtime( $posts_window_css ) : $version
285 + 'os-files',
286 + OPENSTATION_URL . 'assets/css/desktop-files.css',
287 + array( 'os-variables', 'dashicons' ),
288 + file_exists( $desktop_files_css ) ? (string) filemtime( $desktop_files_css ) : $version
184 289 );
185 290
186 - // Native Plugins window CSS — same `filemtime`-cache-bust posture
187 - // as the Posts/Recycle Bin styles.
188 - $plugins_window_css = DESKTOP_MODE_DIR . 'assets/css/plugins-window.css';
291 + // Games hub window (launcher grid, scoreboard, challenges) +
292 + // per-game styles. Same `filemtime` cache-bust posture as the
293 + // other fast-iterating feature stylesheets.
294 + $games_css = OPENSTATION_DIR . 'assets/css/games.css';
189 295 wp_register_style(
190 - 'desktop-mode-plugins-window',
191 - DESKTOP_MODE_URL . 'assets/css/plugins-window.css',
192 - array( 'desktop-mode-variables', 'dashicons' ),
193 - file_exists( $plugins_window_css ) ? (string) filemtime( $plugins_window_css ) : $version
296 + 'desktop-mode-games',
297 + OPENSTATION_URL . 'assets/css/games.css',
298 + array( 'os-variables', 'dashicons' ),
299 + file_exists( $games_css ) ? (string) filemtime( $games_css ) : $version
194 300 );
301 + $game_inkfall_css = OPENSTATION_DIR . 'assets/css/game-inkfall.css';
302 + wp_register_style(
303 + 'os-game-inkfall',
304 + OPENSTATION_URL . 'assets/css/game-inkfall.css',
305 + array( 'os-variables' ),
306 + file_exists( $game_inkfall_css ) ? (string) filemtime( $game_inkfall_css ) : $version
307 + );
308 + $game_alphabet_soup_css = OPENSTATION_DIR . 'assets/css/game-alphabet-soup.css';
309 + wp_register_style(
310 + 'os-game-alphabet-soup',
311 + OPENSTATION_URL . 'assets/css/game-alphabet-soup.css',
312 + array( 'os-variables' ),
313 + file_exists( $game_alphabet_soup_css ) ? (string) filemtime( $game_alphabet_soup_css ) : $version
314 + );
195 315
196 - // Native Comments window CSS — same `filemtime` posture.
197 - $comments_window_css = DESKTOP_MODE_DIR . 'assets/css/comments-window.css';
316 + // Pinned-notes layer styles (paper, pushpin, pastel tokens, pin
317 + // animations). Same `filemtime` cache-bust posture as the other
318 + // fast-iterating feature stylesheets above. Depends on `os-files`
319 + // because a pinned note dresses the canonical `.os-file-tile`
320 + // chrome — anything that restyles a tile has to print after the
321 + // file that declares one.
322 + $notes_css = OPENSTATION_DIR . 'assets/css/notes.css';
198 323 wp_register_style(
199 - 'desktop-mode-comments-window',
200 - DESKTOP_MODE_URL . 'assets/css/comments-window.css',
201 - array( 'desktop-mode-variables', 'dashicons' ),
202 - file_exists( $comments_window_css ) ? (string) filemtime( $comments_window_css ) : $version
324 + 'os-notes',
325 + OPENSTATION_URL . 'assets/css/notes.css',
326 + array( 'os-variables', 'dashicons', 'os-files' ),
327 + file_exists( $notes_css ) ? (string) filemtime( $notes_css ) : $version
203 328 );
204 329
205 - // Files-on-the-Desktop tile + layer styles. `filemtime` for the
206 - // same reason as the recycle-bin / posts-window CSS: this file
207 - // iterates faster than the plugin version, and a stale cache
208 - // would mask a real fix.
209 - $desktop_files_css = DESKTOP_MODE_DIR . 'assets/css/desktop-files.css';
330 + // Announcement-dialog styles (scrim, hero card, buttons). Registered
331 + // always, enqueued only for a user who is actually owed the
332 + // announcement — see the gate in `openstation_enqueue_assets()`. It
333 + // is not lazy-loaded on top of that: on the one boot where it does
334 + // go out, the dialog opens from the main bundle a second later, and
335 + // a fetch racing that would show an unstyled card.
336 + $announce_css = OPENSTATION_DIR . 'assets/css/announce.css';
210 337 wp_register_style(
211 - 'desktop-mode-files',
212 - DESKTOP_MODE_URL . 'assets/css/desktop-files.css',
213 - array( 'desktop-mode-variables', 'dashicons' ),
214 - file_exists( $desktop_files_css ) ? (string) filemtime( $desktop_files_css ) : $version
338 + 'os-announce',
339 + OPENSTATION_URL . 'assets/css/announce.css',
340 + array( 'os-variables' ),
341 + file_exists( $announce_css ) ? (string) filemtime( $announce_css ) : $version
215 342 );
216 343
217 344 // Scripts.
218 345 //
@@ -223,10 +350,10 @@
223 350 // lookups. Both handles are core-shipped but only pre-enqueued
224 351 // when Gutenberg-adjacent deps pull them in, so we list them
225 352 // explicitly to guarantee load order.
226 353 wp_register_script(
227 - 'desktop-mode',
228 - DESKTOP_MODE_URL . 'assets/js/desktop' . $suffix . '.js',
354 + 'openstation',
355 + OPENSTATION_URL . 'assets/js/desktop' . $suffix . '.js',
229 356 // `heartbeat` + `jquery` — the recycle-bin badge module
230 357 // (loaded as part of this bundle) opts into the WordPress
231 358 // Heartbeat API so the count tile / desktop-icon badge
232 359 // stays in sync even when the bin window is closed.
@@ -231,13 +358,24 @@
231 358 // Heartbeat API so the count tile / desktop-icon badge
232 359 // stays in sync even when the bin window is closed.
233 360 array( 'wp-hooks', 'wp-i18n', 'heartbeat', 'jquery' ),
234 361 $built_version( 'assets/js/desktop' . $suffix . '.js' ),
235 - true
362 + // Footer + defer: the shell boots on DOMContentLoaded anyway,
363 + // so deferring frees the parser instead of blocking at the
364 + // footer print point. Both inline payloads attached to this
365 + // handle (`__openStationMenuCommands`, the jazz-quote version
366 + // stamp) are `'before'`-position, which WP keeps as blocking
367 + // inline ahead of a deferred tag — order is preserved. On WP
368 + // < 6.3 the array collapses to a truthy `$in_footer`, same as
369 + // before.
370 + array(
371 + 'in_footer' => true,
372 + 'strategy' => 'defer',
373 + )
236 374 );
237 375
238 - // `desktop-mode-iframe-bridge` — opt-in iframe-side bridge that
239 - // provides `wp.desktop.iframe.publish/subscribe/onConnection/
376 + // `os-iframe-bridge` — opt-in iframe-side bridge that
377 + // provides `wp.os.iframe.publish/subscribe/onConnection/
240 378 // requestConnection` to any same-origin iframe that enqueues it.
241 379 // Same code is also injected inline by the chromeless bridge
242 380 // (so chromeless wp-admin pages don't need a separate enqueue)
243 381 // and auto-injected when a native window opts in via
@@ -243,19 +381,60 @@
243 381 // and auto-injected when a native window opts in via
244 382 // `iframeContent: { bridge: true }`. Plugins targeting their
245 383 // own iframe pages just enqueue this handle.
246 384 wp_register_script(
247 - 'desktop-mode-iframe-bridge',
248 - DESKTOP_MODE_URL . 'assets/js/iframe-bridge' . $suffix . '.js',
385 + 'os-iframe-bridge',
386 + OPENSTATION_URL . 'assets/js/iframe-bridge' . $suffix . '.js',
249 387 array(),
250 388 $built_version( 'assets/js/iframe-bridge' . $suffix . '.js' ),
251 389 true
252 390 );
253 391
254 - // `desktop-mode-gutenberg-drop-receiver` — iframe-side bundle
392 + // `os-deactivation-feedback` — the dialog that asks one optional
393 + // question when an admin deactivates OpenStation. Enqueued on
394 + // `plugins.php` (classic, chromeless and network admin) by
395 + // `includes/feedback/deactivation.php`, and lazy-loaded by the
396 + // native Plugins app from its config block. Plain DOM on purpose:
397 + // the classic screen has no `<os-*>` kit.
398 + wp_register_script(
399 + 'os-deactivation-feedback',
400 + OPENSTATION_URL . 'assets/js/deactivation-feedback' . $suffix . '.js',
401 + array( 'wp-i18n' ),
402 + $built_version( 'assets/js/deactivation-feedback' . $suffix . '.js' ),
403 + true
404 + );
405 + wp_set_script_translations(
406 + 'os-deactivation-feedback',
407 + 'desktop-mode',
408 + OPENSTATION_DIR . 'languages'
409 + );
410 + $feedback_css = OPENSTATION_DIR . 'assets/css/deactivation-feedback.css';
411 + wp_register_style(
412 + 'os-deactivation-feedback',
413 + OPENSTATION_URL . 'assets/css/deactivation-feedback.css',
414 + array(),
415 + file_exists( $feedback_css ) ? (string) filemtime( $feedback_css ) : $version
416 + );
417 +
418 + // `os-chromeless-bridge` — the iframe side of every window,
419 + // enqueued on `admin_footer` by
420 + // `openstation_chromeless_bridge_script()` with its per-request
421 + // data attached as a `before` inline block. Registered here (not
422 + // there) so the handle exists before the enqueue and so the asset
423 + // guard's OPENSTATION_URL snapshot protects it like every other
424 + // bundle of ours.
425 + wp_register_script(
426 + 'os-chromeless-bridge',
427 + OPENSTATION_URL . 'assets/js/chromeless-bridge' . $suffix . '.js',
428 + array(),
429 + $built_version( 'assets/js/chromeless-bridge' . $suffix . '.js' ),
430 + true
431 + );
432 +
433 + // `os-gutenberg-drop-receiver` — iframe-side bundle
255 434 // enqueued only on the Block Editor screens (`post.php` /
256 - // `post-new.php`) for desktop-mode users. Listens for
257 - // `desktop-mode-drop` postMessages from the parent shell (see
435 + // `post-new.php`) for openstation users. Listens for
436 + // `os-drop` postMessages from the parent shell (see
258 437 // `src/drag/iframe-drop-targets.ts`) and inserts the matching
259 438 // Gutenberg block via `wp.data.dispatch('core/block-editor')`.
260 439 // Depends on `wp-blocks` + `wp-data` so the editor stores are
261 440 // guaranteed enqueued before the receiver runs its first message
@@ -260,112 +439,94 @@
260 439 // Depends on `wp-blocks` + `wp-data` so the editor stores are
261 440 // guaranteed enqueued before the receiver runs its first message
262 441 // handler.
263 442 wp_register_script(
264 - 'desktop-mode-gutenberg-drop-receiver',
265 - DESKTOP_MODE_URL . 'assets/js/gutenberg-drop-receiver' . $suffix . '.js',
443 + 'os-gutenberg-drop-receiver',
444 + OPENSTATION_URL . 'assets/js/gutenberg-drop-receiver' . $suffix . '.js',
266 445 array( 'wp-blocks', 'wp-data' ),
267 446 $built_version( 'assets/js/gutenberg-drop-receiver' . $suffix . '.js' ),
268 447 true
269 448 );
270 449
271 - // `desktop-mode-recycle-bin` — small bundle for the Recycle Bin
272 - // native window. Lazy-loaded by the native-window sync the first
273 - // time the bin opens; registers a render callback on
274 - // `window.desktopModeNativeWindows['desktop-mode-recycle-bin']`.
275 - $recycle_bin_js = DESKTOP_MODE_DIR . 'assets/js/recycle-bin' . $suffix . '.js';
450 + // The Recycle Bin window is an App Framework app (`apps/trash/`);
451 + // its client view rides the app-bundle pipeline, so no dedicated
452 + // script handle. The `desktop-mode-recycle-bin` STYLE handle above
453 + // stays — the drag-to-trash drop-target highlight must be present
454 + // at boot (dropping on the closed bin's dock tile), not window-open.
455 +
456 + // `desktop-mode-games` — bundle for the Games hub native window
457 + // (launcher grid, scoreboard, challenges client). Lazy-loaded by
458 + // the native-window sync the first time the hub opens; registers a
459 + // render callback on
460 + // `window.openStationNativeWindows['desktop-mode-games']`.
461 + // `heartbeat` + `jquery` — the challenges client rides the
462 + // WordPress Heartbeat bus for live delivery.
463 + $games_js = OPENSTATION_DIR . 'assets/js/games' . $suffix . '.js';
276 464 wp_register_script(
277 - 'desktop-mode-recycle-bin',
278 - DESKTOP_MODE_URL . 'assets/js/recycle-bin' . $suffix . '.js',
279 - // `heartbeat` + `jquery` — the bin opts in to the WordPress
280 - // Heartbeat API while its window is open as the catch-all
281 - // real-time channel for deletes that don't render an admin
282 - // footer (REST/AJAX/other tabs/WP-CLI). See
283 - // `src/recycle-bin/realtime.ts` for the subscriber.
465 + 'desktop-mode-games',
466 + OPENSTATION_URL . 'assets/js/games' . $suffix . '.js',
284 467 array( 'wp-i18n', 'heartbeat', 'jquery' ),
285 - file_exists( $recycle_bin_js ) ? (string) filemtime( $recycle_bin_js ) : $version,
468 + file_exists( $games_js ) ? (string) filemtime( $games_js ) : $version,
286 469 true
287 470 );
288 471 wp_set_script_translations(
289 - 'desktop-mode-recycle-bin',
472 + 'desktop-mode-games',
290 473 'desktop-mode',
291 - DESKTOP_MODE_DIR . 'languages'
474 + OPENSTATION_DIR . 'languages'
292 475 );
293 476
294 - // `desktop-mode-posts-window` — small bundle for the native Posts
295 - // window. Lazy-loaded by the native-window sync the first time the
296 - // window opens (via the dock-click swap when the user opts in);
297 - // registers a render callback on
298 - // `window.desktopModeNativeWindows['desktop-mode-posts']`.
299 - $posts_window_js = DESKTOP_MODE_DIR . 'assets/js/posts-window' . $suffix . '.js';
477 + // `os-game-inkfall` — the Inkfall game bundle. Loaded
478 + // lazily by the games framework on first launch; publishes the
479 + // game def on `window.openStationGames.inkfall`.
480 + $game_inkfall_js = OPENSTATION_DIR . 'assets/js/game-inkfall' . $suffix . '.js';
300 481 wp_register_script(
301 - 'desktop-mode-posts-window',
302 - DESKTOP_MODE_URL . 'assets/js/posts-window' . $suffix . '.js',
482 + 'os-game-inkfall',
483 + OPENSTATION_URL . 'assets/js/game-inkfall' . $suffix . '.js',
303 484 array( 'wp-i18n' ),
304 - file_exists( $posts_window_js ) ? (string) filemtime( $posts_window_js ) : $version,
485 + file_exists( $game_inkfall_js ) ? (string) filemtime( $game_inkfall_js ) : $version,
305 486 true
306 487 );
307 488 wp_set_script_translations(
308 - 'desktop-mode-posts-window',
489 + 'os-game-inkfall',
309 490 'desktop-mode',
310 - DESKTOP_MODE_DIR . 'languages'
491 + OPENSTATION_DIR . 'languages'
311 492 );
312 493
313 - // `desktop-mode-plugins-window` — small bundle for the native
314 - // Plugins window. Lazy-loaded by the native-window sync the first
315 - // time the window opens (via the dock-click swap when the user
316 - // opts in); registers a render callback on
317 - // `window.desktopModeNativeWindows['desktop-mode-plugins']`.
318 - $plugins_window_js = DESKTOP_MODE_DIR . 'assets/js/plugins-window' . $suffix . '.js';
494 + // `os-game-alphabet-soup` — the Alphabet Soup game
495 + // bundle. Loaded lazily by the games framework on first launch;
496 + // publishes the game def on
497 + // `window.openStationGames['alphabet-soup']`.
498 + $game_alphabet_soup_js = OPENSTATION_DIR . 'assets/js/game-alphabet-soup' . $suffix . '.js';
319 499 wp_register_script(
320 - 'desktop-mode-plugins-window',
321 - DESKTOP_MODE_URL . 'assets/js/plugins-window' . $suffix . '.js',
500 + 'os-game-alphabet-soup',
501 + OPENSTATION_URL . 'assets/js/game-alphabet-soup' . $suffix . '.js',
322 502 array( 'wp-i18n' ),
323 - file_exists( $plugins_window_js ) ? (string) filemtime( $plugins_window_js ) : $version,
503 + file_exists( $game_alphabet_soup_js ) ? (string) filemtime( $game_alphabet_soup_js ) : $version,
324 504 true
325 505 );
326 506 wp_set_script_translations(
327 - 'desktop-mode-plugins-window',
507 + 'os-game-alphabet-soup',
328 508 'desktop-mode',
329 - DESKTOP_MODE_DIR . 'languages'
509 + OPENSTATION_DIR . 'languages'
330 510 );
331 511
332 - // `desktop-mode-comments-window` — small bundle for the native
333 - // Comments window. Lazy-loaded by the native-window sync the first
334 - // time the window opens (via the dock-click swap when the user
335 - // opts in); registers a render callback on
336 - // `window.desktopModeNativeWindows['desktop-mode-comments']`.
337 - $comments_window_js = DESKTOP_MODE_DIR . 'assets/js/comments-window' . $suffix . '.js';
338 - wp_register_script(
339 - 'desktop-mode-comments-window',
340 - DESKTOP_MODE_URL . 'assets/js/comments-window' . $suffix . '.js',
341 - array( 'wp-i18n' ),
342 - file_exists( $comments_window_js ) ? (string) filemtime( $comments_window_js ) : $version,
343 - true
344 - );
345 - wp_set_script_translations(
346 - 'desktop-mode-comments-window',
347 - 'desktop-mode',
348 - DESKTOP_MODE_DIR . 'languages'
349 - );
350 -
351 - // `desktop-mode-animated-logo-wallpaper` — built-in PixiJS canvas
352 - // wallpaper, moved out of `desktop.min.js` in 0.8.4. The wallpaper
512 + // `os-animated-logo-wallpaper` — built-in PixiJS canvas
513 + // wallpaper, moved out of `desktop.min.js`. The wallpaper
353 514 // `server-sync` loads this handle when the user selects the
354 515 // `wp-animated-logo` wallpaper (or opens OS Settings → Wallpaper
355 516 // and the picker pulls every registered canvas def in). The
356 517 // bundle's only side effect is publishing the `WallpaperDef` on
357 - // `window.desktopModeWallpapers['wp-animated-logo']`.
358 - $animated_logo_js = DESKTOP_MODE_DIR . 'assets/js/animated-logo-wallpaper' . $suffix . '.js';
518 + // `window.openStationWallpapers['wp-animated-logo']`.
519 + $animated_logo_js = OPENSTATION_DIR . 'assets/js/animated-logo-wallpaper' . $suffix . '.js';
359 520 wp_register_script(
360 - 'desktop-mode-animated-logo-wallpaper',
361 - DESKTOP_MODE_URL . 'assets/js/animated-logo-wallpaper' . $suffix . '.js',
521 + 'os-animated-logo-wallpaper',
522 + OPENSTATION_URL . 'assets/js/animated-logo-wallpaper' . $suffix . '.js',
362 523 array( 'wp-hooks' ),
363 524 file_exists( $animated_logo_js ) ? (string) filemtime( $animated_logo_js ) : $version,
364 525 true
365 526 );
366 527
367 - // `desktop-mode-snow-wallpaper` — built-in PixiJS canvas
528 + // `os-snow-wallpaper` — built-in PixiJS canvas
368 529 // wallpaper: snowfall that accumulates on window tops and melts
369 530 // away. Same lazy-load path as the animated logo: the wallpaper
370 531 // `server-sync` injects this handle when the user selects the
371 532 // `wp-snow` wallpaper (or opens OS Settings → Wallpaper and the
@@ -370,32 +531,32 @@
370 531 // `server-sync` injects this handle when the user selects the
371 532 // `wp-snow` wallpaper (or opens OS Settings → Wallpaper and the
372 533 // picker pulls the def in). The bundle's only side effect is
373 534 // publishing the `WallpaperDef` on
374 - // `window.desktopModeWallpapers['wp-snow']`.
375 - $snow_js = DESKTOP_MODE_DIR . 'assets/js/snow-wallpaper' . $suffix . '.js';
535 + // `window.openStationWallpapers['wp-snow']`.
536 + $snow_js = OPENSTATION_DIR . 'assets/js/snow-wallpaper' . $suffix . '.js';
376 537 wp_register_script(
377 - 'desktop-mode-snow-wallpaper',
378 - DESKTOP_MODE_URL . 'assets/js/snow-wallpaper' . $suffix . '.js',
538 + 'os-snow-wallpaper',
539 + OPENSTATION_URL . 'assets/js/snow-wallpaper' . $suffix . '.js',
379 540 array( 'wp-hooks', 'wp-i18n' ),
380 541 file_exists( $snow_js ) ? (string) filemtime( $snow_js ) : $version,
381 542 true
382 543 );
383 544 wp_set_script_translations(
384 - 'desktop-mode-snow-wallpaper',
545 + 'os-snow-wallpaper',
385 546 'desktop-mode',
386 - DESKTOP_MODE_DIR . 'languages'
547 + OPENSTATION_DIR . 'languages'
387 548 );
388 549
389 550 // `desktop-mode-ai-assistant` — AI Copilot spotlight overlay,
390 - // moved out of `desktop.min.js` in 0.8.4. The main bundle ships a
391 - // stub matching the public `wp.desktop.ai` contract; the stub
551 + // moved out of `desktop.min.js`. The main bundle ships a
552 + // stub matching the public `wp.os.ai` contract; the stub
392 553 // `<script>`-injects this handle the first time the user opens
393 554 // the assistant (Cmd+K or admin-bar button).
394 - $ai_assistant_js = DESKTOP_MODE_DIR . 'assets/js/ai-assistant' . $suffix . '.js';
555 + $ai_assistant_js = OPENSTATION_DIR . 'assets/js/ai-assistant' . $suffix . '.js';
395 556 wp_register_script(
396 557 'desktop-mode-ai-assistant',
397 - DESKTOP_MODE_URL . 'assets/js/ai-assistant' . $suffix . '.js',
558 + OPENSTATION_URL . 'assets/js/ai-assistant' . $suffix . '.js',
398 559 array( 'wp-hooks', 'wp-i18n' ),
399 560 file_exists( $ai_assistant_js ) ? (string) filemtime( $ai_assistant_js ) : $version,
400 561 true
401 562 );
@@ -401,19 +562,19 @@
401 562 );
402 563 wp_set_script_translations(
403 564 'desktop-mode-ai-assistant',
404 565 'desktop-mode',
405 - DESKTOP_MODE_DIR . 'languages'
566 + OPENSTATION_DIR . 'languages'
406 567 );
407 568
408 569 // Wire the translation bundle to this script handle. WP looks
409 - // for `languages/desktop-mode-{locale}-desktop-mode.json` and
570 + // for `languages/os-{locale}-os.json` and
410 571 // injects its `locale_data` into `wp.i18n` just before the
411 572 // script runs — so every `__()` call resolves to the right
412 573 // language without any runtime fetch.
413 574 wp_set_script_translations(
575 + 'openstation',
414 576 'desktop-mode',
415 - 'desktop-mode',
416 - DESKTOP_MODE_DIR . 'languages'
577 + OPENSTATION_DIR . 'languages'
417 578 );
418 579 }
419 -add_action( 'init', 'desktop_mode_register_assets' );
580 +add_action( 'init', 'openstation_register_assets' );