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
desktop-mode / includes / recycle-bin / window.php

window.php in OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin 1.1.10, at includes/recycle-bin/window.php

204 lines 8.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * OpenStation — Recycle Bin: tile art, gate, shell config.
4 *
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).
15 *
16 * @package OpenStation
17 */
18
19 defined( 'ABSPATH' ) || exit;
20
21 /**
22 * The bin SVG, used by the app window's icon and its dock tile.
23 *
24 * The bin used to be `dashicons-trash`, which worked but wore the
25 * wrong clothes. Dashicons are WP core's icon set: solid fills on a
26 * 20-unit grid, tuned for admin-menu sizes. The shell's own icons are
27 * outlined vessels on a 64-unit grid at stroke 3. Sitting next to
28 * WP Explorer, Corkboard and Games in the dock, the Dashicon was
29 * visibly a guest from another system: heavier, tighter, and drawn to
30 * a different rhythm.
31 *
32 * So this is the same object, redrawn to the house rule the other
33 * three follow: an outlined vessel with solid content, three elements
34 * because it renders as small as 20px in the dock. The lid is the
35 * solid one, which gives the mark a single dense horizontal to be
36 * recognised by when the tapered body below it thins out.
37 *
38 * Drawn in `currentColor`, so `renderIcon()` paints it as a CSS mask
39 * and it takes the surface's own text colour. Dashicons already
40 * inherited colour, being font glyphs; the point of the change is the
41 * drawing, not the theming.
42 *
43 * Note that the row actions inside the bin window, and the "Move to
44 * trash" entries in context menus, stay on `dashicons-trash`. Those
45 * are menu glyphs sitting among other menu glyphs, and they should
46 * match their neighbours rather than this icon.
47 *
48 * The bin has two states. Empty is the vessel on its own; full adds
49 * three crumpled balls inside it and knocks the lid askew.
50 *
51 * @param bool $full Whether to draw the bin holding something.
52 * @return string Raw `<svg>` markup.
53 */
54 function openstation_recycle_bin_icon_svg( $full = false ) {
55 // The lid and the handle travel together. In the full state the
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.
66 $lid_transform = $full
67 ? ' transform="translate(0 -4) rotate(12 52 21.5)"'
68 : '';
69
70 $svg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">'
71 . '<g' . $lid_transform . '>'
72 // The handle, outlined so it reads as a loop rather than a tab.
73 . '<path d="M25 19v-2.5a3.5 3.5 0 0 1 3.5-3.5h7a3.5 3.5 0 0 1 3.5 3.5V19" fill="none" stroke="currentColor" stroke-width="3" stroke-linejoin="round" stroke-linecap="round"/>'
74 // The lid: the one solid element, and the widest, so it anchors
75 // the mark at small sizes.
76 . '<rect x="10" y="19" width="44" height="5" rx="2.5" fill="currentColor"/>'
77 . '</g>'
78 // The body, tapered towards the base the way a real bin is, which
79 // is also what separates it from a plain bucket.
80 //
81 // 27 units tall, narrowing to 71% of its top width. It was 24
82 // tall at 59%, which drew a shallower, more conical tub than a
83 // bin actually is, and left an interior too cramped to hold
84 // anything. Taken further, to a bottom much past 75%, the walls
85 // go vertical and the mark reads as a bucket; this sits at the
86 // edge of that.
87 . '<path d="M15.5 28.5h33l-1.2 24a3.5 3.5 0 0 1-3.5 3H20.2a3.5 3.5 0 0 1-3.5-3z" fill="none" stroke="currentColor" stroke-width="3" stroke-linejoin="round" stroke-linecap="round"/>';
88
89 if ( $full ) {
90 // Three crumpled balls, one path with three subpaths so the
91 // mark stays at four elements rather than six.
92 //
93 // Each is a seven-point polygon on a radius jittered between
94 // 0.81 and 1.0, with a same-colour round-joined stroke that
95 // turns the corners into creases instead of points. Seven
96 // points rather than nine because a ball this small needs
97 // deeper, fewer facets to keep any texture at all.
98 //
99 // The layout is staggered deliberately. Two balls at the same
100 // height with a third centred under them reads as a face, and
101 // it cannot be unseen once noticed, so no two share a y (the
102 // top pair are 4.2 units apart) and the third sits below-left
103 // rather than on the centreline. Every gap in the mark clears
104 // 2 units: 5.1 to the left wall, 4.4 to the right, 2.8 to the
105 // rim, 2.5 to the base, and 2.5 to 4.2 between the balls. Those
106 // last three decide how far down the size ladder they stay
107 // three things instead of one.
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'
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'
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"'
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"/>';
120 }
121
122 return $svg . '</svg>';
123 }
124
125 /**
126 * Both bin states as base64 data URIs, ready for `renderIcon()`.
127 *
128 * The client swaps between these as the count crosses zero, so both
129 * have to reach the page on the first paint. Cheap: two string
130 * builds and two base64 encodes, no queries.
131 *
132 * @return array{empty:string,full:string}
133 */
134 function openstation_recycle_bin_icon_uris() {
135 return array(
136 'empty' => 'data:image/svg+xml;base64,' . base64_encode( openstation_recycle_bin_icon_svg( false ) ),
137 'full' => 'data:image/svg+xml;base64,' . base64_encode( openstation_recycle_bin_icon_svg( true ) ),
138 );
139 }
140
141 /**
142 * Whether the current user should see the recycle bin at all.
143 *
144 * Filterable so plugins can hide it from authors/contributors who
145 * don't manage trash, or invert the gate to expose it to a custom
146 * role. The app's gate (`apps/trash/trash.os.php`) delegates here.
147 *
148 * @return bool
149 */
150 function openstation_recycle_bin_user_can_use() {
151 $can = current_user_can( 'edit_posts' );
152
153 /**
154 * Filter whether the current user can see the recycle bin window.
155 *
156 * @param bool $can Default: edit_posts capability.
157 */
158 return (bool) apply_filters( 'openstation_recycle_bin_user_can_use', $can );
159 }
160
161 /**
162 * Enqueue the bin stylesheet with the shell.
163 *
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.
168 */
169 function openstation_recycle_bin_enqueue_style() {
170 if ( ! openstation_recycle_bin_user_can_use() ) {
171 return;
172 }
173 wp_enqueue_style( 'desktop-mode-recycle-bin' );
174 }
175 add_action( 'admin_enqueue_scripts', 'openstation_recycle_bin_enqueue_style', 5 );
176
177 /**
178 * Inject the initial trash count and both bin drawings into the
179 * shell config, so the dock tile (and any icon a user or plugin has
180 * placed against this window) shows the right one on the very first
181 * paint, before the bin window has ever opened.
182 *
183 * Both drawings travel together rather than the server picking one:
184 * the count changes without a reload, and shipping the pair makes
185 * crossing zero a local swap instead of a round trip.
186 *
187 * @param array $config Shell config blob.
188 * @return array
189 */
190 function openstation_recycle_bin_inject_shell_config( $config ) {
191 if ( ! is_array( $config ) ) {
192 return $config;
193 }
194 $icons = openstation_recycle_bin_icon_uris();
195
196 $config['recycleBinCount'] = openstation_recycle_bin_count();
197 $config['recycleBinCountUrl'] = esc_url_raw( rest_url( 'desktop-mode/v1/recycle-bin/count' ) );
198 $config['recycleBinPostTypes'] = openstation_recycle_bin_capture_post_types();
199 $config['recycleBinIconEmpty'] = $icons['empty'];
200 $config['recycleBinIconFull'] = $icons['full'];
201 return $config;
202 }
203 add_filter( 'openstation_shell_config', 'openstation_recycle_bin_inject_shell_config', 20 );
204