👁 查看:class-react-dropin.php
路径:/home/forge/kingkrunch.com/wp/wp-content/plugins/simple-history/dropins/class-react-dropin.php
大小:6.76 KB · 修改:2026-09-25 00:42:29 · 权限:0644 · 可写
<?php

namespace Simple_History\Dropins;

use Simple_History\Helpers;
use Simple_History\Services\REST_API;

/**
 * Loads the new GUI based on React.
 */
class React_Dropin extends Dropin {
	/** @inheritdoc */
	public function loaded() {
		add_action( 'simple_history/history_page/gui_wrap_top', [ $this, 'output_element_page' ], 1 );
		add_action( 'simple_history/dashboard/before_gui', [ $this, 'output_element_dashboard' ], 1 );
		add_action( 'simple_history/enqueue_admin_scripts', [ $this, 'enqueue_admin_scripts' ] );
	}

	/**
	 * Enqueue scripts generated by wp-scripts.
	 */
	public function enqueue_admin_scripts() {
		// Bail if not a Simple History page so no unneeded scripts are loaded.
		if ( ! Helpers::is_on_our_own_pages() ) {
			return;
		}

		$asset_file = include SIMPLE_HISTORY_PATH . 'build/index.asset.php';

		// Show error if asset file is not found.
		if ( $asset_file === false ) {
			// Bail if function does not exist, ie. WordPress < 6.4.
			if ( ! function_exists( 'wp_admin_notice' ) ) {
				return;
			}

			wp_admin_notice(
				__( 'Simple History failed to load the asset file for the main GUI. Please try reinstalling the plugin or make sure the JavaScript is built.', 'simple-history' ),
				[ 'type' => 'error' ]
			);
			return;
		}

		// Load the WP components CSS or some components will be unstyled.
		wp_enqueue_style( 'wp-components' );

		wp_register_script(
			'simple_history_wp_scripts',
			SIMPLE_HISTORY_DIR_URL . 'build/index.js',
			$asset_file['dependencies'],
			$asset_file['version'],
			true
		);

		wp_enqueue_script( 'simple_history_wp_scripts' );
		wp_set_script_translations( 'simple_history_wp_scripts', 'simple-history' );

		$stored_events_view = get_user_meta( get_current_user_id(), REST_API::EVENTS_VIEW_USER_META_KEY, true );

		// Read at enqueue time too, so the first paint already has the sidebar
		// in the state the reader left it. Fetching it would mean drawing the
		// page one way and then rearranging it, which is the single most
		// visible kind of flash a layout can have.
		$hidden_sidebar_views = get_user_meta(
			get_current_user_id(),
			REST_API::HIDDEN_SIDEBAR_VIEWS_USER_META_KEY,
			true
		);

		// The events page URL is also returned by the search-options REST endpoint,
		// but that arrives after the first render. Anything building a link before
		// it resolves — the surrounding-events view renders without waiting for
		// search options — would otherwise have no base URL to build on. It costs
		// nothing to know at enqueue time, so hand it over rather than fetch it.
		wp_localize_script(
			'simple_history_wp_scripts',
			'simpleHistoryReactData',
			[
				'eventsAdminPageURL'  => Helpers::get_history_admin_url(),
				// Read at enqueue time so the first render already uses the user's view.
				'eventsView'          => $this->get_initial_events_view( $stored_events_view ),
				// The views the reader has hidden the page sidebar in. An
				// array rather than the stored string, because every reader of
				// it wants the list. See REST_API::HIDDEN_SIDEBAR_VIEWS_USER_META_KEY.
				'hiddenSidebarViews'  => array_values(
					array_intersect(
						is_string( $hidden_sidebar_views ) && $hidden_sidebar_views !== ''
							? explode( ',', $hidden_sidebar_views )
							: [],
						REST_API::EVENTS_VIEWS
					)
				),
				// Used by the Table view preview's upgrade link. Built here, not in
				// JS, so it goes through Helpers::get_tracking_url() like every
				// other tracked link (issue 280: an untagged link lost three
				// quarters of the user card's click attribution).
				//
				// Points at the table view's own feature page rather than the
				// generic Premium page, so the click lands on what it promised.
				'tableViewUpgradeUrl' => Helpers::get_tracking_url(
					'https://simple-history.com/features/table-view/',
					'premium_table_view',
					'wpadmin',
					'plugin',
					'preview_cta'
				),
			]
		);
	}

	/**
	 * The view the events page opens in, from the reader's stored choice.
	 *
	 * A stored "table" only counts with Premium active. Without it the table
	 * view is an upgrade preview, and reopening the log on that preview every
	 * visit because the reader clicked the table icon once would be a nag
	 * screen. A ?view=table link still opens the preview, since following one
	 * is a choice made there and then.
	 *
	 * @param mixed $stored_events_view The stored user meta value.
	 * @return string One of "detailed", "compact" or "table".
	 */
	private function get_initial_events_view( $stored_events_view ) {
		if ( $stored_events_view === 'compact' ) {
			return 'compact';
		}

		if ( $stored_events_view === 'table' && Helpers::is_premium_add_on_active() ) {
			return 'table';
		}

		return 'detailed';
	}

	/**
	 * Output HTML element on the history page for React to mount on.
	 */
	public function output_element_page() {
		?>
		<div 
			id="simple-history-react-root" 
			class="SimpleHistoryReactRoot is-page"
			style="<?php echo esc_attr( $this->get_css_style_vars() ); ?>"
		>
			<span class="SimpleHistoryReactRoot-loading">
				<?php esc_html_e( 'Loading history…', 'simple-history' ); ?>
			</span>
		</div>
		<?php
	}

	/**
	 * Output HTML element on the dashboard for React to mount on.
	 */
	public function output_element_dashboard() {
		$this->get_current_theme_colors();
		?>
		<div
			id="simple-history-react-root"
			class="SimpleHistoryReactRoot is-dashboard"
			style="<?php echo esc_attr( $this->get_css_style_vars() ); ?>"
		>
			<span class="SimpleHistoryReactRoot-loading">
				<?php esc_html_e( 'Loading history…', 'simple-history' ); ?>
			</span>
		</div>
		<?php
	}

	/**
	 * Generate css style attributes to use at the react root element.
	 * This is to override the Gutenberg colors that are not the same as the admin theme colors.
	 * For example the blue color in the Gutenberg editor is not the same as the admin theme color.
	 *
	 * @return string
	 */
	private function get_css_style_vars() {
		$colors = $this->get_current_theme_colors();

		$css_vars = [
			'--wp-admin-theme-color' => $colors['link'],
		];

		$css_vars_string = '';
		foreach ( $css_vars as $key => $value ) {
			$css_vars_string = $css_vars_string . $key . ':' . $value . ';';
		}

		return $css_vars_string;
	}

	/**
	 * Get the current theme colors.
	 *
	 * @return array<string, string> An associative array containing the theme colors.
	 */
	private function get_current_theme_colors() {
		$color_scheme = get_user_option( 'admin_color' );

		$colors = [
			'default' => [
				'link'       => '#0073aa',
				'link_focus' => '#135e96',
			],
			// "modern" is the only one with a different color scheme.
			'modern'  => [
				'link'       => '#3858e9',
				'link_focus' => '#183ad6',
			],
		];

		if ( $color_scheme === 'modern' ) {
			$colors = $colors['modern'];
		} else {
			$colors = $colors['default'];
		}

		return $colors;
	}
}