PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 1.1.11
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v1.1.11
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 0.8.8 All 35 releases
desktop-mode / includes / admin-bar.php

admin-bar.php in OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin 1.1.11, at includes/admin-bar.php

268 lines 9.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * OpenStation admin-bar toggle.
4 *
5 * Adds the "Switch to OpenStation" button to the admin bar's top-right
6 * area and wires its click handler to the save-openstation AJAX endpoint.
7 *
8 * The button is the way INTO the shell and only shows in classic admin.
9 * Inside the shell the admin bar carries no OpenStation nodes at all:
10 * everything the desktop offers is reachable from the dock, and the way
11 * back out is the locked "Exit OpenStation" tile.
12 *
13 * This file also publishes the `openStationAdminBar` config global,
14 * which the shell reads for the exit tile's AJAX call
15 * (`src/exit-openstation.ts`) and the keyboard-shortcuts window
16 * (`src/shortcuts.ts`). It is emitted on every admin screen, with or
17 * without the toggle node.
18 *
19 * @package OpenStation
20 */
21
22 defined( 'ABSPATH' ) || exit;
23
24 /**
25 * Adds the OpenStation toggle to the admin bar.
26 *
27 * Only in classic admin. Once the user is viewing the shell the node
28 * would be a second way to do what the "Exit OpenStation" dock tile
29 * already does, and an admin bar carrying shell controls reads as the
30 * shell's own toolbar when it is not one.
31 *
32 * @param WP_Admin_Bar $wp_admin_bar The WP_Admin_Bar instance.
33 */
34 function openstation_admin_bar_toggle( $wp_admin_bar ) {
35 if ( ! is_admin() || ! is_user_logged_in() ) {
36 return;
37 }
38
39 // "Active" means "the user is *currently viewing* OpenStation", not
40 // "the preference is enabled in user meta." These diverge on requests
41 // carrying the per-request classic override (`?desktop_mode_classic=1`):
42 // the user's meta may be '1' but the page they're looking at right now
43 // is classic admin, and it needs the way back in.
44 if ( openstation_is_enabled() && ! openstation_is_classic_request() ) {
45 return;
46 }
47
48 $label = __( 'Switch to OpenStation', 'desktop-mode' );
49
50 $wp_admin_bar->add_node(
51 array(
52 'parent' => 'top-secondary',
53 'id' => 'os-toggle',
54 'title' => '<span class="ab-icon dashicons dashicons-desktop" aria-hidden="true"></span>'
55 . '<span class="ab-label">' . $label . '</span>',
56 'href' => '#',
57 'meta' => array(
58 'tabindex' => 0,
59 'title' => $label,
60 ),
61 )
62 );
63 }
64 add_action( 'admin_bar_menu', 'openstation_admin_bar_toggle', 190 );
65
66 /**
67 * Enqueues the CSS and JS for the OpenStation toggle.
68 *
69 * The CSS is inline, attached to the `admin-bar` style handle so it always
70 * ships with the admin bar itself — no matter which admin screen is showing.
71 * The JS is the external assets/js/admin-bar.js bundle, registered as
72 * `os-admin-bar` with `admin-bar` as a dependency; its config is
73 * emitted as an inline JSON literal `before` the script.
74 */
75 function openstation_enqueue_toggle_assets() {
76 if ( ! is_admin() || ! is_user_logged_in() ) {
77 return;
78 }
79
80 // Inside a chromeless window the admin bar is suppressed outright
81 // (`show_admin_bar` + the `wp_admin_bar_render` removal in
82 // helpers.php), so `#wpadminbar` never reaches the DOM. Every byte
83 // below — the toggle bundle, its inline config, the node styling —
84 // would load and run against markup that does not exist. See
85 // `includes/render/chromeless-trim.php`, which drops the rest of
86 // that family (core's `admin-bar`, host masterbar extras) for the
87 // same reason.
88 if ( openstation_is_chromeless_request() ) {
89 return;
90 }
91
92 // The item is `display: flex`, never `inline-flex`. An
93 // inline-level box sits on a line box the <li> lays out at its
94 // 32px line-height and aligns on the baseline, so the line grows
95 // by the descender: the item became 37px inside a 32px bar. Under
96 // Core's float layout that overflow was invisible. On a host that
97 // lays the secondary group out as a flex row (WordPress.com's Debug
98 // Bar does, to order its own item first) every sibling stretched
99 // to the tallest one and the group's background painted 5px into
100 // the shell, under the windows' title bars. Block-level, the item
101 // is exactly the bar. `Tests_OpenStation_AdminBarDesktopToggle`
102 // pins it; `desktop.css` caps the group as well, for items we do
103 // not own.
104 $css = '
105 #wpadminbar #wp-admin-bar-os-toggle > .ab-item {
106 display: flex;
107 align-items: center;
108 gap: 6px;
109 }
110 #wpadminbar #wp-admin-bar-os-toggle .ab-icon {
111 float: none;
112 margin: 0;
113 padding: 0;
114 display: inline-flex;
115 align-items: center;
116 justify-content: center;
117 width: 20px;
118 height: 20px;
119 }
120 #wp-admin-bar-os-toggle .ab-icon.dashicons {
121 font: normal 20px/1 dashicons;
122 -webkit-font-smoothing: antialiased;
123 -moz-osx-font-smoothing: grayscale;
124 }
125 #wp-admin-bar-os-toggle .ab-icon.dashicons::before {
126 content: "\f472";
127 top: 0;
128 position: static;
129 }
130 @media screen and (max-width: 782px) {
131 /* WP core hides most admin-bar items on mobile. Force the toggle to
132 stay visible so users can switch back to OpenStation/Classic. */
133 #wpadminbar #wp-admin-bar-os-toggle {
134 display: block;
135 }
136 #wpadminbar #wp-admin-bar-os-toggle > .ab-item {
137 padding: 0 14px;
138 }
139 #wpadminbar #wp-admin-bar-os-toggle .ab-label {
140 display: none;
141 }
142 }
143 ';
144 wp_add_inline_style( 'admin-bar', $css );
145
146 // All PHP→JS values are emitted as JSON literals (never interpolated
147 // raw into the script body) so special characters, quotes, and
148 // unexpected shapes can't break the parser or be exploited.
149 //
150 // The config is emitted on every admin screen, including the ones
151 // where the toggle node is absent: the shell reads the same global
152 // for the "Exit OpenStation" tile's AJAX call and for the
153 // keyboard-shortcuts window.
154 wp_register_script(
155 'os-admin-bar',
156 OPENSTATION_URL . 'assets/js/admin-bar.js',
157 array( 'admin-bar' ),
158 OPENSTATION_VERSION,
159 true
160 );
161 // Emit the config as a JSON literal via wp_add_inline_script, not
162 // wp_localize_script — the latter casts every value to a string,
163 // so `network` would arrive as '' / '1'. 'before' runs ahead of
164 // admin-bar.js so the global is ready when the IIFE fires.
165 wp_add_inline_script(
166 'os-admin-bar',
167 'var openStationAdminBar = ' . wp_json_encode(
168 array(
169 'nonce' => wp_create_nonce( 'save-openstation' ),
170 // `self_admin_url()`: switching off from the network
171 // admin returns there, not to the main site.
172 'classicUrl' => esc_url_raw( self_admin_url() ),
173 'portalUrl' => esc_url_raw( openstation_portal_url() ),
174 // Passed back on the enable / disable AJAX call: the
175 // handler runs on `admin-ajax.php`, where
176 // `is_network_admin()` is always false.
177 'network' => is_network_admin(),
178 'ajaxUrl' => esc_url_raw( admin_url( 'admin-ajax.php' ) ),
179
180 /*
181 * Keyboard-shortcuts reference content. Translated once
182 * on the server and read by `src/shortcuts.ts`, which
183 * renders the Keyboard shortcuts window.
184 *
185 * `contextual` is a small table that distinguishes the
186 * three modes the shortcuts operate in (Outside
187 * Workspaces, Inside Workspaces, Show Desktop).
188 * `general` is a flat list for shortcuts whose
189 * behaviour doesn't shift by mode.
190 */
191 'shortcuts' => array(
192 'title' => __( 'Keyboard shortcuts', 'desktop-mode' ),
193 'contextual' => array(
194 'heading' => __( 'Workspaces', 'desktop-mode' ),
195 'headers' => array(
196 'key' => __( 'Key', 'desktop-mode' ),
197 'outside' => __( 'Outside Workspaces', 'desktop-mode' ),
198 'inside' => __( 'Inside Workspaces', 'desktop-mode' ),
199 'showDesktop' => __( 'In Show Desktop', 'desktop-mode' ),
200 ),
201 'rows' => array(
202 array(
203 'keys' => array( '' ),
204 'outside' => __( 'Previous workspace (wraps)', 'desktop-mode' ),
205 'inside' => __( 'Previous workspace (grid + top-bar update)', 'desktop-mode' ),
206 'showDesktop' => __( 'Previous workspace', 'desktop-mode' ),
207 ),
208 array(
209 'keys' => array( '' ),
210 'outside' => __( 'Next workspace (wraps)', 'desktop-mode' ),
211 'inside' => __( 'Next workspace (grid + top-bar update)', 'desktop-mode' ),
212 'showDesktop' => __( 'Next workspace', 'desktop-mode' ),
213 ),
214 array(
215 'keys' => array( '' ),
216 'outside' => __( 'Enter Workspaces', 'desktop-mode' ),
217 'inside' => __( 'Exit onto the active workspace', 'desktop-mode' ),
218 'showDesktop' => __( 'Restore windows (exit Show Desktop)', 'desktop-mode' ),
219 ),
220 array(
221 'keys' => array( '' ),
222 'outside' => __( 'Toggle Show Desktop', 'desktop-mode' ),
223 'inside' => __( 'Exit Workspaces (no minimize)', 'desktop-mode' ),
224 'showDesktop' => __( 'Toggle Show Desktop', 'desktop-mode' ),
225 ),
226 array(
227 'keys' => array( 'Enter' ),
228 'note' => __( '(in Workspaces)', 'desktop-mode' ),
229 'outside' => '',
230 'inside' => __( 'Commit current workspace, exit Workspaces', 'desktop-mode' ),
231 'showDesktop' => '',
232 ),
233 ),
234 ),
235 'general' => array(
236 'heading' => __( 'Windows & palette', 'desktop-mode' ),
237 'items' => array(
238 array(
239 'keys' => array( '`' ),
240 'description' => __( 'Cycle to the next window on the active workspace.', 'desktop-mode' ),
241 ),
242 array(
243 'keys' => array( 'Shift', '`' ),
244 'description' => __( 'Cycle to the previous window on the active workspace.', 'desktop-mode' ),
245 ),
246 array(
247 'keys' => array( '⌘/Ctrl', 'K' ),
248 'description' => __( 'Open the command palette / Ask AI overlay.', 'desktop-mode' ),
249 ),
250 array(
251 'keys' => array( '⌥/Alt', '⌘/Ctrl', 'W' ),
252 'description' => __( 'Close every open window on the current workspace (asks first).', 'desktop-mode' ),
253 ),
254 array(
255 'keys' => array( 'Esc' ),
256 'description' => __( 'Exit Workspaces (or Snap Overview) without changing window state.', 'desktop-mode' ),
257 ),
258 ),
259 ),
260 ),
261 )
262 ) . ';',
263 'before'
264 );
265 wp_enqueue_script( 'os-admin-bar' );
266 }
267 add_action( 'admin_enqueue_scripts', 'openstation_enqueue_toggle_assets' );
268