` markup.
*/
function openstation_recycle_bin_icon_svg( $full = false ) {
// The lid and the handle travel together. In the full state the
// pair is knocked askew, which is the whole difference at the top
// of the mark.
$lid_transform = $full
? ' transform="translate(0 -2.5) rotate(8 32 21.5)"'
: '';
$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 ) ),
);
}
/**
* Echoes the recycle bin window's template body.
*
* The shell wraps this in ``
* and clones it into the window body BEFORE the JS render callback runs.
* The `data-os-recycle-bin-*` hooks below are the contract the JS
* relies on — keep them intact (or rename via the filter) when
* customizing the layout.
*/
function openstation_recycle_bin_render_template() {
ob_start();
?>
__( 'Trash', 'desktop-mode' ),
'icon' => $icon_uri,
'template' => 'openstation_recycle_bin_render_template',
'script' => 'desktop-mode-recycle-bin',
'width' => 880,
'height' => 560,
'min_width' => 520,
'min_height' => 360,
'placement' => 'dock',
'nav_kind' => 'control',
// Last on the rail, after the shell's own cluster (Mio 10,
// Overview 20, System 30). Trash is where things END UP, and a
// dock reads left to right: putting it anywhere but the end
// makes it one more app rather than the bottom of the pile.
'dock_order' => 40,
// The bin is the one dock tile a user can reasonably not want,
// so it gets a row in Apps & Plugins: dock (the default),
// desktop, both, or hidden. It registers no desktop icon, so
// that row is its only control.
'placeable' => true,
);
/**
* Filter the args used to register the recycle bin native window.
*
* @param array $window_args Args passed to `openstation_register_window()`.
*/
$window_args = (array) apply_filters( 'openstation_recycle_bin_window_args', $window_args );
$registered = openstation_register_window( 'desktop-mode-recycle-bin', $window_args );
if ( is_wp_error( $registered ) ) {
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
error_log( '[openstation] Recycle bin window registration failed: ' . $registered->get_error_message() );
}
}
add_action( 'init', 'openstation_recycle_bin_register_window', 20 );
/**
* Localize REST endpoints for the JS bundle.
*
* Same pattern as the code editor: the bundle reads its config off
* `window.openStationRecycleBinConfig` and never hardcodes URLs.
*/
function openstation_recycle_bin_localize_config() {
if ( ! openstation_recycle_bin_user_can_use() ) {
return;
}
wp_localize_script(
'desktop-mode-recycle-bin',
'openStationRecycleBinConfig',
array(
'restNonce' => wp_create_nonce( 'wp_rest' ),
'listUrl' => esc_url_raw( rest_url( 'desktop-mode/v1/recycle-bin' ) ),
'restoreUrl' => esc_url_raw( rest_url( 'desktop-mode/v1/recycle-bin/restore' ) ),
'purgeUrl' => esc_url_raw( rest_url( 'desktop-mode/v1/recycle-bin/purge' ) ),
'emptyUrl' => esc_url_raw( rest_url( 'desktop-mode/v1/recycle-bin/empty' ) ),
'countUrl' => esc_url_raw( rest_url( 'desktop-mode/v1/recycle-bin/count' ) ),
'postTypes' => openstation_recycle_bin_capture_post_types(),
)
);
wp_enqueue_style( 'desktop-mode-recycle-bin' );
}
// Priority 5, not an afterthought: `openstation_enqueue_assets()` (default 10)
// harvests every lazy window's `wp_localize_script` data into the shell
// payload, so config attached after 10 ships the bundle with no config — the
// exact "openStationRecycleBinConfig is missing" failure the bundle warns
// about. This ran at 30 and got away with it only while the bundle was
// enqueued eagerly and WordPress printed the data itself at print time.
add_action( 'admin_enqueue_scripts', 'openstation_recycle_bin_localize_config', 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 );