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/recycle-bin/window.php +40 -196 1.1.21.1.10 View file →
@@ -1,23 +1,19 @@
1 1 <?php
2 2 /**
3 - * OpenStation — Recycle Bin: window registration.
3 + * OpenStation — Recycle Bin: tile art, gate, shell config.
4 4 *
5 - * Native window with id `desktop-mode-recycle-bin`, pinned to the dock.
6 - * Like the code editor, the template body is a static skeleton that the
7 - * JS bundle enhances on first open — the table is populated from the
8 - * REST list endpoint at render time.
5 + * The bin WINDOW is an App Framework app (`apps/trash/trash.os.php`)
6 + * that claims the frozen `desktop-mode-recycle-bin` id, so every
7 + * shortcut, dock placement and drop target keeps working. This file
8 + * keeps what the shell needs regardless of the window: the two bin
9 + * drawings (the dock tile's empty/full swap — `icon-state.ts` — and
10 + * the app's own `ctx.host.setIcon()` swap read the same pair), the
11 + * capability gate, the shell-config seed that makes the tile correct
12 + * on the very first paint, and the stylesheet enqueue (the
13 + * drag-to-trash drop-target highlight must exist at boot, not at
14 + * window-open).
9 15 *
10 - * The bin lands on the dock and nowhere else. It used to also register
11 - * a wallpaper icon, which put the same target on two surfaces at once
12 - * and made the desktop something the shell furnished rather than
13 - * something the user did. That is a default, not a rule: the tile is
14 - * `placeable`, so the wallpaper is one pick away in Apps & Plugins.
15 - *
16 - * The registration is filterable via `openstation_recycle_bin_window_args`
17 - * so a plugin can swap the icon, change the dimensions, or restrict who
18 - * sees the bin without touching this file.
19 - *
20 16 * @package OpenStation
21 17 */
22 18
23 19 defined( 'ABSPATH' ) || exit;
@@ -22,9 +18,9 @@
22 18
23 19 defined( 'ABSPATH' ) || exit;
24 20
25 21 /**
26 - * The bin SVG, used by the window icon and its dock tile.
22 + * The bin SVG, used by the app window's icon and its dock tile.
27 23 *
28 24 * The bin used to be `dashicons-trash`, which worked but wore the
29 25 * wrong clothes. Dashicons are WP core's icon set: solid fills on a
30 26 * 20-unit grid, tuned for admin-menu sizes. The shell's own icons are
@@ -49,11 +45,9 @@
49 45 * are menu glyphs sitting among other menu glyphs, and they should
50 46 * match their neighbours rather than this icon.
51 47 *
52 48 * The bin has two states. Empty is the vessel on its own; full adds
53 - * three crumpled balls inside it and knocks the lid askew. See
54 - * {@link openstation_recycle_bin_icon_svg()} for why the lid only
55 - * moves 8 degrees.
49 + * three crumpled balls inside it and knocks the lid askew.
56 50 *
57 51 * @param bool $full Whether to draw the bin holding something.
58 52 * @return string Raw `<svg>` markup.
59 53 */
@@ -58,12 +52,20 @@
58 52 * @return string Raw `<svg>` markup.
59 53 */
60 54 function openstation_recycle_bin_icon_svg( $full = false ) {
61 55 // The lid and the handle travel together. In the full state the
62 - // pair is knocked askew, which is the whole difference at the top
63 - // of the mark.
56 + // pair is lifted clear of the rim and tipped, hinged at the far
57 + // corner, the way a lid sits on a bin that has too much in it.
58 + //
59 + // It was a 2.5-unit lift at 8 degrees, which on the 20px dock
60 + // tile and the 58px home tile was no difference at all: the bin
61 + // read as empty while it held things. At 4 units and 12 degrees
62 + // (a positive angle turns clockwise about the far corner, so the
63 + // near end rises) the lid's near end clears the rim by a fifth
64 + // of the body's height and its far end by nine units, and the
65 + // wedge of light under it survives every size the mark is drawn.
64 66 $lid_transform = $full
65 - ? ' transform="translate(0 -2.5) rotate(8 32 21.5)"'
67 + ? ' transform="translate(0 -4) rotate(12 52 21.5)"'
66 68 : '';
67 69
68 70 $svg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">'
69 71 . '<g' . $lid_transform . '>'
@@ -106,8 +108,16 @@
106 108 $svg .= '<path d="M29.7 38 27.4 39.5 24.7 39.6 23.6 37.1 24.1 34.4 26.8 34.1 29.2 35.1'
107 109 . 'ZM39.4 44.1 36.7 43.5 34.8 41.6 35.8 39.1 38.1 37.6 40.2 39.3 41.1 41.8'
108 110 . 'ZM28.1 50.4 27 47.9 27.4 45.2 30 44.6 32.6 45.6 32.4 48.3 31 50.5Z"'
109 111 . ' fill="currentColor" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round"/>';
112 + // A fourth, larger sheet rides the rim under the lifted end of
113 + // the lid — the one element of the full state that is legible
114 + // at 20px, where the balls inside the body are a texture at
115 + // best. Same seven-point construction, twice the radius,
116 + // straddling the rim (y 28.5) so it reads as spilling out
117 + // rather than sitting in.
118 + $svg .= '<path d="M30 26 27.3 30 22.7 31.7 19.5 28.2 18.6 23.4 22.8 20.7 27.6 21.6Z"'
119 + . ' fill="currentColor" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round"/>';
110 120 }
111 121
112 122 return $svg . '</svg>';
113 123 }
@@ -128,114 +138,13 @@
128 138 );
129 139 }
130 140
131 141 /**
132 - * Echoes the recycle bin window's template body.
133 - *
134 - * The shell wraps this in `<template id="os-native-window-desktop-mode-recycle-bin">`
135 - * and clones it into the window body BEFORE the JS render callback runs.
136 - * The `data-os-recycle-bin-*` hooks below are the contract the JS
137 - * relies on — keep them intact (or rename via the filter) when
138 - * customizing the layout.
139 - */
140 -function openstation_recycle_bin_render_template() {
141 - ob_start();
142 - ?>
143 - <div class="desktop-mode-recycle-bin" data-os-recycle-bin-root>
144 - <header class="os-recycle-bin__toolbar" data-os-recycle-bin-toolbar>
145 - <div class="os-recycle-bin__toolbar-left">
146 - <os-segmented data-os-recycle-bin-filter>
147 - <os-segment value="" selected><?php esc_html_e( 'All', 'desktop-mode' ); ?></os-segment>
148 - <os-segment value="post"><?php esc_html_e( 'Posts', 'desktop-mode' ); ?></os-segment>
149 - <os-segment value="page"><?php esc_html_e( 'Pages', 'desktop-mode' ); ?></os-segment>
150 - <?php
151 - // The Media segment is only useful when WP itself routes
152 - // attachment deletions through Trash. That gate is the
153 - // `MEDIA_TRASH` constant — defaults to false in core, can
154 - // be flipped to true from `wp-config.php`. Without it,
155 - // attachments permanent-delete on first click and the
156 - // Trash bin will never have anything in this bucket, so
157 - // the tab would always read "0" and confuse users.
158 - if ( defined( 'MEDIA_TRASH' ) && MEDIA_TRASH ) :
159 - ?>
160 - <os-segment value="attachment"><?php esc_html_e( 'Media', 'desktop-mode' ); ?></os-segment>
161 - <?php
162 - endif;
163 - ?>
164 - <os-segment value="comment"><?php esc_html_e( 'Comments', 'desktop-mode' ); ?></os-segment>
165 - <os-segment value="desktop"><?php esc_html_e( 'Desktop', 'desktop-mode' ); ?></os-segment>
166 - </os-segmented>
167 - <os-text-field
168 - data-os-recycle-bin-search
169 - placeholder="<?php esc_attr_e( 'Search trash…', 'desktop-mode' ); ?>"
170 - ></os-text-field>
171 - </div>
172 - <div class="os-recycle-bin__toolbar-right" data-os-recycle-bin-bulk hidden>
173 - <span class="os-recycle-bin__count" data-os-recycle-bin-count></span>
174 - <os-button variant="secondary" data-os-recycle-bin-restore-selected>
175 - <span class="dashicons dashicons-image-rotate" aria-hidden="true"></span>
176 - <?php esc_html_e( 'Restore', 'desktop-mode' ); ?>
177 - </os-button>
178 - <os-button variant="secondary" data-os-recycle-bin-pin-to-desktop>
179 - <span class="dashicons dashicons-desktop" aria-hidden="true"></span>
180 - <?php esc_html_e( 'Pin to desktop', 'desktop-mode' ); ?>
181 - </os-button>
182 - <os-button variant="danger" data-os-recycle-bin-purge-selected>
183 - <span class="dashicons dashicons-trash" aria-hidden="true"></span>
184 - <?php esc_html_e( 'Delete forever', 'desktop-mode' ); ?>
185 - </os-button>
186 - </div>
187 - <div class="os-recycle-bin__toolbar-trailing">
188 - <os-button variant="ghost" data-os-recycle-bin-refresh title="<?php esc_attr_e( 'Refresh', 'desktop-mode' ); ?>">
189 - <span class="dashicons dashicons-update" aria-hidden="true"></span>
190 - </os-button>
191 - <os-button variant="danger" data-os-recycle-bin-empty>
192 - <span class="dashicons dashicons-trash" aria-hidden="true"></span>
193 - <?php esc_html_e( 'Empty Trash', 'desktop-mode' ); ?>
194 - </os-button>
195 - </div>
196 - </header>
197 - <div class="os-recycle-bin__body" data-os-recycle-bin-body>
198 - <os-table
199 - data-os-recycle-bin-table
200 - selectable="multi"
201 - sticky-header
202 - hover
203 - striped
204 - loading
205 - >
206 - <div slot="empty" class="os-recycle-bin__empty">
207 - <span class="dashicons dashicons-trash" aria-hidden="true"></span>
208 - <p><?php esc_html_e( 'The Trash is empty.', 'desktop-mode' ); ?></p>
209 - <p class="os-recycle-bin__empty-hint">
210 - <?php esc_html_e( 'Deleted posts, pages, and media show up here. Restoring puts them back where they were.', 'desktop-mode' ); ?>
211 - </p>
212 - </div>
213 - </os-table>
214 - </div>
215 - </div>
216 - <?php
217 - $html = (string) ob_get_clean();
218 -
219 - /**
220 - * Filter the recycle bin window's template HTML.
221 - *
222 - * Keep the `data-os-recycle-bin-*` hooks intact so the JS render
223 - * callback can find its mount points, or rename them and update the
224 - * matching constants in `src/recycle-bin/index.ts`.
225 - *
226 - * @param string $html Default template HTML.
227 - */
228 - $filtered = (string) apply_filters( 'openstation_recycle_bin_template_html', $html );
229 - echo wp_kses( $filtered, openstation_native_window_allowed_html() );
230 -}
231 -
232 -/**
233 142 * Whether the current user should see the recycle bin at all.
234 143 *
235 144 * Filterable so plugins can hide it from authors/contributors who
236 145 * don't manage trash, or invert the gate to expose it to a custom
237 - * role.
146 + * role. The app's gate (`apps/trash/trash.os.php`) delegates here.
238 147 *
239 148 * @return bool
240 149 */
241 150 function openstation_recycle_bin_user_can_use() {
@@ -249,87 +158,22 @@
249 158 return (bool) apply_filters( 'openstation_recycle_bin_user_can_use', $can );
250 159 }
251 160
252 161 /**
253 - * Register the recycle bin window on `init`.
162 + * Enqueue the bin stylesheet with the shell.
254 163 *
255 - * Hooked at priority 20, after `components.php` has bootstrapped the
256 - * native-window registry — same timing as the code editor.
164 + * Not a window-open companion: the sheet also paints the
165 + * drag-to-trash drop-target highlight on the CLOSED bin's dock tile
166 + * (`data-os-trash-drop-active`), which must work before the window
167 + * has ever opened.
257 168 */
258 -function openstation_recycle_bin_register_window() {
169 +function openstation_recycle_bin_enqueue_style() {
259 170 if ( ! openstation_recycle_bin_user_can_use() ) {
260 171 return;
261 172 }
262 -
263 - $icon_uris = openstation_recycle_bin_icon_uris();
264 - $icon_uri = $icon_uris['empty'];
265 -
266 - $window_args = array(
267 - 'title' => __( 'Trash', 'desktop-mode' ),
268 - 'icon' => $icon_uri,
269 - 'template' => 'openstation_recycle_bin_render_template',
270 - 'script' => 'desktop-mode-recycle-bin',
271 - 'width' => 880,
272 - 'height' => 560,
273 - 'min_width' => 520,
274 - 'min_height' => 360,
275 - 'placement' => 'dock',
276 - 'nav_kind' => 'control',
277 - // Last on the rail, after the shell's own cluster (Mio 10,
278 - // Overview 20, System 30). Trash is where things END UP, and a
279 - // dock reads left to right: putting it anywhere but the end
280 - // makes it one more app rather than the bottom of the pile.
281 - 'dock_order' => 40,
282 - // The bin is the one dock tile a user can reasonably not want,
283 - // so it gets a row in Apps & Plugins: dock (the default),
284 - // desktop, both, or hidden. It registers no desktop icon, so
285 - // that row is its only control.
286 - 'placeable' => true,
287 - );
288 -
289 - /**
290 - * Filter the args used to register the recycle bin native window.
291 - *
292 - * @param array $window_args Args passed to `openstation_register_window()`.
293 - */
294 - $window_args = (array) apply_filters( 'openstation_recycle_bin_window_args', $window_args );
295 -
296 - $registered = openstation_register_window( 'desktop-mode-recycle-bin', $window_args );
297 - if ( is_wp_error( $registered ) ) {
298 - // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
299 - error_log( '[openstation] Recycle bin window registration failed: ' . $registered->get_error_message() );
300 - }
301 -}
302 -add_action( 'init', 'openstation_recycle_bin_register_window', 20 );
303 -
304 -/**
305 - * Localize REST endpoints for the JS bundle.
306 - *
307 - * Same pattern as the code editor: the bundle reads its config off
308 - * `window.openStationRecycleBinConfig` and never hardcodes URLs.
309 - */
310 -function openstation_recycle_bin_localize_config() {
311 - if ( ! openstation_recycle_bin_user_can_use() ) {
312 - return;
313 - }
314 -
315 - wp_localize_script(
316 - 'desktop-mode-recycle-bin',
317 - 'openStationRecycleBinConfig',
318 - array(
319 - 'restNonce' => wp_create_nonce( 'wp_rest' ),
320 - 'listUrl' => esc_url_raw( rest_url( 'desktop-mode/v1/recycle-bin' ) ),
321 - 'restoreUrl' => esc_url_raw( rest_url( 'desktop-mode/v1/recycle-bin/restore' ) ),
322 - 'purgeUrl' => esc_url_raw( rest_url( 'desktop-mode/v1/recycle-bin/purge' ) ),
323 - 'emptyUrl' => esc_url_raw( rest_url( 'desktop-mode/v1/recycle-bin/empty' ) ),
324 - 'countUrl' => esc_url_raw( rest_url( 'desktop-mode/v1/recycle-bin/count' ) ),
325 - 'postTypes' => openstation_recycle_bin_capture_post_types(),
326 - )
327 - );
328 -
329 173 wp_enqueue_style( 'desktop-mode-recycle-bin' );
330 174 }
331 -add_action( 'admin_enqueue_scripts', 'openstation_recycle_bin_localize_config', 30 );
175 +add_action( 'admin_enqueue_scripts', 'openstation_recycle_bin_enqueue_style', 5 );
332 176
333 177 /**
334 178 * Inject the initial trash count and both bin drawings into the
335 179 * shell config, so the dock tile (and any icon a user or plugin has