11import { map } from 'lodash' ;
22
3- import { PluginSidebar , PluginSidebarMoreMenuItem } from '@wordpress/editor' ;
3+ import { PluginSidebar , PluginSidebarMoreMenuItem , store as editorStore } from '@wordpress/editor' ;
44import { __ } from '@wordpress/i18n' ;
5- import { Fragment , useState } from '@wordpress/element' ;
6- import { PanelBody , Button } from '@wordpress/components' ;
5+ import { Fragment , useState , useEffect , useRef } from '@wordpress/element' ;
6+ import { PanelBody , Button , ToggleControl } from '@wordpress/components' ;
77import { applyFilters } from '@wordpress/hooks' ;
8+ import { useSelect , useDispatch } from '@wordpress/data' ;
9+ import { external } from '@wordpress/icons' ;
10+ import { store as coreStore } from '@wordpress/core-data' ;
11+ import { store as preferencesStore } from '@wordpress/preferences' ;
12+ import { store as noticesStore } from '@wordpress/notices' ;
13+ import { addQueryArgs } from '@wordpress/url' ;
814/**
915 * Import Icons
1016 */
@@ -26,6 +32,166 @@ import ExportDefaults from './block-defaults/export-defaults';
2632import ImportDefaults from './block-defaults/import-defaults' ;
2733import ResetDefaults from './block-defaults/reset-defaults' ;
2834import DefaultEditorBlock from './default-editor-block' ;
35+
36+ // Optimizer constants - matching the PHP version
37+ const META_KEY = '_kb_optimizer_status' ;
38+ const STATUS_EXCLUDED = - 1 ;
39+ const STATUS_UNOPTIMIZED = 0 ;
40+ const STATUS_OPTIMIZED = 1 ;
41+
42+ /**
43+ * Custom hook to get the performance optimizer enabled setting
44+ * @returns {boolean } Whether the optimizer is enabled
45+ */
46+ function useOptimizerEnabled ( ) {
47+ const globalSettings = kadence_blocks_params . globalSettings ? JSON . parse ( kadence_blocks_params . globalSettings ) : { } ;
48+ return globalSettings ?. performance_optimizer_enabled === true ;
49+ }
50+
51+ /**
52+ * Performance Optimizer toggle component that uses the shared hook
53+ * This ensures we use the same state source for both the toggle and conditional panel
54+ */
55+ function PerformanceOptimizerToggle ( ) {
56+ const isOptimizerEnabled = useOptimizerEnabled ( ) ;
57+ const [ isSaving , setIsSaving ] = useState ( false ) ;
58+ const { createSuccessNotice } = useDispatch ( noticesStore ) ;
59+
60+ const saveConfig = ( value ) => {
61+ setIsSaving ( true ) ;
62+ const config = kadence_blocks_params . globalSettings ? JSON . parse ( kadence_blocks_params . globalSettings ) : { } ;
63+ config . performance_optimizer_enabled = value ;
64+ const settingModel = new wp . api . models . Settings ( { kadence_blocks_settings : JSON . stringify ( config ) } ) ;
65+
66+ settingModel . save ( ) . then ( ( response ) => {
67+ createSuccessNotice ( __ ( 'Settings saved' , 'kadence-blocks' ) , {
68+ type : 'snackbar' ,
69+ } ) ;
70+
71+ setIsSaving ( false ) ;
72+ kadence_blocks_params . globalSettings = JSON . stringify ( config ) ;
73+ // Reload the page to load/unload the external optimizer JavaScript.
74+ window . location . reload ( ) ;
75+ } ) ;
76+ } ;
77+
78+ return (
79+ < ToggleControl
80+ label = { __ ( 'Globally Enable The Performance Optimizer' , 'kadence-blocks' ) }
81+ isBusy = { isSaving }
82+ checked = { isOptimizerEnabled }
83+ onChange = { ( value ) => {
84+ saveConfig ( value ) ;
85+ } }
86+ />
87+ ) ;
88+ }
89+
90+ /**
91+ * Component for excluding the current post from optimization
92+ */
93+ function OptimizerExcludeToggle ( ) {
94+ const meta = useSelect ( ( select ) => select ( 'core/editor' ) . getEditedPostAttribute ( 'meta' ) ) ;
95+ const savedMeta = useSelect ( ( select ) => select ( 'core/editor' ) . getCurrentPostAttribute ( 'meta' ) ) ;
96+ const { editPost } = useDispatch ( 'core/editor' ) ;
97+ const originalMetaValue = useRef ( null ) ;
98+
99+ // Capture the original meta value when it first becomes available, before any edits.
100+ useEffect ( ( ) => {
101+ if ( savedMeta !== undefined && originalMetaValue . current === null ) {
102+ // Capture the value from the saved post, not the edited version
103+ if ( savedMeta && savedMeta [ META_KEY ] !== undefined ) {
104+ originalMetaValue . current = savedMeta [ META_KEY ] ;
105+ } else {
106+ // If no saved value exists, default to unoptimized
107+ originalMetaValue . current = STATUS_UNOPTIMIZED ;
108+ }
109+ }
110+ } , [ savedMeta ] ) ;
111+
112+ if ( meta === undefined ) {
113+ return null ;
114+ }
115+
116+ return (
117+ < ToggleControl
118+ label = { __ ( 'Exclude this post from optimization' , 'kadence-blocks' ) }
119+ checked = { meta [ META_KEY ] === STATUS_EXCLUDED }
120+ onChange = { ( value ) => {
121+ if ( value ) {
122+ // When checking, set to excluded
123+ editPost ( { meta : { [ META_KEY ] : STATUS_EXCLUDED } } ) ;
124+ } else {
125+ // When unchecking, restore to original value (or unoptimized if original was excluded)
126+ const restoreValue =
127+ originalMetaValue . current !== null && originalMetaValue . current !== STATUS_EXCLUDED
128+ ? originalMetaValue . current
129+ : STATUS_UNOPTIMIZED ;
130+ editPost ( { meta : { [ META_KEY ] : restoreValue } } ) ;
131+ }
132+ } }
133+ />
134+ ) ;
135+ }
136+
137+ /**
138+ * Component for viewing the optimized version of a post
139+ */
140+ function OptimizedViewLink ( ) {
141+ const { hasLoaded, permalink, isPublished, label, meta, showIconLabels } = useSelect ( ( select ) => {
142+ const editor = select ( editorStore ) ;
143+ const { get } = select ( preferencesStore ) ;
144+
145+ // Get post type for label.
146+ const postTypeSlug = editor . getCurrentPostType ( ) ;
147+ const postType = select ( coreStore ) . getPostType ( postTypeSlug ) ;
148+ const postTypeLabel = postType ?. labels ?. singular_name || 'Post' ;
149+ const dynamicLabel = __ ( 'View Optimized' , 'kadence-blocks' ) + ' ' + postTypeLabel ;
150+
151+ return {
152+ permalink : editor . getPermalink ( ) ,
153+ isPublished : editor . isCurrentPostPublished ( ) ,
154+ label : dynamicLabel ,
155+ hasLoaded : ! ! postType ,
156+ meta : editor . getEditedPostAttribute ( 'meta' ) ,
157+ showIconLabels : get ( 'core' , 'showIconLabels' ) ,
158+ } ;
159+ } , [ ] ) ;
160+
161+ if ( ! isPublished || ! permalink || ! hasLoaded ) {
162+ return null ;
163+ }
164+
165+ if ( meta !== undefined && meta [ META_KEY ] !== STATUS_OPTIMIZED ) {
166+ return null ;
167+ }
168+
169+ const optimizerData = window . kbOptimizer || { } ;
170+ const nonce = optimizerData . token ;
171+
172+ const url = addQueryArgs ( permalink , {
173+ perf_token : nonce ,
174+ kb_optimizer_preview : 1 ,
175+ } ) ;
176+
177+ return (
178+ < div style = { { marginTop : '12px' } } >
179+ < Button
180+ style = { { paddingLeft : 0 } }
181+ icon = { external }
182+ iconPosition = { 'right' }
183+ label = { label }
184+ href = { url }
185+ target = "_blank"
186+ showTooltip = { ! showIconLabels }
187+ size = "compact"
188+ >
189+ { label }
190+ </ Button >
191+ </ div >
192+ ) ;
193+ }
194+
29195/**
30196 * Build the row edit
31197 */
@@ -40,6 +206,10 @@ function KadenceConfig() {
40206 const [ controlIcon , setControlIcon ] = useState (
41207 applyFilters ( 'kadence.block_sidebar_control_icon' , BlockIcons . kadenceNewIcon )
42208 ) ;
209+
210+ // Get the performance optimizer enabled setting using the shared hook
211+ const isOptimizerEnabled = useOptimizerEnabled ( ) ;
212+
43213 return (
44214 < Fragment >
45215 < PluginSidebarMoreMenuItem target = "kadence-controls" icon = { controlIcon } >
@@ -754,14 +924,14 @@ function KadenceConfig() {
754924 />
755925 </ PanelBody >
756926 < PanelBody title = { __ ( 'Performance Optimizer' , 'kadence-blocks' ) } initialOpen = { false } >
757- < KadenceSetting
758- slug = { 'performance_optimizer_enabled' }
759- label = { __ ( 'Globally Enable The Performance Optimizer' , 'kadence-blocks' ) }
760- type = { 'toggle' }
761- theDefault = { false }
762- // Reload the page to load/unload the external optimizer JavaScript.
763- successCallback = { ( ) => window . location . reload ( ) }
764- />
927+ < PerformanceOptimizerToggle />
928+
929+ { isOptimizerEnabled && (
930+ < >
931+ < OptimizerExcludeToggle />
932+ < OptimizedViewLink />
933+ </ >
934+ ) }
765935 </ PanelBody >
766936 < PanelBody title = { __ ( 'Custom CSS Indicator' , 'kadence-blocks' ) } initialOpen = { false } >
767937 < KadenceSetting
0 commit comments