PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 1.1.13
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v1.1.13
1.1.13 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 All 37 releases
← All changes | includes/os-settings.php +122 -27 1.1.4 → 1.1.13 View file →
@@ -30,8 +30,11 @@
30 30
31 31 /** Valid window-radius IDs — mirrors the TS `WINDOW_RADII` constant. */
32 32 const OPENSTATION_OS_SETTINGS_WINDOW_RADII = array( 'sharp', 'default', 'round' );
33 33
34 +/** How a newly opened window lands — mirrors the TS `OPEN_WINDOWS_AS` constant. */
35 +const OPENSTATION_OS_SETTINGS_OPEN_WINDOWS_AS = array( 'default', 'maximized', 'focused' );
36 +
34 37 /**
35 38 * Valid admin-bar mode IDs — mirrors the TS `ADMIN_BAR_MODES` constant.
36 39 *
37 40 * `static` keeps the WordPress admin bar pinned above the shell (the
@@ -62,8 +65,18 @@
62 65 */
63 66 const OPENSTATION_OS_SETTINGS_DOCK_BEHAVIORS = array( 'static', 'dynamic' );
64 67
65 68 /**
69 + * `mobileLayout` — which experience the shell renders. `auto`
70 + * follows the viewport; the other two force it either way.
71 + * Mirrors `OsModePreference` in `src/mode/index.ts`.
72 + */
73 +const OPENSTATION_OS_SETTINGS_MOBILE_LAYOUTS = array( 'auto', 'desktop', 'mobile' );
74 +
75 +/** `mobileTabs` — at most this many ids pinned to the phone tab bar. */
76 +const OPENSTATION_OS_SETTINGS_MOBILE_TABS_MAX = 3;
77 +
78 +/**
66 79 * Playable range for the window-reveal duration override, in ms.
67 80 * Mirrors `MIN_REVEAL_DURATION_MS` / `MAX_REVEAL_DURATION_MS` in
68 81 * `src/reveals/registry.ts`.
69 82 *
@@ -83,8 +96,10 @@
83 96 */
84 97 function openstation_default_os_settings() {
85 98 return array(
86 99 'wallpaper' => 'galaxy',
100 + // Pulse, the brand's signature. Mirrors `DEFAULTS` in
101 + // `src/settings/constants.ts`.
87 102 'accent' => 'pulse',
88 103 // Only read when `accent` is `custom`. Seeded with Pulse so
89 104 // picking Custom before touching the wheel is a no-op rather
90 105 // than a jump to black. Mirrors `DEFAULTS` in
@@ -98,8 +113,9 @@
98 113 // `src/settings/constants.ts` — PHP seeds the first load and JS
99 114 // owns every paint after it, so a mismatch shows up as the
100 115 // corners changing shape a moment after the shell boots.
101 116 'windowRadius' => 'round',
117 + 'openWindowsAs' => 'default',
102 118 // How the WordPress admin bar presents above the shell.
103 119 // `hidden` ships as the default so a fresh desktop has ONE
104 120 // navigation surface: everything the user can open lives on the
105 121 // dock, and the dock's "Exit OpenStation" tile is the way back
@@ -200,8 +216,13 @@
200 216 // window (e.g. array( 'author', 'tags' )). Empty array means
201 217 // every column is visible. The sticky 'title' column is always
202 218 // shown — the UI prevents toggling it.
203 219 'nativePostsHiddenColumns' => array(),
220 + // Per-user list of column keys hidden in the native Pages
221 + // window (e.g. array( 'author', 'parent' )). Empty array means
222 + // every column is visible. The sticky 'title' column is always
223 + // shown — the UI prevents toggling it.
224 + 'nativePagesHiddenColumns' => array(),
204 225 // Per-user opt-IN for the native Pages window. Same posture as
205 226 // nativePostsEnabled — defaults OFF (Beta), users opt in to swap
206 227 // the classic `edit.php?post_type=page` iframe for the native UI.
207 228 'nativePagesEnabled' => false,
@@ -224,21 +245,11 @@
224 245 // (including any custom dashboard a plugin builds there) opens
225 246 // as a chromeless iframe until the user opts in via OS
226 247 // Settings → Features → Beta features.
227 248 'stationHomeEnabled' => false,
228 - // Per-user opt-IN for the service worker's shared admin-asset
229 - // cache (Experimental). Defaults OFF. The value feeds the
230 - // `openstation_pwa_admin_asset_cache` filter's default via
231 - // `openstation_pwa_admin_asset_cache_enabled()` and reaches the
232 - // SW inside the served `sw.js` bytes, so a change applies via a
233 - // normal SW update on the user's next reload.
234 - 'adminAssetCacheEnabled' => false,
235 - // Per-user opt-IN for hover-intent window prewarming
236 - // (Experimental). Defaults OFF. When on, a sustained mouse
237 - // hover on a dock tile speculatively builds that page's window
238 - // hidden so it appears already rendered on click. Read live by
239 - // the dock JS; no server-side behavior attaches to it.
240 - 'windowPrewarmEnabled' => false,
249 + // Performance enhancements are enabled unless explicitly disabled.
250 + 'adminAssetCacheEnabled' => true,
251 + 'windowPrewarmEnabled' => true,
241 252 // When true, left-clicking the empty wallpaper triggers the
242 253 // "Show desktop" toggle (macOS-style) and the matching entry is
243 254 // hidden from the wallpaper context menu. When false (default),
244 255 // the entry stays in the menu and left clicks on the wallpaper
@@ -243,13 +254,20 @@
243 254 // hidden from the wallpaper context menu. When false (default),
244 255 // the entry stays in the menu and left clicks on the wallpaper
245 256 // do nothing. Per-user.
246 257 'showDesktopOnWallpaperClick' => false,
258 + // Whether the close-all-windows shortcut (Alt+Cmd/Ctrl+W) asks
259 + // before it closes. The dialog's "Don't ask again" checkbox is
260 + // what writes false; OpenStation Preferences -> Windows is what
261 + // turns it back on. Per-user.
262 + 'confirmCloseAllWindows' => true,
247 263 // Mio — a soft-body companion that floats over
248 264 // the wallpaper, settles onto nearby windows, and watches the
249 265 // pointer. Off by default; toggled from the wallpaper context
250 266 // menu. Per-user. See `docs/mio.md`.
251 267 'mioEnabled' => false,
268 + 'mioApiEnabled' => false,
269 + 'mioShowOnWallpaper' => true,
252 270 // The user's own Mio, as built in "Make it yours": partial
253 271 // appearance + silhouette overrides, both empty until they
254 272 // touch a control. Stored per user rather than per browser
255 273 // because it is a preference about the person — ten minutes
@@ -300,8 +318,14 @@
300 318 // Per-user ordering, flat across every dock/sidebar zone. Ids
301 319 // not in the list keep their registration order and render
302 320 // after the listed ones. Unknown ids are tolerated.
303 321 'navOrder' => array(),
322 + // Which experience the shell renders: 'auto' follows the
323 + // viewport, 'desktop' / 'mobile' force it. See `includes/mobile.php`.
324 + 'mobileLayout' => 'auto',
325 + // Ids pinned to the phone tab bar, at most three. Empty means
326 + // the server default (`openstation_mobile_tab_bar`).
327 + 'mobileTabs' => array(),
304 328 // Persisted desktop position for every item the user has
305 329 // promoted to the wallpaper via `navPlacement[id]=desktop|both`.
306 330 // Keyed by item id, value is `{ x: int, y: int }`. The JS
307 331 // synthesizer reads this when building a synthetic placement so
@@ -322,14 +346,14 @@
322 346 */
323 347 function openstation_get_os_settings( $user_id ) {
324 348 $user_id = (int) $user_id;
325 349 if ( $user_id <= 0 ) {
326 - return openstation_default_os_settings();
350 + return openstation_sanitize_os_settings( array() );
327 351 }
328 352
329 353 $raw = get_user_meta( $user_id, OPENSTATION_OS_SETTINGS_META_KEY, true );
330 354 if ( ! is_array( $raw ) ) {
331 - return openstation_default_os_settings();
355 + return openstation_sanitize_os_settings( array() );
332 356 }
333 357
334 358 return openstation_sanitize_os_settings( $raw );
335 359 }
@@ -432,16 +456,22 @@
432 456 function openstation_sanitize_os_settings( $raw ) {
433 457 $defaults = openstation_default_os_settings();
434 458
435 459 if ( ! is_array( $raw ) ) {
436 - return $defaults;
460 + $raw = array();
437 461 }
438 462
439 463 // Wallpaper — any non-empty string; registry membership is validated
440 464 // client-side at apply time.
441 - $wallpaper = isset( $raw['wallpaper'] ) && is_string( $raw['wallpaper'] ) && '' !== $raw['wallpaper']
442 - ? sanitize_key( $raw['wallpaper'] )
443 - : $defaults['wallpaper'];
465 + // Key-clean per `/` segment: a desktop theme's wallpapers are
466 + // registered as `desktop-theme/<theme>/<id>`, and a flat
467 + // `sanitize_key()` would fold that into an id nothing answers to.
468 + $wallpaper = isset( $raw['wallpaper'] ) && is_string( $raw['wallpaper'] )
469 + ? implode( '/', array_filter( array_map( 'sanitize_key', explode( '/', $raw['wallpaper'] ) ) ) )
470 + : '';
471 + if ( '' === $wallpaper ) {
472 + $wallpaper = $defaults['wallpaper'];
473 + }
444 474
445 475 // Accent — non-empty string; swatch validity is enforced in the picker.
446 476 $accent = isset( $raw['accent'] ) && is_string( $raw['accent'] ) && '' !== $raw['accent']
447 477 ? sanitize_key( $raw['accent'] )
@@ -466,8 +496,13 @@
466 496 $window_radius = isset( $raw['windowRadius'] ) && in_array( $raw['windowRadius'], OPENSTATION_OS_SETTINGS_WINDOW_RADII, true )
467 497 ? (string) $raw['windowRadius']
468 498 : $defaults['windowRadius'];
469 499
500 + // How a newly opened window lands — one of the three known values.
501 + $open_windows_as = isset( $raw['openWindowsAs'] ) && in_array( $raw['openWindowsAs'], OPENSTATION_OS_SETTINGS_OPEN_WINDOWS_AS, true )
502 + ? (string) $raw['openWindowsAs']
503 + : $defaults['openWindowsAs'];
504 +
470 505 // Admin-bar mode — must be one of the three known values.
471 506 $admin_bar_mode = isset( $raw['adminBarMode'] )
472 507 && in_array( $raw['adminBarMode'], OPENSTATION_OS_SETTINGS_ADMIN_BAR_MODES, true )
473 508 ? (string) $raw['adminBarMode']
@@ -765,8 +800,27 @@
765 800 // user meta indefinitely.
766 801 $native_posts_hidden_columns = array_slice( array_values( array_unique( $native_posts_hidden_columns ) ), 0, 32 );
767 802 }
768 803
804 + $native_pages_hidden_columns = $defaults['nativePagesHiddenColumns'];
805 + if ( isset( $raw['nativePagesHiddenColumns'] ) && is_array( $raw['nativePagesHiddenColumns'] ) ) {
806 + $native_pages_hidden_columns = array();
807 + foreach ( $raw['nativePagesHiddenColumns'] as $col ) {
808 + if ( ! is_string( $col ) || '' === $col ) {
809 + continue;
810 + }
811 + $slug = sanitize_key( $col );
812 + if ( '' === $slug ) {
813 + continue;
814 + }
815 + $native_pages_hidden_columns[] = $slug;
816 + }
817 + // Cap to a sane upper bound — far more than any plausible
818 + // column count, but blocks a malicious payload from bloating
819 + // user meta indefinitely.
820 + $native_pages_hidden_columns = array_slice( array_values( array_unique( $native_pages_hidden_columns ) ), 0, 32 );
821 + }
822 +
769 823 $native_pages_enabled = isset( $raw['nativePagesEnabled'] )
770 824 ? (bool) $raw['nativePagesEnabled']
771 825 : $defaults['nativePagesEnabled'];
772 826
@@ -785,23 +839,25 @@
785 839 $station_home_enabled = isset( $raw['stationHomeEnabled'] )
786 840 ? (bool) $raw['stationHomeEnabled']
787 841 : $defaults['stationHomeEnabled'];
788 842
789 - $admin_asset_cache_enabled = isset( $raw['adminAssetCacheEnabled'] )
790 - ? (bool) $raw['adminAssetCacheEnabled']
791 - : $defaults['adminAssetCacheEnabled'];
843 + // Site-wide performance controls supersede the legacy per-user values.
844 + // Keep the snapshot keys so existing window consumers can read them.
845 + $extended_options = openstation_get_extended_options();
846 + $admin_asset_cache_enabled = $extended_options['admin_asset_cache'];
847 + $window_prewarm_enabled = $extended_options['window_prewarm'];
792 848
793 - $window_prewarm_enabled = isset( $raw['windowPrewarmEnabled'] )
794 - ? (bool) $raw['windowPrewarmEnabled']
795 - : $defaults['windowPrewarmEnabled'];
796 -
797 849 $show_desktop_on_wallpaper_click = isset( $raw['showDesktopOnWallpaperClick'] )
798 850 ? (bool) $raw['showDesktopOnWallpaperClick']
799 851 : $defaults['showDesktopOnWallpaperClick'];
800 852
853 + $confirm_close_all_windows = isset( $raw['confirmCloseAllWindows'] )
854 + ? (bool) $raw['confirmCloseAllWindows']
855 + : $defaults['confirmCloseAllWindows'];
856 +
801 857 $mio_enabled = isset( $raw['mioEnabled'] )
802 858 ? (bool) $raw['mioEnabled']
803 - : $defaults['mioEnabled'];
859 + : ( isset( $raw['mioApiEnabled'] ) ? (bool) $raw['mioApiEnabled'] : $defaults['mioEnabled'] );
804 860
805 861 // A missing key means "no look saved yet", which sanitizes to the
806 862 // same pair of empty arrays the defaults carry — so this needs no
807 863 // isset() branch of its own.
@@ -816,8 +872,35 @@
816 872 $developer_mode_enabled = isset( $raw['developerModeEnabled'] )
817 873 ? (bool) $raw['developerModeEnabled']
818 874 : $defaults['developerModeEnabled'];
819 875
876 + // mobileLayout — the phone/desktop override.
877 + $mobile_layout = isset( $raw['mobileLayout'] )
878 + && in_array( $raw['mobileLayout'], OPENSTATION_OS_SETTINGS_MOBILE_LAYOUTS, true )
879 + ? (string) $raw['mobileLayout']
880 + : $defaults['mobileLayout'];
881 +
882 + // mobileTabs — ordered nav ids pinned to the phone tab bar. Same
883 + // id grammar as navOrder, capped at the tab bar's slot count.
884 + $mobile_tabs = array();
885 + if ( isset( $raw['mobileTabs'] ) && is_array( $raw['mobileTabs'] ) ) {
886 + $seen_tabs = array();
887 + foreach ( $raw['mobileTabs'] as $id ) {
888 + if ( ! is_string( $id ) || '' === $id ) {
889 + continue;
890 + }
891 + $slug = sanitize_key( openstation_canonical_nav_id( $id ) );
892 + if ( '' === $slug || isset( $seen_tabs[ $slug ] ) ) {
893 + continue;
894 + }
895 + $seen_tabs[ $slug ] = true;
896 + $mobile_tabs[] = $slug;
897 + if ( count( $mobile_tabs ) >= OPENSTATION_OS_SETTINGS_MOBILE_TABS_MAX ) {
898 + break;
899 + }
900 + }
901 + }
902 +
820 903 $folders_sharing_enabled = isset( $raw['foldersSharingEnabled'] )
821 904 ? (bool) $raw['foldersSharingEnabled']
822 905 : $defaults['foldersSharingEnabled'];
823 906
@@ -935,8 +1018,9 @@
935 1018 'accent' => $accent,
936 1019 'customAccent' => $custom_accent,
937 1020 'dockSize' => $dock_size,
938 1021 'windowRadius' => $window_radius,
1022 + 'openWindowsAs' => $open_windows_as,
939 1023 'adminBarMode' => $admin_bar_mode,
940 1024 'desktopLayout' => $desktop_layout,
941 1025 'dockPlacement' => $dock_placement,
942 1026 'dockBehavior' => $dock_behavior,
@@ -960,8 +1044,9 @@
960 1044 'heartbeatRate' => $heartbeat_rate,
961 1045 'nativePostsEnabled' => $native_posts_enabled,
962 1046 'nativePostsHiddenColumns' => $native_posts_hidden_columns,
963 1047 'nativePagesEnabled' => $native_pages_enabled,
1048 + 'nativePagesHiddenColumns' => $native_pages_hidden_columns,
964 1049 'nativeUsersEnabled' => $native_users_enabled,
965 1050 'nativePluginsEnabled' => $native_plugins_enabled,
966 1051 'nativeCommentsEnabled' => $native_comments_enabled,
967 1052 'stationHomeEnabled' => $station_home_enabled,
@@ -967,9 +1052,12 @@
967 1052 'stationHomeEnabled' => $station_home_enabled,
968 1053 'adminAssetCacheEnabled' => $admin_asset_cache_enabled,
969 1054 'windowPrewarmEnabled' => $window_prewarm_enabled,
970 1055 'showDesktopOnWallpaperClick' => $show_desktop_on_wallpaper_click,
1056 + 'confirmCloseAllWindows' => $confirm_close_all_windows,
971 1057 'mioEnabled' => $mio_enabled,
1058 + 'mioApiEnabled' => $mio_enabled,
1059 + 'mioShowOnWallpaper' => isset( $raw['mioShowOnWallpaper'] ) ? (bool) $raw['mioShowOnWallpaper'] : $defaults['mioShowOnWallpaper'],
972 1060 'mioStyle' => $mio_style,
973 1061 'showPostStatusRibbons' => $show_post_status_ribbons,
974 1062 'developerModeEnabled' => $developer_mode_enabled,
975 1063 'foldersSharingEnabled' => $folders_sharing_enabled,
@@ -974,8 +1062,10 @@
974 1062 'developerModeEnabled' => $developer_mode_enabled,
975 1063 'foldersSharingEnabled' => $folders_sharing_enabled,
976 1064 'navPlacement' => $nav_placement,
977 1065 'navOrder' => $nav_order,
1066 + 'mobileLayout' => $mobile_layout,
1067 + 'mobileTabs' => $mobile_tabs,
978 1068 'dockPromotedPositions' => $dock_promoted_positions,
979 1069 );
980 1070 }
981 1071
@@ -1075,8 +1165,13 @@
1075 1165 // true of every path into this handler, not just the ones the
1076 1166 // schema happens to guard.
1077 1167 if ( ! is_array( $payload ) ) {
1078 1168 return rest_ensure_response( openstation_get_os_settings( $user_id ) );
1169 + }
1170 +
1171 + // Normalize an alias-only patch before merging it with the saved master value.
1172 + if ( ! array_key_exists( 'mioEnabled', $payload ) && array_key_exists( 'mioApiEnabled', $payload ) ) {
1173 + $payload['mioEnabled'] = $payload['mioApiEnabled'];
1079 1174 }
1080 1175
1081 1176 openstation_save_os_settings(
1082 1177 $user_id,