*/ function adminight_modes() { return array( 'light' => __( 'Light', 'adminight' ), 'dark' => __( 'Dark', 'adminight' ), 'auto' => __( 'Auto (follow the device)', 'adminight' ), ); } /** * The mode for users who have not picked one themselves. * * @return string light | dark | auto */ function adminight_default_mode() { $mode = get_option( ADMINIGHT_OPTION, 'auto' ); /** * Filters the mode used by people who have not chosen one. * * @param string $mode light, dark or auto. */ $mode = apply_filters( 'adminight_default_mode', $mode ); return array_key_exists( $mode, adminight_modes() ) ? $mode : 'auto'; } /** * A user's mode: their own choice, or the site default. * * @param int $user_id User ID; the current user when 0. * @return string light | dark | auto */ function adminight_get_mode( $user_id = 0 ) { $user_id = $user_id ? $user_id : get_current_user_id(); $mode = $user_id ? get_user_meta( $user_id, ADMINIGHT_META, true ) : ''; return array_key_exists( $mode, adminight_modes() ) ? $mode : adminight_default_mode(); } /** * Asset version: the plugin version, or the file's time while SCRIPT_DEBUG is on, so edits show up at once. * * @param string $file File name inside assets/. * @return string */ function adminight_asset_version( $file ) { if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) { return (string) filemtime( __DIR__ . '/assets/' . $file ); } return ADMINIGHT_VERSION; } /** * The class this screen gets when dark: "adminight-on" (styled), "adminight-invert" (inverted) or "" (not here). * * @return string */ function adminight_screen_class() { $style = adminight_current_style(); if ( 'invert' === $style ) { return 'adminight-invert'; } return 'dark' === $style ? 'adminight-on' : ''; } /** * Sets the class on before the page paints, so a dark screen never flashes white. */ function adminight_head_script() { $script = sprintf( '(function(d,m,c,s){var q=window.matchMedia("(prefers-color-scheme: dark)");function a(){var on=!!c&&(m==="dark"||(m==="auto"&&q.matches));d.classList.toggle(c||"adminight-on",on);}d.setAttribute("data-adminight-mode",m);d.setAttribute("data-adminight-class",c);d.setAttribute("data-adminight-scope",s);a();if(q.addEventListener){q.addEventListener("change",function(){m=d.getAttribute("data-adminight-mode");a();});}})(document.documentElement,%s,%s,%s);', wp_json_encode( adminight_get_mode() ), wp_json_encode( adminight_screen_class() ), wp_json_encode( adminight_current_scope() ) ); wp_print_inline_script_tag( $script, array( 'id' => 'adminight-mode' ) ); } add_action( 'admin_head', 'adminight_head_script', 0 ); /** * Stylesheet and the toolbar switch. */ function adminight_enqueue() { wp_enqueue_style( 'adminight', ADMINIGHT_URL . 'assets/adminight.css', array(), adminight_asset_version( 'adminight.css' ) ); wp_enqueue_script( 'adminight', ADMINIGHT_URL . 'assets/adminight.js', array(), adminight_asset_version( 'adminight.js' ), true ); wp_localize_script( 'adminight', 'AdminightSettings', array( 'ajax' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'adminight_mode' ), 'labels' => adminight_modes(), ) ); } add_action( 'admin_enqueue_scripts', 'adminight_enqueue' ); // The Customizer is its own screen with its own hooks. add_action( 'customize_controls_enqueue_scripts', 'adminight_enqueue' ); add_action( 'customize_controls_print_styles', 'adminight_head_script', 0 ); /** * The login screen has no user yet, so it follows the site default (Auto = the device's setting). */ function adminight_login_style() { $mode = adminight_default_mode(); $areas = adminight_site_areas(); if ( 'light' === $mode || empty( $areas['login'] ) || adminight_paused() ) { return; } wp_enqueue_style( 'adminight-login', ADMINIGHT_URL . 'assets/adminight-login.css', array( 'login' ), adminight_asset_version( 'adminight-login.css' ), 'dark' === $mode ? 'all' : '(prefers-color-scheme: dark)' ); } add_action( 'login_enqueue_scripts', 'adminight_login_style' ); /** * The classic editor writes inside its own frame, so it gets its own small stylesheet and a class with the mode. * * @param string $css Comma-separated stylesheet URLs. * @return string */ function adminight_mce_css( $css ) { if ( ! is_admin() ) { return $css; } $url = ADMINIGHT_URL . 'assets/adminight-editor.css?ver=' . adminight_asset_version( 'adminight-editor.css' ); return $css ? $css . ',' . $url : $url; } add_filter( 'mce_css', 'adminight_mce_css' ); /** * Adds the mode to the classic editor's body class, or "light" where dark mode is not used. * * @param array $init TinyMCE settings. * @return array */ function adminight_mce_body_class( $init ) { if ( is_admin() ) { $mode = 'adminight-on' === adminight_screen_class() ? adminight_get_mode() : 'light'; $init['body_class'] = trim( ( isset( $init['body_class'] ) ? $init['body_class'] : '' ) . ' adminight-mce-' . $mode ); } return $init; } add_filter( 'tiny_mce_before_init', 'adminight_mce_body_class' ); /** * Toolbar switch, inside wp-admin only. * * @param WP_Admin_Bar $bar The toolbar. */ function adminight_bar_node( $bar ) { if ( ! is_admin() || ! is_user_logged_in() ) { return; } $mode = adminight_get_mode(); $labels = adminight_modes(); $bar->add_node( array( 'id' => 'adminight', 'parent' => 'top-secondary', 'title' => '' . esc_html( $labels[ $mode ] ) . '', 'href' => '#', 'meta' => array( 'title' => __( 'Admin colours: Light, Dark or Auto', 'adminight' ), 'class' => 'adminight-ab', ), ) ); foreach ( $labels as $key => $label ) { $bar->add_node( array( 'id' => 'adminight-' . $key, 'parent' => 'adminight', 'title' => esc_html( $label ), 'href' => '#', 'meta' => array( 'class' => 'adminight-ab-choice' . ( $key === $mode ? ' adminight-current' : '' ) ), ) ); } if ( '' === adminight_screen_class() && ! adminight_paused() ) { $bar->add_node( array( 'id' => 'adminight-not-here', 'parent' => 'adminight', 'title' => esc_html__( 'Not used on this screen', 'adminight' ), 'href' => current_user_can( 'manage_options' ) ? admin_url( 'options-general.php?page=adminight' ) : admin_url( 'profile.php#adminight-mode' ), 'meta' => array( 'class' => 'adminight-ab-note' ), ) ); } } add_action( 'admin_bar_menu', 'adminight_bar_node', 100 ); /** * Saves the choice made in the toolbar. */ function adminight_ajax_set_mode() { check_ajax_referer( 'adminight_mode', 'nonce' ); if ( ! current_user_can( 'read' ) ) { wp_send_json_error( null, 403 ); } $mode = isset( $_POST['mode'] ) ? sanitize_key( wp_unslash( $_POST['mode'] ) ) : ''; if ( ! array_key_exists( $mode, adminight_modes() ) ) { wp_send_json_error( null, 400 ); } update_user_meta( get_current_user_id(), ADMINIGHT_META, $mode ); wp_send_json_success( array( 'mode' => $mode ) ); } add_action( 'wp_ajax_adminight_set_mode', 'adminight_ajax_set_mode' );