PluginProbe
Adminify – White Label, Admin Menu Editor, Login Customizer / 4.2.10
Adminify – White Label, Admin Menu Editor, Login Customizer v4.2.10
4.3.1 4.3.0 4.2.26 4.2.25 4.2.24 4.2.23 4.2.22 4.2.21 4.2.20 4.2.19 4.2.18 4.2.17 4.2.16 4.2.15 4.2.14 4.2.13 4.2.12 4.2.11 4.2.10 4.2.9 4.2.8 4.2.7 4.2.6 4.2.5 4.1.17 All 164 releases
adminify / Inc / Classes / DarkModeConflicts.php

DarkModeConflicts.php in Adminify – White Label, Admin Menu Editor, Login Customizer 4.2.10, at Inc/Classes/DarkModeConflicts.php

622 lines 25.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace PXLBSAdminify\Inc\Classes;
4
5 use PXLBSAdminify\Inc\Utils;
6 use PXLBSAdminify\Inc\Admin\AdminSettings;
7
8 // no direct access allowed
9 if (!defined('ABSPATH')) {
10 exit;
11 }
12 /**
13 * PXLBSAdminify
14 * Dark Mode Conflicts with other plugins supports
15 *
16 * @author Jewel Theme <support@jeweltheme.com>
17 */
18
19 class DarkModeConflicts
20 {
21 public $options;
22
23 public function __construct()
24 {
25 add_action('admin_enqueue_scripts', array($this, 'darkmode_scripts'), 100);
26 add_action( 'enqueue_block_editor_assets', array($this, "gutenberg_block_editor_darkmode_assets"));
27 // WP 6.3+/7.0: the block editor canvas runs in an iframe. The AdminifyDarkMode
28 // script has no built-in iframe support, so inject the same script INTO the
29 // iframe and call .enable() from inside — that way Darkreader runs over the
30 // iframe DOM the same dynamic way it runs on the parent admin.
31 // Use admin_footer (not enqueue_block_editor_assets — wp_add_inline_script
32 // silently dropped the bridge) and direct-print via wp_print_inline_script_tag.
33 add_action('admin_footer', array($this, 'inject_darkmode_into_editor_iframe'), 999);
34 // Classic editor (TinyMCE) renders the Visual tab inside its own iframe
35 // (#content_ifr). Same iframe-isolation problem as the block canvas: the
36 // parent Darkreader run can't reach the iframe DOM, so the editor body
37 // stays white in dark mode. Inject the same script into TinyMCE iframes.
38 add_action('admin_footer', array($this, 'inject_darkmode_into_classic_editor_iframe'), 999);
39 // customize.php controls: Adminify scripts are skipped there by design
40 // (Assets::should_skip_adminify_scripts), so enqueue dark-mode only on this
41 // dedicated hook to keep the customize panel dark without the rest of Adminify.
42 add_action('customize_controls_enqueue_scripts', array($this, 'customize_controls_darkmode_enqueue'));
43 // customize.php PREVIEW: the right-side theme preview renders inside its own
44 // iframe (a full frontend render). The controls-panel enqueue above never
45 // reaches it, so the previewed site stays light in dark mode. customize_preview_init
46 // fires inside the preview frame context — enqueue dark-mode there to darken the
47 // previewed theme the same dynamic Darkreader way, matching the classic editor.
48 add_action('customize_preview_init', array($this, 'customize_preview_darkmode_enqueue'));
49 }
50
51 public function darkmode_scripts()
52 {
53
54 $this->options = (array) AdminSettings::get_instance()->get();
55 $this->options = !empty($this->options['light_dark_mode']['admin_ui_mode']) ? $this->options['light_dark_mode']['admin_ui_mode'] : '';
56
57 if ($this->options == 'light') {
58 return;
59 }
60
61
62 $dark_mode_style = '.ReactModal__Content,
63 .select2-selection,
64 .select2-results__options,
65 .adminify-dark-mode.toplevel_page_aio-contact-lite,
66 .aio-contact-menu,
67 .bsr-action-form input.regular-text,
68 .select2-dropdown,
69 .form-cancel-btn,
70 .folders-tabs,
71 .folder-tab-menu,
72 .folder-tab-menu a,
73 .custom-checkbox span,
74 .preview-inner-box,
75 .preview-inner-box .form-options,
76 .media-buttons,
77 .popup-form-content,
78 .select2-results__option,
79 div.tagsinput,
80 .settings-tabs-list .nav-tab,
81 input[type=number],
82 .bulk-action-select .bulk-action-select__control,
83 .bulk-action-select__menu,
84 .wprf-section-fields,
85 .wprf-section-title,
86 .wprf-input-radio-option:not(.wprf-option-selected) .wprf-input-label,
87 .wprf-control-field .components-button,
88 .wprf-select__menu,
89 .wprf-select__control,
90 .wprf-tab-content,
91 .squirrly-seo-settings #wpcontent .bg-light,
92 .bootstrap-select,
93 .bg-white,
94 .wdt-addons-intro {
95 background: white !important;
96 }
97
98 .el-checkbox.is-checked ~ div,
99 .fluentcrm_header {
100 background: none!important;
101 }
102
103 .folder-user-settings .pro-feature-popup {
104 background: rgb(0, 0, 0, 0.4)
105 }
106
107 .big-pluspro-btn,
108 .dokan-btn,
109 .close_dp_help,
110 .dup-btn,
111 .folder-tab-menu a,
112 .pro-feature-popup .pro-feature-content > a,
113 .user-upgrade-inline-btn,
114 .pro-feature-popup .pro-feature-content .pro-user-title,
115 .pro-feature-popup .pro-feature-content .pro-user-desc,
116 .folder-access,
117 .add-new-folder,
118 .media-select option,
119 .popup-form-content,
120 .nf-button:hover,
121 .wp-react-form h1,
122 .wp-react-form h2,
123 .wp-react-form h3,
124 .wp-react-form h4,
125 .wprf-input-label,
126 .wprf-tab-nav-item:not(:hover),
127 .swift-btn,
128 .wpcode-button,
129 .wdt-constructor-type-selecter-block .card-body h4,
130 .wdt-constructor-type-selecter-block .card-body h4 span,
131 .yoast-button-upsell,
132 .aioseo-button:hover,
133 .el-button {
134 color: white !important;
135 }
136
137 .folders-tabs .dashicons-editor-help,
138 .folder-tab-menu a.active,
139 .folder-list li a span,
140 .select2-selection__rendered,
141 .fp-item-name,
142 .select2-results__option,
143 .form-sample,
144 input[type=number],
145 .wprf-select__single-value,
146 .wprf-code-viewer textarea,
147 .wdt-constructor-type-selecter-block .card-body span,
148 .mce-menu-item > span {
149 color: gray !important;
150 }
151
152 .select2-selection,
153 .bsr-action-form input.regular-text,
154 #bsr-table-select,
155 .custom-checkbox input+span,
156 .preview-inner-box,
157 div.tagsinput,
158 input[type=number],
159 .bulk-action-select .bulk-action-select__control,
160 .wprf-tab-nav-item,
161 .wprf-control-field .components-button,
162 .wprf-select__control,
163 .wprf-control-field input[type="checkbox"],
164 .bootstrap-select {
165 border-color: #D0D5DD !important;
166 }
167
168 .dokan-admin-header-logo img,
169 .dup-header img {
170 filter: grayscale(1) brightness(5);
171 }
172
173 .jetpack-logo,
174 .it-ui-list div[direction="horizontal"] > svg {
175 fill: black !important;
176 }
177
178 .jp-form-block-fade {
179 opacity: 0.5;
180 }
181 ';
182
183 // Elementor Style issues
184 // if (Utils::is_plugin_active('elementor/elementor.php')) {
185 // $dark_mode_style .= '.darkmode{
186 // background: white !important;
187 // }';
188 // }
189
190 // Better Links Style issues
191 if (Utils::is_plugin_active('betterlinks/betterlinks.php')) {
192 $dark_mode_style .= '#betterlinksbody .kpyoXL,
193 .btl-react-select__menu,
194 #betterlinksbody .jlDjrx {
195 background: white !important;
196 }
197 #betterlinksbody .kpyoXL{
198 color: white !important;
199 }
200 ';
201 }
202
203 // Forminator Style issues
204 if (Utils::is_plugin_active('forminator/forminator.php')) {
205 $dark_mode_style .= '.sui-box,
206 .sui-icon-plugin-2,
207 .sui-vertical-tab a.current,
208 .sui-wrap .fui-multi-answers,
209 .sui-wrap .fui-multi-answers .fui-answers>li,
210 .sui-dropdown.open ul,
211 .sui-notice-content,
212 .sui-wrap .sui-box-selectors,
213 .sui-select-dropdown,
214 .sui-accordion-item,
215 .sui-tabs-menu,
216 .forminator-addon-card--footer,
217 .sui-vertical-tab.current,
218 .sui-form-control,
219 select#forminator-field-user_role,
220 .forminator-save-field-settings {
221 background: white !important;
222 }
223
224 .sui-upgrade-page,
225 .sui-upgrade-page-header,
226 .sui-upgrade-page-cta {
227 background: none!important;
228 }
229
230 .sui-header-title,
231 .sui-summary-large,
232 .sui-list-label,
233 .sui-box-title,
234 .sui-wrap h1,
235 .sui-wrap h2,
236 .sui-wrap h3,
237 .sui-button,
238 .sui-vertical-tab a.current,
239 .sui-table thead>tr>th,
240 .sui-trim-text,
241 .sui-message-content h2,
242 .sui-tab-item.active,
243 .sui-vertical-tab.current a,
244 select#forminator-field-user_role {
245 color: white !important;
246 }
247
248 .sui-upsell-list li,
249 .sui-table-item-title,
250 .sui-vertical-tab a,
251 .sui-form-control,
252 .sui-settings-label {
253 color: gray !important;
254 }
255
256 .sui-list li,
257 .sui-box-header,
258 #sui-cross-sell-footer>div,
259 .sui-box-settings-row,
260 .sui-dropdown.open ul,
261 .sui-box-footer,
262 .sui-status-changes,
263 .sui-table thead>tr>th,
264 .sui-select-dropdown,
265 .sui-tab-content,
266 .forminator-addon-card--footer,
267 .sui-table.fui-table--apps,
268 .sui-table tbody>tr>td,
269 .sui-tabs-overflow,
270 .sui-form-control,
271 .sui-button,
272 select#forminator-field-user_role {
273 border-color: #D0D5DD !important;
274 }
275
276 .sui-dropdown.open ul::after,
277 .sui-dropdown.open ul::before {
278 border-color: #D0D5DD rgba(0, 0, 0, 0)!important;
279 }
280
281 .sui-box,
282 .sui-accordion-item,
283 .sui-tabs-menu {
284 box-shadow: none!important;
285 }
286
287 .sui-chartjs-message--empty {
288 background-blend-mode: exclusion;
289 }
290
291 .sui-tag,
292 .sui-tabs-menu .sui-tab-item {
293 background: #6f6f6f!important;
294 color: #fff!important;
295 }
296
297 .sui-tab-item.active {
298 background: black!important;
299 }
300 ';
301 }
302
303 // Loginpress
304 if (Utils::is_plugin_active('loginpress/loginpress.php')) {
305 $dark_mode_style .= '.loginpress-help-page pre textarea,
306 .loginpress-import-export-page .upload-file,
307 .loginpress-extension {
308 background: white !important;
309 }
310
311 .toplevel_page_loginpress-settings #wpcontent,
312 .loginpress_page_loginpress-help #wpcontent,
313 .loginpress_page_loginpress-import-export #wpcontent,
314 .loginpress-header-wrapper,
315 .loginpress-settings {
316 background: none!important;
317 }
318
319 .loginpress-help-page h2,
320 .loginpress-import-export-page h2,
321 .loginpress-addons-wrap h2,
322 .loginpress-extension h3 span,
323 .loginpress-settings h3{
324 color: white !important;
325 }
326
327 .loginpress-help-page pre textarea,
328 .loginpress-import-export-page > div,
329 .loginpress-settings .form-table tr th,
330 .loginpress-settings .form-table tr td fieldset label {
331 color: gray !important
332 }
333
334 .loginpress-help-page pre textarea,
335 .loginpress-import-export-page .upload-file,
336 .loginpress-extension h3,
337 .loginpress-extension {
338 border-color: #D0D5DD !important;
339 }
340
341 .loginpress-header-logo img {
342 filter: grayscale(1) brightness(5);
343 }
344
345 ';
346 }
347
348 // Notificationx Style issues
349 if (Utils::is_plugin_active('notificationx/notificationx.php')) {
350 $dark_mode_style .= '.nx-analytics-counter,
351 #notificationx .notificationx-items .nx-admin-menu>ul li:not(.nx-active) a,
352 .nx-admin-sidebar .sidebar-widget,
353 .nx-settings-right,
354 .nx-admin-block,
355 .nx-sidebar,
356 .nx-quick-builder-wrapper {
357 background: white !important;
358 }
359
360 .nx-button:not(:hover) {
361 background: none!important;
362 }
363
364 .nx-counter-number,
365 .nx-admin-title {
366 color: white !important;
367 }
368
369 #notificationx .notificationx-items .nx-admin-menu>ul li:not(.nx-active) a,
370 #nx-title,
371 #notification-template,
372 .nx-admin-sidebar-cta a:not(:hover) {
373 color: gray !important;
374 }
375
376 #notificationx .notificationx-items .nx-admin-menu>ul li:not(.nx-active) a,
377 #nx-title,
378 .nx-widget-title,
379 #notification-template {
380 border-color: #D0D5DD !important;
381 }
382
383 .nx-admin-sidebar-logo img {
384 filter: grayscale(1) brightness(5);
385 }
386
387 .nx-admin-header svg g {
388 fill: #fff!important;
389 }
390 ';
391 }
392
393 // Wpdatatables Style issues
394 if (Utils::is_plugin_active('wpdatatables/wpdatatables.php')) {
395 $dark_mode_style .= '.wpdt-c.toplevel_page_wpdatatables-dashboard,
396 .wpdt-c .wdt-datatables-admin-wrap .plugin-dashboard,
397 .wpdt-c.wpdatatables_page_wpdatatables-administration,
398 .card-header.wdt-admin-card-header.ch-alt,
399 #wdt-datatables-browse-table,
400 .manage-column,
401 .wpdt-c.wpdatatables_page_wpdatatables-constructor,
402 .wdt-constructor-type-selecter-block .card-header,
403 .wpdt-c,
404 .chart-wizard-breadcrumb,
405 .wpdt-c .chart-name,
406 .wpdt-c .render-engine {
407 background: white !important;
408 }
409
410 ';
411 }
412
413
414
415 $dark_mode_style = preg_replace('#/\*.*?\*/#s', '', $dark_mode_style);
416 $dark_mode_style = preg_replace('/\s*([{}|:;,])\s+/', '$1', $dark_mode_style);
417 $dark_mode_style = preg_replace('/\s\s+(.*)/', '$1', $dark_mode_style);
418 wp_add_inline_style('adminify-admin', wp_strip_all_tags($dark_mode_style));
419 }
420
421 /**
422 * Gutenberg Block Editor Dark Mode CSS
423 */
424 function gutenberg_block_editor_darkmode_assets () {
425
426 wp_register_style('adminify-gutenberg-dark', false, array(), PXLBSADMINIFY_VER);
427 wp_enqueue_style('adminify-gutenberg-dark');
428
429 // $parent_selector = 'body.wp-adminify.adminify-dark-mode';
430 $parent_selector = 'body.wp-adminify';
431
432 $dark_mode_style = "$parent_selector .components-modal__content .components-text,
433 $parent_selector .components-popover__content .components-text { color: black!important; }
434 $parent_selector .block-editor-block-inspector .components-tools-panel { border-top-color: #e0e0e0; }
435 $parent_selector .admin-ui-navigable-region .components-panel__header > div > button { color: black; }
436 $parent_selector .editor-sidebar__panel .editor-post-card-panel__header svg,
437 $parent_selector .commands-command-menu__container .commands-command-menu__header svg { fill: black; }
438 ";
439 wp_add_inline_style('adminify-gutenberg-dark', wp_strip_all_tags($dark_mode_style));
440 }
441
442 /**
443 * Resolve the active light/dark mode for the current user.
444 * Per-user `color_mode` meta takes precedence over the global setting.
445 * Returns 'light' | 'dark' | 'auto' | ''.
446 */
447 public function pxlbsadminify_resolve_color_mode()
448 {
449 $opts = (array) AdminSettings::get_instance()->get();
450 $global_mode = !empty($opts['light_dark_mode']['admin_ui_mode']) ? $opts['light_dark_mode']['admin_ui_mode'] : 'light';
451 $user_mode = get_user_meta(get_current_user_id(), 'color_mode', true);
452 return !empty($user_mode) ? $user_mode : $global_mode;
453 }
454
455 /**
456 * Inject the AdminifyDarkMode script INTO the WP 6.3+/7.0 block editor iframe
457 * canvas. The script attaches a global `window.AdminifyDarkMode` and uses a
458 * Darkreader-style dynamic theme that rewrites colors based on the running
459 * document — so it must be loaded inside the iframe's window to darken the
460 * canvas DOM, not just the parent admin chrome.
461 *
462 * The bridge below watches for `iframe[name="editor-canvas"]` (added/changed
463 * across edits or full-site editor route changes), injects the dark-mode JS
464 * into the iframe's document, and calls `AdminifyDarkMode.enable()` once it
465 * loads. `__adminifyDarkInjected` guards against double-injection.
466 */
467 public function inject_darkmode_into_editor_iframe()
468 {
469 $mode = $this->pxlbsadminify_resolve_color_mode();
470 if ( $mode === 'auto' ) {
471 $mode = 'system';
472 }
473 // 'dark' = always on; 'system' = follow OS prefers-color-scheme (decided client-side).
474 if ( $mode !== 'dark' && $mode !== 'system' ) {
475 return;
476 }
477 // Only run on block-editor pages (post.php / post-new.php / site editor).
478 $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
479 if ( ! $screen || ! method_exists( $screen, 'is_block_editor' ) || ! $screen->is_block_editor() ) {
480 // also accept Site Editor screen ids
481 $is_site_editor = $screen && in_array( $screen->id, array( 'site-editor', 'gutenberg_page_gutenberg-edit-site' ), true );
482 if ( ! $is_site_editor ) {
483 return;
484 }
485 }
486 $dark_js_url = PXLBSADMINIFY_ASSETS . 'admin/js/wp-adminify-dark-mode' . Utils::assets_ext( '.js' );
487 // For 'system' mode, only proceed when the OS currently prefers dark; otherwise bail
488 // out of the bridge entirely so the iframe stays light (matches the parent admin).
489 $apply_guard = ( $mode === 'system' )
490 ? 'if(!(window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches)){return;}'
491 : '';
492 $bridge = '(function(){'
493 . $apply_guard
494 . 'var URL=' . wp_json_encode( $dark_js_url ) . ';'
495 . 'function looksLikeEditor(ifr){try{if(ifr.name==="editor-canvas")return true;var d=ifr.contentDocument;return !!(d&&d.body&&d.body.classList&&(d.body.classList.contains("block-editor-iframe__body")||d.body.classList.contains("editor-styles-wrapper")));}catch(e){return false;}}'
496 . 'function activate(w){try{if(w&&w.AdminifyDarkMode){w.AdminifyDarkMode.enable({brightness:120});return true;}}catch(e){}return false;}'
497 . 'function inject(ifr){try{var d=ifr.contentDocument,w=ifr.contentWindow;if(!d||!w)return;if(w.__adminifyDM){activate(w);return;}w.__adminifyDM=true;if(activate(w))return;var s=d.createElement("script");s.src=URL;s.onload=function(){if(!activate(w)){setTimeout(function(){activate(w);},100);setTimeout(function(){activate(w);},500);}};(d.head||d.documentElement||d.body).appendChild(s);}catch(e){}}'
498 . 'var seen=new WeakSet();'
499 . 'function watch(ifr){if(seen.has(ifr))return;seen.add(ifr);inject(ifr);ifr.addEventListener("load",function(){try{ifr.contentWindow.__adminifyDM=false;}catch(e){}inject(ifr);});}'
500 . 'function scan(){var all=document.querySelectorAll("iframe");for(var i=0;i<all.length;i++){if(looksLikeEditor(all[i]))watch(all[i]);}}'
501 . 'if(document.readyState!=="loading"){scan();}else{document.addEventListener("DOMContentLoaded",scan);}'
502 . 'new MutationObserver(scan).observe(document.documentElement,{childList:true,subtree:true});'
503 . '}());';
504 if ( function_exists( 'wp_print_inline_script_tag' ) ) {
505 wp_print_inline_script_tag( $bridge );
506 } else {
507 echo '<script>' . $bridge . '</script>'; // phpcs:ignore WordPress.WP.EnqueuedResources
508 }
509 return; // sentinel — never reach legacy enqueue path below
510 }
511
512 /**
513 * Inject the AdminifyDarkMode script INTO every classic-editor TinyMCE iframe.
514 *
515 * The TinyMCE Visual tab renders post content inside an iframe (`#content_ifr`,
516 * generally `{editor_id}_ifr`) whose body carries the `mce-content-body` class.
517 * As with the block-editor canvas, the parent Darkreader run never touches the
518 * iframe document, so the editor background stays white in dark mode. The bridge
519 * below watches for TinyMCE iframes (created lazily, and re-created when toggling
520 * Visual/Text or initializing extra editors), injects the dark-mode JS into each
521 * iframe's document and calls `AdminifyDarkMode.enable()` from inside. `__adminifyDM`
522 * guards against double-injection per iframe window.
523 */
524 public function inject_darkmode_into_classic_editor_iframe()
525 {
526 $mode = $this->pxlbsadminify_resolve_color_mode();
527 if ( $mode === 'auto' ) {
528 $mode = 'system';
529 }
530 // 'dark' = always on; 'system' = follow OS prefers-color-scheme (decided client-side).
531 if ( $mode !== 'dark' && $mode !== 'system' ) {
532 return;
533 }
534 $dark_js_url = PXLBSADMINIFY_ASSETS . 'admin/js/wp-adminify-dark-mode' . Utils::assets_ext( '.js' );
535 // For 'system' mode, only proceed when the OS currently prefers dark; otherwise bail
536 // out of the bridge entirely so the iframe stays light (matches the parent admin).
537 $apply_guard = ( $mode === 'system' )
538 ? 'if(!(window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches)){return;}'
539 : '';
540 $bridge = '(function(){'
541 . $apply_guard
542 . 'var URL=' . wp_json_encode( $dark_js_url ) . ';'
543 . 'function looksLikeMCE(ifr){try{if(/_ifr$/.test(ifr.id||""))return true;var d=ifr.contentDocument;return !!(d&&d.body&&d.body.classList&&d.body.classList.contains("mce-content-body"));}catch(e){return false;}}'
544 . 'function activate(w){try{if(w&&w.AdminifyDarkMode){w.AdminifyDarkMode.enable({brightness:120});return true;}}catch(e){}return false;}'
545 . 'function inject(ifr){try{var d=ifr.contentDocument,w=ifr.contentWindow;if(!d||!w||!d.body)return;if(w.__adminifyDM){activate(w);return;}w.__adminifyDM=true;if(activate(w))return;var s=d.createElement("script");s.src=URL;s.onload=function(){if(!activate(w)){setTimeout(function(){activate(w);},100);setTimeout(function(){activate(w);},500);}};(d.head||d.documentElement||d.body).appendChild(s);}catch(e){}}'
546 . 'var seen=new WeakSet();'
547 . 'function watch(ifr){if(seen.has(ifr))return;seen.add(ifr);inject(ifr);ifr.addEventListener("load",function(){try{ifr.contentWindow.__adminifyDM=false;}catch(e){}inject(ifr);});}'
548 . 'function scan(){var all=document.querySelectorAll("iframe");for(var i=0;i<all.length;i++){if(looksLikeMCE(all[i]))watch(all[i]);}}'
549 . 'if(document.readyState!=="loading"){scan();}else{document.addEventListener("DOMContentLoaded",scan);}'
550 . 'new MutationObserver(scan).observe(document.documentElement,{childList:true,subtree:true});'
551 . '}());';
552 if ( function_exists( 'wp_print_inline_script_tag' ) ) {
553 wp_print_inline_script_tag( $bridge );
554 } else {
555 echo '<script>' . $bridge . '</script>'; // phpcs:ignore WordPress.WP.EnqueuedResources
556 }
557 }
558
559 /**
560 * customize.php controls: Adminify's general scripts are deliberately skipped on
561 * customize.php (Assets::should_skip_adminify_scripts), so dark-mode never reaches
562 * the controls panel. Enqueue dark-mode standalone on the customize controls hook.
563 */
564 public function customize_controls_darkmode_enqueue()
565 {
566 $mode = $this->pxlbsadminify_resolve_color_mode();
567 if ($mode === 'auto') {
568 $mode = 'system';
569 }
570 if ($mode !== 'dark' && $mode !== 'system') {
571 return;
572 }
573 wp_enqueue_script(
574 'adminify--dark-mode',
575 PXLBSADMINIFY_ASSETS . 'admin/js/wp-adminify-dark-mode' . Utils::assets_ext('.js'),
576 array(),
577 PXLBSADMINIFY_VER,
578 false
579 );
580 wp_add_inline_script('adminify--dark-mode', $this->darkmode_enable_inline($mode));
581 }
582
583 /**
584 * Build the inline enable() snippet. For 'dark' it always enables; for 'system' it
585 * enables only when the OS currently prefers dark (prefers-color-scheme), matching
586 * the parent-admin behavior in Assets::header_scripts.
587 */
588 private function darkmode_enable_inline($mode)
589 {
590 $enable = ($mode === 'system')
591 ? 'if(window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches){window.AdminifyDarkMode.enable({brightness:120});}'
592 : 'window.AdminifyDarkMode.enable({brightness:120});';
593 return 'if(window.AdminifyDarkMode){' . $enable . '}'
594 . 'addEventListener("load",function(){if(window.AdminifyDarkMode){' . $enable . '}});';
595 }
596
597 /**
598 * customize.php preview: the previewed theme renders inside the preview iframe,
599 * which the controls-panel enqueue never reaches. customize_preview_init runs in
600 * the preview frame's frontend context, so enqueue the dark-mode JS here and call
601 * .enable() to darken the previewed site dynamically — same as the classic editor.
602 */
603 public function customize_preview_darkmode_enqueue()
604 {
605 $mode = $this->pxlbsadminify_resolve_color_mode();
606 if ($mode === 'auto') {
607 $mode = 'system';
608 }
609 if ($mode !== 'dark' && $mode !== 'system') {
610 return;
611 }
612 wp_enqueue_script(
613 'adminify--dark-mode',
614 PXLBSADMINIFY_ASSETS . 'admin/js/wp-adminify-dark-mode' . Utils::assets_ext('.js'),
615 array(),
616 PXLBSADMINIFY_VER,
617 false
618 );
619 wp_add_inline_script('adminify--dark-mode', $this->darkmode_enable_inline($mode));
620 }
621 }
622