PluginProbe
Adminify – White Label, Admin Menu Editor, Login Customizer / 4.2.18
Adminify – White Label, Admin Menu Editor, Login Customizer v4.2.18
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.18, at Inc/Classes/DarkModeConflicts.php

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