| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | <?php |
| 2 | 2 | /** |
| 3 | - * Desktop Mode — Appearance window tab adaptations. | |
| 3 | + * OpenStation — Appearance window tab adaptations. | |
| 4 | 4 | * |
| 5 | 5 | * The Appearance dock item opens an iframe of `themes.php` and uses |
| 6 | 6 | * the in-window submenu strip (built from the WP `$submenu` global) |
| 7 | 7 | * as its tab bar. WP Core does not register `theme-install.php` as a |
| @@ -11,14 +11,14 @@ | ||
| 11 | 11 | * Inside chromeless we hide that button (it scrolled out of the |
| 12 | 12 | * iframe's visible area on first paint, leaving no entry point to |
| 13 | 13 | * the install flow — see assets/css/chromeless.css). This file |
| 14 | 14 | * compensates by injecting an "Add Theme" tab at the front of the |
| 15 | - * Appearance window's submenu strip via the `desktop_mode_dock_item` | |
| 15 | + * Appearance window's submenu strip via the `openstation_dock_item` | |
| 16 | 16 | * filter. |
| 17 | 17 | * |
| 18 | 18 | * Resulting tab order: Appearance | Add Theme | Editor | Fonts | … |
| 19 | 19 | * |
| 20 | - * @package Desktop_Mode | |
| 20 | + * @package OpenStation | |
| 21 | 21 | */ |
| 22 | 22 | |
| 23 | 23 | defined( 'ABSPATH' ) || exit; |
| 24 | 24 | |
| @@ -24,9 +24,9 @@ | ||
| 24 | 24 | |
| 25 | 25 | /** |
| 26 | 26 | * Prepends an "Add Theme" entry to the Appearance dock item's submenu. |
| 27 | 27 | * |
| 28 | - * Called once per dock item via {@see desktop_mode_build_dock_items()}. | |
| 28 | + * Called once per dock item via {@see openstation_build_dock_items()}. | |
| 29 | 29 | * Skipped for every menu other than `themes.php` and for users who |
| 30 | 30 | * lack the `install_themes` capability — matching what classic |
| 31 | 31 | * admin's "Add Theme" page-title-action enforces. |
| 32 | 32 | * |
| @@ -34,9 +34,9 @@ | ||
| 34 | 34 | * badge, submenu, multi, placement, isCore). |
| 35 | 35 | * @param string $menu_slug The menu slug — e.g. `themes.php`. |
| 36 | 36 | * @return array Filtered dock item. |
| 37 | 37 | */ |
| 38 | -function desktop_mode_inject_appearance_tabs( $dock_item, $menu_slug ) { | |
| 38 | +function openstation_inject_appearance_tabs( $dock_item, $menu_slug ) { | |
| 39 | 39 | if ( 'themes.php' !== $menu_slug ) { |
| 40 | 40 | return $dock_item; |
| 41 | 41 | } |
| 42 | 42 | |
| @@ -71,11 +71,88 @@ | ||
| 71 | 71 | array_unshift( $dock_item['submenu'], $add_theme ); |
| 72 | 72 | |
| 73 | 73 | return $dock_item; |
| 74 | 74 | } |
| 75 | -add_filter( 'desktop_mode_dock_item', 'desktop_mode_inject_appearance_tabs', 10, 2 ); | |
| 75 | +add_filter( 'openstation_dock_item', 'openstation_inject_appearance_tabs', 10, 2 ); | |
| 76 | 76 | |
| 77 | 77 | /** |
| 78 | + * Renders the orientation header for the chromeless Themes workspace. | |
| 79 | + * | |
| 80 | + * Core's page heading is intentionally hidden inside OpenStation because the | |
| 81 | + * window chrome already names the screen. The Themes page still needs a little | |
| 82 | + * more context than a generic list screen, though: a theme changes the public | |
| 83 | + * face of the site, and Core's single-theme state otherwise opens directly on | |
| 84 | + * an unexplained details panel. | |
| 85 | + * | |
| 86 | + * The markup is emitted through `admin_notices`, which places it immediately | |
| 87 | + * before the page's `.wrap`. Core continues to own the theme cards, details | |
| 88 | + * overlay, actions, AJAX updates, and keyboard behavior. | |
| 89 | + * | |
| 90 | + * The screen is identified by `get_current_screen()`, not `$pagenow`. Every | |
| 91 | + * page registered with `add_theme_page()` also reports `themes.php` as its | |
| 92 | + * `$pagenow`, but its body class comes from the hook suffix | |
| 93 | + * (`appearance_page_<slug>`) and so matches none of the workspace CSS, which | |
| 94 | + * is scoped to `.themes-php`. Gating on `$pagenow` would emit this header | |
| 95 | + * unstyled on top of unrelated Appearance screens. The screen ID also keeps | |
| 96 | + * network admin (`themes-network`, a different list table entirely) out. | |
| 97 | + */ | |
| 98 | +function openstation_render_themes_workspace_intro() { | |
| 99 | + if ( ! openstation_is_chromeless_request() ) { | |
| 100 | + return; | |
| 101 | + } | |
| 102 | + | |
| 103 | + $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null; | |
| 104 | + if ( ! $screen || 'themes' !== $screen->id ) { | |
| 105 | + return; | |
| 106 | + } | |
| 107 | + | |
| 108 | + /* | |
| 109 | + * Mirrors how `wp_prepare_themes_for_js()` builds its own list, without | |
| 110 | + * paying for the preparation itself. Core already called that function | |
| 111 | + * on this request before `admin-header.php` ran, and calling it again | |
| 112 | + * would re-resolve every screenshot, tag and author URL and fire | |
| 113 | + * `pre_prepare_themes_for_js` / `wp_prepare_themes_for_js` a second | |
| 114 | + * time — so any third-party callback hanging off them would run twice | |
| 115 | + * per page load. `wp_get_themes()` is cached, so this is a lookup. | |
| 116 | + */ | |
| 117 | + if ( current_user_can( 'switch_themes' ) ) { | |
| 118 | + $themes = wp_get_themes( array( 'allowed' => true ) ); | |
| 119 | + $stylesheet = get_stylesheet(); | |
| 120 | + if ( ! isset( $themes[ $stylesheet ] ) ) { | |
| 121 | + $themes[ $stylesheet ] = wp_get_theme(); | |
| 122 | + } | |
| 123 | + $theme_count = count( $themes ); | |
| 124 | + } else { | |
| 125 | + $theme_count = 1; | |
| 126 | + } | |
| 127 | + ?> | |
| 128 | + <section class="openstation-themes-intro" aria-labelledby="openstation-themes-intro-title"> | |
| 129 | + <div class="openstation-themes-intro__copy"> | |
| 130 | + <p class="openstation-themes-intro__eyebrow"><?php esc_html_e( 'Site appearance', 'desktop-mode' ); ?></p> | |
| 131 | + <h1 id="openstation-themes-intro-title"><?php esc_html_e( 'Choose how your site greets the world.', 'desktop-mode' ); ?></h1> | |
| 132 | + <p><?php esc_html_e( 'Themes shape your site’s look. Switching keeps your posts and pages in place.', 'desktop-mode' ); ?></p> | |
| 133 | + </div> | |
| 134 | + <?php | |
| 135 | + /* | |
| 136 | + * Left readable rather than labelled: `aria-label` is ignored on a | |
| 137 | + * `<p>` (the paragraph role prohibits an author-supplied name), so | |
| 138 | + * pairing it with `aria-hidden` children hid the count from | |
| 139 | + * assistive tech entirely — and Core's own `.title-count` inside | |
| 140 | + * the page `<h1>` is display:none in chromeless mode, making this | |
| 141 | + * the only count on the screen. Read in DOM order the two spans | |
| 142 | + * announce as "3 Themes installed" on their own. | |
| 143 | + */ | |
| 144 | + ?> | |
| 145 | + <p class="openstation-themes-intro__count"> | |
| 146 | + <strong><?php echo esc_html( number_format_i18n( $theme_count ) ); ?></strong> | |
| 147 | + <span><?php echo esc_html( _n( 'Theme installed', 'Themes installed', $theme_count, 'desktop-mode' ) ); ?></span> | |
| 148 | + </p> | |
| 149 | + </section> | |
| 150 | + <?php | |
| 151 | +} | |
| 152 | +add_action( 'admin_notices', 'openstation_render_themes_workspace_intro', 0 ); | |
| 153 | + | |
| 154 | +/** | |
| 78 | 155 | * Fixes the visible "active tab" state inside chromeless |
| 79 | 156 | * theme-install.php iframes. |
| 80 | 157 | * |
| 81 | 158 | * Background: WP's installer JS uses a Backbone router whose pattern |
| @@ -80,10 +157,10 @@ | ||
| 80 | 157 | * |
| 81 | 158 | * Background: WP's installer JS uses a Backbone router whose pattern |
| 82 | 159 | * `theme-install.php?browse=:sort` greedy-captures everything past |
| 83 | 160 | * `browse=` ([^/?]+ matches `&` too). Inside chromeless the URL also |
| 84 | - * carries `desktop_mode_chromeless=1`, so `:sort` ends up as | |
| 85 | - * `popular&desktop_mode_chromeless=1`. WP's `view.sort()` then runs | |
| 161 | + * carries `openstation_chromeless=1`, so `:sort` ends up as | |
| 162 | + * `popular&openstation_chromeless=1`. WP's `view.sort()` then runs | |
| 86 | 163 | * with that polluted value and the `[data-sort]` selector finds |
| 87 | 164 | * nothing — leaving every tab in the unselected state even though |
| 88 | 165 | * the popular themes ARE the rendered listing. |
| 89 | 166 | * |
| @@ -99,10 +176,10 @@ | ||
| 99 | 176 | * A MutationObserver on `.filter-links` keeps the tab synced when WP's |
| 100 | 177 | * router fires or state changes (e.g. switching tabs to Latest or |
| 101 | 178 | * returning via pushState). |
| 102 | 179 | */ |
| 103 | -function desktop_mode_theme_install_active_tab_script() { | |
| 104 | - if ( ! desktop_mode_is_chromeless_request() ) { | |
| 180 | +function openstation_theme_install_active_tab_script() { | |
| 181 | + if ( ! openstation_is_chromeless_request() ) { | |
| 105 | 182 | return; |
| 106 | 183 | } |
| 107 | 184 | if ( ! isset( $GLOBALS['pagenow'] ) || 'theme-install.php' !== $GLOBALS['pagenow'] ) { |
| 108 | 185 | return; |
| @@ -179,5 +256,5 @@ | ||
| 179 | 256 | JS; |
| 180 | 257 | |
| 181 | 258 | wp_print_inline_script_tag( $js ); |
| 182 | 259 | } |
| 183 | -add_action( 'admin_footer', 'desktop_mode_theme_install_active_tab_script', 100 ); | |
| 260 | +add_action( 'admin_footer', 'openstation_theme_install_active_tab_script', 100 ); | |