` markup. */ function openstation_recycle_bin_icon_svg( $full = false ) { // The lid and the handle travel together. In the full state the // pair is lifted clear of the rim and tipped, hinged at the far // corner, the way a lid sits on a bin that has too much in it. // // It was a 2.5-unit lift at 8 degrees, which on the 20px dock // tile and the 58px home tile was no difference at all: the bin // read as empty while it held things. At 4 units and 12 degrees // (a positive angle turns clockwise about the far corner, so the // near end rises) the lid's near end clears the rim by a fifth // of the body's height and its far end by nine units, and the // wedge of light under it survives every size the mark is drawn. $lid_transform = $full ? ' transform="translate(0 -4) rotate(12 52 21.5)"' : ''; $svg = '' . '' // The handle, outlined so it reads as a loop rather than a tab. . '' // The lid: the one solid element, and the widest, so it anchors // the mark at small sizes. . '' . '' // The body, tapered towards the base the way a real bin is, which // is also what separates it from a plain bucket. // // 27 units tall, narrowing to 71% of its top width. It was 24 // tall at 59%, which drew a shallower, more conical tub than a // bin actually is, and left an interior too cramped to hold // anything. Taken further, to a bottom much past 75%, the walls // go vertical and the mark reads as a bucket; this sits at the // edge of that. . ''; if ( $full ) { // Three crumpled balls, one path with three subpaths so the // mark stays at four elements rather than six. // // Each is a seven-point polygon on a radius jittered between // 0.81 and 1.0, with a same-colour round-joined stroke that // turns the corners into creases instead of points. Seven // points rather than nine because a ball this small needs // deeper, fewer facets to keep any texture at all. // // The layout is staggered deliberately. Two balls at the same // height with a third centred under them reads as a face, and // it cannot be unseen once noticed, so no two share a y (the // top pair are 4.2 units apart) and the third sits below-left // rather than on the centreline. Every gap in the mark clears // 2 units: 5.1 to the left wall, 4.4 to the right, 2.8 to the // rim, 2.5 to the base, and 2.5 to 4.2 between the balls. Those // last three decide how far down the size ladder they stay // three things instead of one. $svg .= ''; // A fourth, larger sheet rides the rim under the lifted end of // the lid — the one element of the full state that is legible // at 20px, where the balls inside the body are a texture at // best. Same seven-point construction, twice the radius, // straddling the rim (y 28.5) so it reads as spilling out // rather than sitting in. $svg .= ''; } return $svg . ''; } /** * Both bin states as base64 data URIs, ready for `renderIcon()`. * * The client swaps between these as the count crosses zero, so both * have to reach the page on the first paint. Cheap: two string * builds and two base64 encodes, no queries. * * @return array{empty:string,full:string} */ function openstation_recycle_bin_icon_uris() { return array( 'empty' => 'data:image/svg+xml;base64,' . base64_encode( openstation_recycle_bin_icon_svg( false ) ), 'full' => 'data:image/svg+xml;base64,' . base64_encode( openstation_recycle_bin_icon_svg( true ) ), ); } /** * Whether the current user should see the recycle bin at all. * * Filterable so plugins can hide it from authors/contributors who * don't manage trash, or invert the gate to expose it to a custom * role. The app's gate (`apps/trash/trash.os.php`) delegates here. * * @return bool */ function openstation_recycle_bin_user_can_use() { $can = current_user_can( 'edit_posts' ); /** * Filter whether the current user can see the recycle bin window. * * @param bool $can Default: edit_posts capability. */ return (bool) apply_filters( 'openstation_recycle_bin_user_can_use', $can ); } /** * Enqueue the bin stylesheet with the shell. * * Not a window-open companion: the sheet also paints the * drag-to-trash drop-target highlight on the CLOSED bin's dock tile * (`data-os-trash-drop-active`), which must work before the window * has ever opened. */ function openstation_recycle_bin_enqueue_style() { if ( ! openstation_recycle_bin_user_can_use() ) { return; } wp_enqueue_style( 'desktop-mode-recycle-bin' ); } add_action( 'admin_enqueue_scripts', 'openstation_recycle_bin_enqueue_style', 5 ); /** * Inject the initial trash count and both bin drawings into the * shell config, so the dock tile (and any icon a user or plugin has * placed against this window) shows the right one on the very first * paint, before the bin window has ever opened. * * Both drawings travel together rather than the server picking one: * the count changes without a reload, and shipping the pair makes * crossing zero a local swap instead of a round trip. * * @param array $config Shell config blob. * @return array */ function openstation_recycle_bin_inject_shell_config( $config ) { if ( ! is_array( $config ) ) { return $config; } $icons = openstation_recycle_bin_icon_uris(); $config['recycleBinCount'] = openstation_recycle_bin_count(); $config['recycleBinCountUrl'] = esc_url_raw( rest_url( 'desktop-mode/v1/recycle-bin/count' ) ); $config['recycleBinPostTypes'] = openstation_recycle_bin_capture_post_types(); $config['recycleBinIconEmpty'] = $icons['empty']; $config['recycleBinIconFull'] = $icons['full']; return $config; } add_filter( 'openstation_shell_config', 'openstation_recycle_bin_inject_shell_config', 20 );