PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 1.1.10
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v1.1.10
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 0.8.8 0.8.7 All 34 releases
← All changes | includes/render/assets.php +83 -53 1.1.51.1.10 View file →
@@ -89,12 +89,16 @@
89 89 wp_enqueue_style( 'os-window-overview' );
90 90 wp_enqueue_style( 'os-dock' );
91 91 wp_enqueue_style( 'os-dock-peek' );
92 92 wp_enqueue_style( 'os-notch' );
93 + wp_enqueue_style( 'os-workspaces' );
93 94 wp_enqueue_style( 'os-shortcuts' );
94 95 wp_enqueue_style( 'os-openstation-layout' );
95 96 wp_enqueue_style( 'os-files' );
96 97 wp_enqueue_style( 'os-notes' );
98 + // Unconditional like the layout sheet: a live crossing into the
99 + // phone band must not find the phone layer unstyled.
100 + wp_enqueue_style( 'os-mobile' );
97 101
98 102 // Solo mode — a single window freed into a native OS window by the
99 103 // desktop host. Same shell, everything but that one window hidden.
100 104 $solo_window = openstation_solo_window_id();
@@ -217,11 +221,11 @@
217 221 // plugin-contributed top-level routes. `openstation_dock_placement`
218 222 // is the per-item filter escape hatch for hiding. Shared with the
219 223 // REST menu endpoint so live refreshes (post plugin-activation)
220 224 // produce the same ordering as the boot payload.
221 - $menu_payload = openstation_build_menu_payload();
222 - $dock_items = $menu_payload['dockItems'];
223 - $native_windows = isset( $menu_payload['nativeWindows'] )
225 + $menu_payload = openstation_build_menu_payload();
226 + $dock_items = $menu_payload['dockItems'];
227 + $native_windows = isset( $menu_payload['nativeWindows'] )
224 228 ? $menu_payload['nativeWindows']
225 229 : array();
226 230
227 231 // The BOOT page prints every registry window's template as a real
@@ -329,9 +333,9 @@
329 333 $desktop_theme_row['cssDeferred'] = true;
330 334 }
331 335 }
332 336 unset( $desktop_theme_row );
333 - $desktop_icons = isset( $menu_payload['desktopIcons'] )
337 + $desktop_icons = isset( $menu_payload['desktopIcons'] )
334 338 ? $menu_payload['desktopIcons']
335 339 : array();
336 340
337 341 // Files-on-the-Desktop payload (Phase 0+1). Plugin-registered
@@ -507,9 +511,13 @@
507 511 array(
508 512 'currentPage' => esc_url( $current_page ),
509 513 'currentTitle' => $current_title,
510 514 'currentIcon' => sanitize_html_class( $menu_icon ),
511 - 'adminUrl' => esc_url( admin_url() ),
515 + // `self_admin_url()`: the base a window id is derived from,
516 + // and the URL the shell leaves for on exit. Both want the
517 + // admin the screen is in, which is the network one when the
518 + // network shell screen is what rendered.
519 + 'adminUrl' => esc_url( self_admin_url() ),
512 520 'homeUrl' => esc_url( home_url( '/' ) ),
513 521 // Decoded: the shell assigns this to `window.location`,
514 522 // where `&` would make `_wpnonce` arrive as
515 523 // `amp;_wpnonce` and fail the nonce check.
@@ -570,9 +578,17 @@
570 578 'coreNotices' => openstation_get_core_notices(),
571 579 'pluginNotices' => openstation_get_plugin_notices(),
572 580 'defaultWallpaper' => openstation_get_default_wallpaper(),
573 581 'session' => openstation_get_session( get_current_user_id() ),
574 - 'sessionUrl' => esc_url_raw( rest_url( 'desktop-mode/v1/session' ) ),
582 + // The session route runs in the main site's blog context
583 + // whichever desktop posts to it, so the network screen's
584 + // URL says which session it is addressing — see
585 + // `openstation_rest_session_network()`.
586 + 'sessionUrl' => esc_url_raw(
587 + is_network_admin()
588 + ? add_query_arg( 'network', '1', rest_url( 'desktop-mode/v1/session' ) )
589 + : rest_url( 'desktop-mode/v1/session' )
590 + ),
575 591 'restUrl' => esc_url_raw( rest_url() ),
576 592 'mediaUrl' => esc_url_raw( rest_url( 'wp/v2/media' ) ),
577 593 'dropConfig' => $drop_config,
578 594 'defaultWindowUrl' => esc_url_raw( rest_url( 'desktop-mode/v1/default-window' ) ),
@@ -595,15 +611,8 @@
595 611 // stub `<script>`-injects this URL the first time the user
596 612 // opens the assistant. Picking `.js` vs `.min.js` here keeps
597 613 // the SCRIPT_DEBUG gate server-side, matching iframeBridgeUrl.
598 614 'aiAssistantBundleUrl' => $lazy_bundle_url( 'ai-assistant' ),
599 - // URL of the OS Settings panel lazy bundle. Injected by
600 - // the main bundle's `OsSettings.renderPanel()` stub on
601 - // the user's first Settings open. Holds every section
602 - // renderer + the `<os-*>` components only the panel
603 - // uses, so nothing about Settings ships in
604 - // `desktop.min.js` for users who never open it.
605 - 'osSettingsPanelBundleUrl' => $lazy_bundle_url( 'os-settings-panel' ),
606 615 // URL of the shell-overlays lazy bundle. Pre-loaded by
607 616 // the main bundle after first paint so action-triggered
608 617 // overlays (toast, confirm dialog, context menus) feel
609 618 // instant the first time they fire.
@@ -658,12 +667,29 @@
658 667 // / `openNew()` call (both async); pre-loaded
659 668 // by the shell after first paint when no session is being
660 669 // restored and no `openCurrentPage` will fire.
661 670 'windowSystemBundleUrl' => $lazy_bundle_url( 'window-system' ),
671 + // URL of the lazy phone-layer bundle. Injected by the main
672 + // bundle only when the mode resolves to `mobile`, so a
673 + // desktop never fetches it. `mode` carries the preference
674 + // and breakpoints the first-paint head stamp already used,
675 + // plus the server's default tab-bar pins — see
676 + // `includes/mobile.php`.
677 + 'mobileBundleUrl' => $lazy_bundle_url( 'mobile' ),
678 + 'mode' => openstation_mode_config( get_current_user_id() ),
662 679 // URL of the item-visibility-menu lazy bundle — the
663 680 // right-click "hide from dock / desktop" menu. Injected by
664 681 // the main bundle's loader shim on the first right-click.
665 682 'itemVisibilityMenuBundleUrl' => $lazy_bundle_url( 'item-visibility-menu' ),
683 + // URL of the workspace-wizard lazy bundle — the modal
684 + // behind "Edit this workspace…". Injected by the main
685 + // bundle's loader shim on first open.
686 + 'workspaceWizardBundleUrl' => $lazy_bundle_url( 'workspace-wizard' ),
687 + // Server-side view of the workspace templates, so a plugin
688 + // can add or drop one from PHP. The client merges these
689 + // with its own built-ins by id — see
690 + // `src/workspaces/server-sync.ts`.
691 + 'workspacePresets' => openstation_workspace_presets(),
666 692 // URL of the release-card lazy bundle — the vinyl core-
667 693 // update announcement. Injected by `maybeShowUpdate()` only
668 694 // when a core update is actually pending.
669 695 'releaseCardBundleUrl' => $lazy_bundle_url( 'release-card' ),
@@ -695,38 +721,21 @@
695 721 // Site-wide games kill switch (Extended options). Exposed to
696 722 // every user — the shell skips the challenges Heartbeat
697 723 // channel when the framework is off.
698 724 'gamesEnabled' => openstation_games_enabled(),
699 - // Comments-window AI moderation toggle — surfaced at the
700 - // shell level so the OS Settings → Features tab can render
701 - // the toggle without depending on the Comments window
702 - // being registered for this user. URL is the same
703 - // endpoint the comments-window config exposes; state is
704 - // `null` for non-admins (the UI hides the row entirely).
705 - 'commentsAiUrl' => esc_url_raw( rest_url( 'desktop-mode/v1/comments/ai-settings' ) ),
706 - // Non-null only for admins on a site where the Core AI stack is
707 - // present. Comment scoring routes through the AI Client (WP 7.0+),
708 - // so on older WordPress the whole row is hidden — same as the
709 - // assistant toggle — rather than shown disabled pointing at a
710 - // Settings → Connectors screen that doesn't exist there.
711 - 'commentsAi' => (
712 - current_user_can( 'manage_options' )
713 - && function_exists( 'openstation_ai_is_available' )
714 - && openstation_ai_is_available()
715 - )
716 - ? array(
717 - 'enabled' => function_exists( 'openstation_comments_ai_is_enabled' )
718 - ? openstation_comments_ai_is_enabled()
719 - : false,
720 - 'providerConfigured' => function_exists( 'openstation_comments_ai_provider_configured' )
721 - ? openstation_comments_ai_provider_configured()
722 - : false,
723 - )
724 - : null,
725 725 'currentUserIsAdmin' => current_user_can( 'manage_options' ),
726 + // Null on single-site installs; its `networkAdmin` null
727 + // without `manage_network`, which is what keeps the dock
728 + // tile from registering.
729 + 'multisite' => openstation_multisite_payload(),
726 730 'portalUrl' => esc_url( openstation_portal_url() ),
727 731 'fromPortal' => $from_portal,
728 732 'fromPortalIntent' => $from_portal_intent,
733 + // One-shot like the boot target: a switch from another
734 + // site's overview lands in this one's.
735 + 'landInOverview' => openstation_shell_lands_in_overview(),
736 + 'arrivalDirection' => openstation_shell_arrival_direction(),
737 + 'hopLinkOffer' => function_exists( 'openstation_network_link_offer' ) ? openstation_network_link_offer() : null,
729 738 'pwa' => array(
730 739 'manifestUrl' => esc_url_raw( openstation_pwa_manifest_url() ),
731 740 'swUrl' => esc_url_raw( openstation_pwa_sw_url() ),
732 741 // Extensionless retry target for hosts whose nginx 404s
@@ -731,8 +740,12 @@
731 740 'swUrl' => esc_url_raw( openstation_pwa_sw_url() ),
732 741 // Extensionless retry target for hosts whose nginx 404s
733 742 // virtual .js paths before WordPress runs (WordPress.com).
734 743 'swFallbackUrl' => esc_url_raw( openstation_pwa_sw_fallback_url() ),
744 + // The site's home path — the scope the registration
745 + // asks for, so a subdirectory network's sites each get
746 + // their own worker instead of fighting over the root.
747 + 'swScope' => openstation_pwa_sw_scope(),
735 748 // The worker's per-user flags, computed HERE rather than
736 749 // baked into the served `sw.js`.
737 750 //
738 751 // A service worker is origin-wide but these are per-user
@@ -738,12 +751,11 @@
738 751 // A service worker is origin-wide but these are per-user
739 752 // preferences, so putting them in the script bytes made
740 753 // the body differ between an anonymous and a logged-in
741 754 // request — and any in-scope logged-out navigation then
742 - // installed a "new" worker and tripped the shell's
743 - // `controllerchange` reload. The bytes are identical for
744 - // everyone now; the shell posts these to the worker at
745 - // boot.
755 + // installed a "new" worker, which at the time reloaded
756 + // the shell. The bytes are identical for everyone now;
757 + // the shell posts these to the worker at boot.
746 758 //
747 759 // Computed server-side, not read from the settings
748 760 // snapshot client-side, because
749 761 // `openstation_pwa_admin_asset_cache_enabled()` applies
@@ -752,8 +764,14 @@
752 764 'swConfig' => array(
753 765 'adminAssetCache' => (bool) openstation_pwa_admin_asset_cache_enabled(),
754 766 'windowPrewarm' => ! empty( openstation_get_os_settings( get_current_user_id() )['windowPrewarmEnabled'] ),
755 767 ),
768 + // The build this shell document belongs to. When a new
769 + // worker takes over mid-session the shell asks it for
770 + // the stamp it was served with and compares; only a
771 + // difference — the shell's own files changed on the
772 + // server — offers the user a reload. Never automatic.
773 + 'shellBuild' => openstation_shell_build_stamp(),
756 774 'stateUrl' => esc_url_raw( rest_url( 'desktop-mode/v1/pwa-state' ) ),
757 775 'state' => openstation_pwa_get_user_state( get_current_user_id() ),
758 776 // Mirrors the manifest's `name` field — used by the
759 777 // install pill so the button reads "Install <site>"
@@ -790,19 +808,19 @@
790 808 : array(),
791 809 'deferredStyles' => openstation_build_deferred_styles(
792 810 array_merge(
793 811 array(
794 - 'os-settings',
795 812 'desktop-mode-ai-assistant',
796 813 'desktop-mode-bug-report',
797 - // WP Explorer's sheet. It rides that window as a
798 - // companion style, but the desktop FOLDER window
799 - // paints its preview pane with the same
800 - // `os-my-wordpress__*` classes and — being a
801 - // native window opened straight from JS — carries
802 - // no companion styles of its own. Without this,
803 - // the pane rendered unstyled until WP Explorer
804 - // had been opened once in the session.
814 + // The explorer's shared sheet. It rides the WP
815 + // Explorer APP as a companion style, but the
816 + // desktop FOLDER window paints its preview pane
817 + // with the same `os-my-wordpress__*` classes and
818 + // — being a native window opened straight from
819 + // JS — carries no companion styles of its own.
820 + // Without this, the pane rendered unstyled until
821 + // the explorer had been opened once in the
822 + // session.
805 823 'desktop-mode-my-wordpress',
806 824 ),
807 825 // The Games sheets. They also ride the hub window as
808 826 // companion styles, but a game is reachable without
@@ -955,8 +973,21 @@
955 973 'rel' => 'prefetch',
956 974 ),
957 975 );
958 976
977 + // The phone layer is needed at boot on a phone and never on a
978 + // desktop; the server cannot see the viewport, so the user agent
979 + // decides whether the hint is worth its bytes. A wrong guess costs
980 + // one low-priority fetch, never a wrong layout — the stamp and the
981 + // bundle loader read the real viewport.
982 + if ( openstation_mode_hint_is_mobile( get_current_user_id() ) ) {
983 + $hints[] = array(
984 + 'href' => $build_url( 'assets/js/mobile' . $suffix . '.js' ),
985 + 'as' => 'script',
986 + 'rel' => 'prefetch',
987 + );
988 + }
989 +
959 990 /**
960 991 * Filters the list of resource preload hints emitted in `<head>`.
961 992 *
962 993 * Each entry is a `{ 'href' => string, 'as' => string,
@@ -1073,9 +1104,8 @@
1073 1104 'os-openstation-layout',
1074 1105 'desktop-mode-ai-assistant',
1075 1106 'desktop-mode-bug-report',
1076 1107 'os-window-overview',
1077 - 'os-settings',
1078 1108 )
1079 1109 );
1080 1110
1081 1111 if ( ! in_array( $handle, (array) $deferred, true ) ) {