` shell components here because they only ship inside the * desktop bundle, which is precisely *not* loaded on the classic admin * screens where this dialog is allowed to appear. * * @package OpenStation */ defined( 'ABSPATH' ) || exit; /** Slug stored in `desktop_mode_seen_intros` for this dialog. */ const OPENSTATION_WELCOME_INTRO_SLUG = 'activation-welcome'; /** * Decides whether the welcome dialog should render on the current request. * * Six gates: * * 1. We're inside `/wp-admin` (`is_admin()`). * 2. The user is logged in and can `read` (sanity gate — the dialog has * no destructive surface, but anonymous output makes no sense). * 3. The request is NOT chromeless — chromeless pages are iframes * rendering inside the desktop shell; the parent shell already shows * its own UX. * 4. OpenStation is NOT already enabled for the user. This is a * "switch to OpenStation" promo, so it has nothing to say once the * user is in the shell. The desktop shell's *parent* page is admin * context and is not chromeless, so without this gate the dialog * re-renders there the moment the user clicks "Enable it now" — read * as a duplicate dialog, because the fire-and-forget seen-intro POST * races the redirect into the shell and often loses. * 5. The user has not already dismissed this intro. * 6. The `openstation_show_welcome_dialog` filter returns truthy, so * sites can suppress the dialog entirely (e.g. managed-host onboarding * flows that ship their own). * * @return bool */ function openstation_should_show_welcome_dialog() { if ( ! is_admin() || ! is_user_logged_in() ) { return false; } if ( ! current_user_can( 'read' ) ) { return false; } if ( function_exists( 'openstation_is_chromeless_request' ) && openstation_is_chromeless_request() ) { return false; } if ( function_exists( 'openstation_is_enabled' ) && openstation_is_enabled() ) { return false; } $user_id = get_current_user_id(); if ( openstation_has_seen_intro( $user_id, OPENSTATION_WELCOME_INTRO_SLUG ) ) { return false; } /** * Filters whether the first-run welcome dialog should render for * the current user on the current request. All earlier gates * (admin context, capability, chromeless, seen-state) have * already passed by the time this filter fires. * * @param bool $show Whether to render the dialog. Default true. * @param int $user_id Current user ID. */ return (bool) apply_filters( 'openstation_show_welcome_dialog', true, $user_id ); } /** * Prints the welcome dialog markup, styles and dismiss script into * `admin_footer`. * * Self-contained on purpose: everything is scoped under the * `.os-welcome` namespace so it cannot collide with the host * admin theme. The dismiss button POSTs to the seen-intros REST route, * which is exactly the same endpoint the in-shell intros use. */ function openstation_render_welcome_dialog() { if ( ! openstation_should_show_welcome_dialog() ) { return; } $rest_url = esc_url_raw( rest_url( 'desktop-mode/v1/intros/seen' ) ); $rest_nonce = wp_create_nonce( 'wp_rest' ); $ajax_url = esc_url_raw( admin_url( 'admin-ajax.php' ) ); $ajax_nonce = wp_create_nonce( 'save-openstation' ); $slug = OPENSTATION_WELCOME_INTRO_SLUG; // All user-facing strings are passed through translation; the dialog // is keyboard-dismissible (Escape) and moves initial focus to the // primary CTA. $title = __( 'Welcome to OpenStation', 'desktop-mode' ); $subtitle = __( 'A floating, window-based workspace for the WordPress admin — more like a real OS, less like a webpage.', 'desktop-mode' ); $body = __( 'OpenStation reimagines the WordPress admin as a true desktop environment. Open multiple admin screens side-by-side, drag and drop content between windows, and keep your work in view as you move between tasks.', 'desktop-mode' ); $cta = __( 'Got it', 'desktop-mode' ); $enable = __( 'Enable it now', 'desktop-mode' ); $enabling = __( 'Enabling…', 'desktop-mode' ); $features = array( array( 'icon' => '🪟', 'title' => __( 'Multi-window workspace', 'desktop-mode' ), 'desc' => __( 'Open Posts, Media and Plugins in their own draggable, resizable windows. Tile, cascade or stack them however you work best.', 'desktop-mode' ), ), array( 'icon' => '⚡', 'title' => __( 'Native, table-driven apps', 'desktop-mode' ), 'desc' => __( 'Posts, Pages, Users and Plugins are reimplemented as fast native windows with sticky headers, bulk actions, multi-select and inline previews.', 'desktop-mode' ), ), array( 'icon' => '🎨', 'title' => __( 'Wallpapers, dock & themes', 'desktop-mode' ), 'desc' => __( 'Make it yours. Choose a wallpaper, pin your favorite screens to the dock, and switch accent colors — all from OpenStation Preferences.', 'desktop-mode' ), ), array( 'icon' => '🤖', 'title' => __( 'AI Copilot, built in', 'desktop-mode' ), 'desc' => __( 'Press ⌘K anywhere to ask the AI Assistant — it can run commands, navigate windows and answer questions about your site.', 'desktop-mode' ), ), ); ?>