ru-se.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

class-twenty-twenty-one-dark-mode.php (12162B)


      1 <?php
      2 /**
      3  * Dark Mode Class
      4  *
      5  * @package WordPress
      6  * @subpackage Twenty_Twenty_One
      7  * @since Twenty Twenty-One 1.0
      8  */
      9 
     10 /**
     11  * This class is in charge of Dark Mode.
     12  */
     13 class Twenty_Twenty_One_Dark_Mode {
     14 
     15 	/**
     16 	 * Instantiate the object.
     17 	 *
     18 	 * @since Twenty Twenty-One 1.0
     19 	 */
     20 	public function __construct() {
     21 
     22 		// Enqueue assets for the block-editor.
     23 		add_action( 'enqueue_block_editor_assets', array( $this, 'editor_custom_color_variables' ) );
     24 
     25 		// Add styles for dark-mode.
     26 		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
     27 
     28 		// Add scripts for customizer controls.
     29 		add_action( 'customize_controls_enqueue_scripts', array( $this, 'customize_controls_enqueue_scripts' ) );
     30 
     31 		// Add customizer controls.
     32 		add_action( 'customize_register', array( $this, 'customizer_controls' ) );
     33 
     34 		// Add HTML classes.
     35 		add_filter( 'twentytwentyone_html_classes', array( $this, 'html_classes' ) );
     36 
     37 		// Add classes to <body> in the dashboard.
     38 		add_filter( 'admin_body_class', array( $this, 'admin_body_classes' ) );
     39 
     40 		// Add the switch on the frontend & customizer.
     41 		add_action( 'wp_footer', array( $this, 'the_switch' ) );
     42 
     43 		// Add the privacy policy content.
     44 		add_action( 'admin_init', array( $this, 'add_privacy_policy_content' ) );
     45 	}
     46 
     47 	/**
     48 	 * Editor custom color variables & scripts.
     49 	 *
     50 	 * @since Twenty Twenty-One 1.0
     51 	 *
     52 	 * @return void
     53 	 */
     54 	public function editor_custom_color_variables() {
     55 		if ( ! $this->switch_should_render() ) {
     56 			return;
     57 		}
     58 		$background_color            = get_theme_mod( 'background_color', 'D1E4DD' );
     59 		$should_respect_color_scheme = get_theme_mod( 'respect_user_color_preference', false );
     60 		if ( $should_respect_color_scheme && Twenty_Twenty_One_Custom_Colors::get_relative_luminance_from_hex( $background_color ) > 127 ) {
     61 			// Add Dark Mode variable overrides.
     62 			wp_add_inline_style(
     63 				'twenty-twenty-one-custom-color-overrides',
     64 				'.is-dark-theme.is-dark-theme .editor-styles-wrapper { --global--color-background: var(--global--color-dark-gray); --global--color-primary: var(--global--color-light-gray); --global--color-secondary: var(--global--color-light-gray); --button--color-text: var(--global--color-background); --button--color-text-hover: var(--global--color-secondary); --button--color-text-active: var(--global--color-secondary); --button--color-background: var(--global--color-secondary); --button--color-background-active: var(--global--color-background); --global--color-border: #9ea1a7; --table--stripes-border-color: rgba(240, 240, 240, 0.15); --table--stripes-background-color: rgba(240, 240, 240, 0.15); }'
     65 			);
     66 		}
     67 		wp_enqueue_script(
     68 			'twentytwentyone-dark-mode-support-toggle',
     69 			get_template_directory_uri() . '/assets/js/dark-mode-toggler.js',
     70 			array(),
     71 			'1.0.0',
     72 			true
     73 		);
     74 
     75 		wp_enqueue_script(
     76 			'twentytwentyone-editor-dark-mode-support',
     77 			get_template_directory_uri() . '/assets/js/editor-dark-mode-support.js',
     78 			array( 'twentytwentyone-dark-mode-support-toggle' ),
     79 			'1.0.0',
     80 			true
     81 		);
     82 	}
     83 
     84 	/**
     85 	 * Enqueue scripts and styles.
     86 	 *
     87 	 * @since Twenty Twenty-One 1.0
     88 	 *
     89 	 * @return void
     90 	 */
     91 	public function enqueue_scripts() {
     92 		if ( ! $this->switch_should_render() ) {
     93 			return;
     94 		}
     95 		$url = get_template_directory_uri() . '/assets/css/style-dark-mode.css';
     96 		if ( is_rtl() ) {
     97 			$url = get_template_directory_uri() . '/assets/css/style-dark-mode-rtl.css';
     98 		}
     99 		wp_enqueue_style( 'tt1-dark-mode', $url, array( 'twenty-twenty-one-style' ), wp_get_theme()->get( 'Version' ) ); // @phpstan-ignore-line. Version is always a string.
    100 	}
    101 
    102 	/**
    103 	 * Enqueue scripts for the customizer.
    104 	 *
    105 	 * @since Twenty Twenty-One 1.0
    106 	 *
    107 	 * @return void
    108 	 */
    109 	public function customize_controls_enqueue_scripts() {
    110 		if ( ! $this->switch_should_render() ) {
    111 			return;
    112 		}
    113 		wp_enqueue_script(
    114 			'twentytwentyone-customize-controls',
    115 			get_template_directory_uri() . '/assets/js/customize.js',
    116 			array( 'customize-base', 'customize-controls', 'underscore', 'jquery', 'twentytwentyone-customize-helpers' ),
    117 			'1.0.0',
    118 			true
    119 		);
    120 	}
    121 
    122 	/**
    123 	 * Register customizer options.
    124 	 *
    125 	 * @since Twenty Twenty-One 1.0
    126 	 *
    127 	 * @param WP_Customize_Manager $wp_customize Theme Customizer object.
    128 	 * @return void
    129 	 */
    130 	public function customizer_controls( $wp_customize ) {
    131 
    132 		$colors_section = $wp_customize->get_section( 'colors' );
    133 		if ( is_object( $colors_section ) ) {
    134 			$colors_section->title = __( 'Colors & Dark Mode', 'twentytwentyone' );
    135 		}
    136 
    137 		// Custom notice control.
    138 		include_once get_theme_file_path( 'classes/class-twenty-twenty-one-customize-notice-control.php' ); // phpcs:ignore WPThemeReview.CoreFunctionality.FileInclude.FileIncludeFound
    139 
    140 		$wp_customize->add_setting(
    141 			'respect_user_color_preference_notice',
    142 			array(
    143 				'capability'        => 'edit_theme_options',
    144 				'default'           => '',
    145 				'sanitize_callback' => '__return_empty_string',
    146 			)
    147 		);
    148 
    149 		$wp_customize->add_control(
    150 			new Twenty_Twenty_One_Customize_Notice_Control(
    151 				$wp_customize,
    152 				'respect_user_color_preference_notice',
    153 				array(
    154 					'section'         => 'colors',
    155 					'priority'        => 100,
    156 					'active_callback' => function() {
    157 						return 127 >= Twenty_Twenty_One_Custom_Colors::get_relative_luminance_from_hex( get_theme_mod( 'background_color', 'D1E4DD' ) );
    158 					},
    159 				)
    160 			)
    161 		);
    162 
    163 		$wp_customize->add_setting(
    164 			'respect_user_color_preference',
    165 			array(
    166 				'capability'        => 'edit_theme_options',
    167 				'default'           => false,
    168 				'sanitize_callback' => function( $value ) {
    169 					return (bool) $value;
    170 				},
    171 			)
    172 		);
    173 
    174 		$description  = '<p>';
    175 		$description .= sprintf(
    176 			/* translators: %s: Twenty Twenty-One support article URL. */
    177 			__( 'Dark Mode is a device setting. If a visitor to your site requests it, your site will be shown with a dark background and light text. <a href="%s">Learn more about Dark Mode.</a>', 'twentytwentyone' ),
    178 			esc_url( __( 'https://wordpress.org/support/article/twenty-twenty-one/#dark-mode-support', 'twentytwentyone' ) )
    179 		);
    180 		$description .= '</p>';
    181 		$description .= '<p>' . __( 'Dark Mode can also be turned on and off with a button that you can find in the bottom right corner of the page.', 'twentytwentyone' ) . '</p>';
    182 
    183 		$wp_customize->add_control(
    184 			'respect_user_color_preference',
    185 			array(
    186 				'type'            => 'checkbox',
    187 				'section'         => 'colors',
    188 				'label'           => esc_html__( 'Dark Mode support', 'twentytwentyone' ),
    189 				'priority'        => 110,
    190 				'description'     => $description,
    191 				'active_callback' => function( $value ) {
    192 					return 127 < Twenty_Twenty_One_Custom_Colors::get_relative_luminance_from_hex( get_theme_mod( 'background_color', 'D1E4DD' ) );
    193 				},
    194 			)
    195 		);
    196 
    197 		// Add partial for background_color.
    198 		$wp_customize->selective_refresh->add_partial(
    199 			'background_color',
    200 			array(
    201 				'selector'            => '#dark-mode-toggler',
    202 				'container_inclusive' => true,
    203 				'render_callback'     => function() {
    204 					$attrs = ( $this->switch_should_render() ) ? array() : array( 'style' => 'display:none;' );
    205 					$this->the_html( $attrs );
    206 				},
    207 			)
    208 		);
    209 	}
    210 
    211 	/**
    212 	 * Calculate classes for the main <html> element.
    213 	 *
    214 	 * @since Twenty Twenty-One 1.0
    215 	 *
    216 	 * @param string $classes The classes for <html> element.
    217 	 * @return string
    218 	 */
    219 	public function html_classes( $classes ) {
    220 		if ( ! $this->switch_should_render() ) {
    221 			return $classes;
    222 		}
    223 
    224 		$background_color            = get_theme_mod( 'background_color', 'D1E4DD' );
    225 		$should_respect_color_scheme = get_theme_mod( 'respect_user_color_preference', false );
    226 		if ( $should_respect_color_scheme && 127 <= Twenty_Twenty_One_Custom_Colors::get_relative_luminance_from_hex( $background_color ) ) {
    227 			return ( $classes ) ? ' respect-color-scheme-preference' : 'respect-color-scheme-preference';
    228 		}
    229 
    230 		return $classes;
    231 	}
    232 
    233 	/**
    234 	 * Adds a class to the <body> element in the editor to accommodate dark-mode.
    235 	 *
    236 	 * @since Twenty Twenty-One 1.0
    237 	 *
    238 	 * @param string $classes The admin body-classes.
    239 	 * @return string
    240 	 */
    241 	public function admin_body_classes( $classes ) {
    242 		if ( ! $this->switch_should_render() ) {
    243 			return $classes;
    244 		}
    245 
    246 		global $current_screen;
    247 		if ( empty( $current_screen ) ) {
    248 			set_current_screen();
    249 		}
    250 
    251 		if ( $current_screen->is_block_editor() ) {
    252 			$should_respect_color_scheme = get_theme_mod( 'respect_user_color_preference', false );
    253 			$background_color            = get_theme_mod( 'background_color', 'D1E4DD' );
    254 
    255 			if ( $should_respect_color_scheme && Twenty_Twenty_One_Custom_Colors::get_relative_luminance_from_hex( $background_color ) > 127 ) {
    256 				$classes .= ' twentytwentyone-supports-dark-theme';
    257 			}
    258 		}
    259 
    260 		return $classes;
    261 	}
    262 
    263 	/**
    264 	 * Determine if we want to print the dark-mode switch or not.
    265 	 *
    266 	 * @since Twenty Twenty-One 1.0
    267 	 *
    268 	 * @return bool
    269 	 */
    270 	public function switch_should_render() {
    271 		global $is_IE;
    272 		return (
    273 			get_theme_mod( 'respect_user_color_preference', false ) &&
    274 			! $is_IE &&
    275 			127 <= Twenty_Twenty_One_Custom_Colors::get_relative_luminance_from_hex( get_theme_mod( 'background_color', 'D1E4DD' ) )
    276 		);
    277 	}
    278 
    279 	/**
    280 	 * Add night/day switch.
    281 	 *
    282 	 * @since Twenty Twenty-One 1.0
    283 	 *
    284 	 * @return void
    285 	 */
    286 	public function the_switch() {
    287 		if ( ! $this->switch_should_render() ) {
    288 			return;
    289 		}
    290 		$this->the_html();
    291 		$this->the_script();
    292 	}
    293 
    294 	/**
    295 	 * Print the dark-mode switch HTML.
    296 	 *
    297 	 * Inspired from https://codepen.io/aaroniker/pen/KGpXZo (MIT-licensed)
    298 	 *
    299 	 * @since Twenty Twenty-One 1.0
    300 	 *
    301 	 * @param array $attrs The attributes to add to our <button> element.
    302 	 * @return void
    303 	 */
    304 	public function the_html( $attrs = array() ) {
    305 		$attrs = wp_parse_args(
    306 			$attrs,
    307 			array(
    308 				'id'           => 'dark-mode-toggler',
    309 				'class'        => 'fixed-bottom',
    310 				'aria-pressed' => 'false',
    311 				'onClick'      => 'toggleDarkMode()',
    312 			)
    313 		);
    314 		echo '<button';
    315 		foreach ( $attrs as $key => $val ) {
    316 			echo ' ' . esc_attr( $key ) . '="' . esc_attr( $val ) . '"';
    317 		}
    318 		echo '>';
    319 		printf(
    320 			/* translators: %s: On/Off */
    321 			esc_html__( 'Dark Mode: %s', 'twentytwentyone' ),
    322 			'<span aria-hidden="true"></span>'
    323 		);
    324 		echo '</button>';
    325 		?>
    326 		<style>
    327 			#dark-mode-toggler > span {
    328 				margin-<?php echo is_rtl() ? 'right' : 'left'; ?>: 5px;
    329 			}
    330 			#dark-mode-toggler > span::before {
    331 				content: '<?php esc_attr_e( 'Off', 'twentytwentyone' ); ?>';
    332 			}
    333 			#dark-mode-toggler[aria-pressed="true"] > span::before {
    334 				content: '<?php esc_attr_e( 'On', 'twentytwentyone' ); ?>';
    335 			}
    336 			<?php if ( is_admin() || wp_is_json_request() ) : ?>
    337 				.components-editor-notices__pinned ~ .edit-post-visual-editor #dark-mode-toggler {
    338 					z-index: 20;
    339 				}
    340 				.is-dark-theme.is-dark-theme #dark-mode-toggler:not(:hover):not(:focus) {
    341 					color: var(--global--color-primary);
    342 				}
    343 				@media only screen and (max-width: 782px) {
    344 					#dark-mode-toggler {
    345 						margin-top: 32px;
    346 					}
    347 				}
    348 			<?php endif; ?>
    349 		</style>
    350 
    351 		<?php
    352 	}
    353 
    354 	/**
    355 	 * Print the dark-mode switch script.
    356 	 *
    357 	 * @since Twenty Twenty-One 1.0
    358 	 *
    359 	 * @return void
    360 	 */
    361 	public function the_script() {
    362 		echo '<script>';
    363 		include get_template_directory() . '/assets/js/dark-mode-toggler.js'; // phpcs:ignore WPThemeReview.CoreFunctionality.FileInclude
    364 		echo '</script>';
    365 	}
    366 
    367 	/**
    368 	 * Adds information to the privacy policy.
    369 	 *
    370 	 * @since Twenty Twenty-One 1.0
    371 	 *
    372 	 * @return void
    373 	 */
    374 	public function add_privacy_policy_content() {
    375 		if ( ! function_exists( 'wp_add_privacy_policy_content' ) ) {
    376 			return;
    377 		}
    378 		$content = '<p class="privacy-policy-tutorial">' . __( 'Twenty Twenty-One uses LocalStorage when Dark Mode support is enabled.', 'twentytwentyone' ) . '</p>'
    379 				. '<strong class="privacy-policy-tutorial">' . __( 'Suggested text:', 'twentytwentyone' ) . '</strong> '
    380 				. __( 'This website uses LocalStorage to save the setting when Dark Mode support is turned on or off.<br> LocalStorage is necessary for the setting to work and is only used when a user clicks on the Dark Mode button.<br> No data is saved in the database or transferred.', 'twentytwentyone' );
    381 		wp_add_privacy_policy_content( 'Twenty Twenty-One', wp_kses_post( wpautop( $content, false ) ) );
    382 	}
    383 
    384 }