PluginProbe
Darkify – Dark Mode & Night Mode for Website & Admin (Dark Theme Included) / 2.1.3
Darkify – Dark Mode & Night Mode for Website & Admin (Dark Theme Included) v2.1.3
2.1.3 2.1.2 2.1.1 2.1.0 2.0.4 2.0.3 2.0.2 2.0.1 2.0.0 1.5.5 1.5.4 1.5.3 1.5.2 1.5.1 1.5.0 trunk 1.0.1 1.1.0 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.3.0 All 57 releases
darkify / src / Admin / Views / Control.php

Control.php in Darkify – Dark Mode & Night Mode for Website & Admin (Dark Theme Included) 2.1.3, at src/Admin/Views/Control.php

539 lines 36.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Control class for Control options.
5 *
6 * @link https://themeatelier.net
7 * @since 1.0.0
8 *
9 * @package darkify
10 * @subpackage darkify/src/Admin/Views/Control
11 * @author ThemeAtelier<themeatelierbd@gmail.com>
12 */
13
14 namespace ThemeAtelier\Darkify\Admin\Views;
15
16 use ThemeAtelier\Darkify\Admin\Schema\SchemaRegistry as Darkify;
17
18 class Control
19 {
20 /**
21 * Create Option fields for the setting options.
22 *
23 * @param string $prefix Option setting key prefix.
24 * @return void
25 */
26 public static function options($prefix)
27 {
28 Darkify::createSection(
29 $prefix,
30 array(
31 // Explicit, locale-independent id. Without it the REST layer falls
32 // back to sanitize_title() of the *translated* title, so the route
33 // became #/sterowanie on a Polish site and every link 404'd inside
34 // the SPA. Value matches the old English slug so existing
35 // `#tab=` / `#/controls` bookmarks keep resolving.
36 'id' => 'controls',
37 'title' => esc_html__('Controls', 'darkify'),
38 'icon' => 'icofont-ui-settings',
39 'fields' => array(
40 array(
41 'type' => 'section_tab',
42 'tabs' => array(
43
44 array(
45 'id' => 'frontend',
46 'title' => esc_html__('Frontend', 'darkify'),
47 'icon' => 'icofont-computer',
48 'fields' => array(
49 // Intro line with a docs link, rendered plain above the section cards.
50 array(
51 'type' => 'page_hint',
52 'content' => sprintf(
53 /* translators: %s: documentation link */
54 __('Decide how and when dark mode turns on for visitors on your public website. %s', 'darkify'),
55 '<a href="https://darkifywp.com/docs/" target="_blank" rel="noopener noreferrer">' . esc_html__('View documentation', 'darkify') . '</a>'
56 ),
57 ),
58
59 // ===== AVAILABILITY =====
60 array(
61 'type' => 'heading',
62 'title' => esc_html__('Availability', 'darkify'),
63 'section_start' => true,
64 ),
65 array(
66 'id' => 'enable_dark_mode_switch',
67 'type' => 'switcher',
68 'title' => esc_html__('Frontend Dark Mode', 'darkify'),
69 'title_help' => '<div class="darkify-info-label">' .
70 __('Show the dark mode floating switch on your website frontend. This is the master control for everything below.', 'darkify') .
71 '</div>' . '' . '',
72 'text_on' => esc_html__('Enabled', 'darkify'),
73 'text_off' => esc_html__('Disabled', 'darkify'),
74 'text_width' => 100,
75 'default' => true,
76 // Commit instantly (master toggle governs the whole frontend feature).
77 'auto_save' => true,
78 ),
79 array(
80 'id' => 'enable_default_dark_mode',
81 'type' => 'switcher',
82 'title' => esc_html__('Default Dark Mode', 'darkify'),
83 'title_help' =>
84 '<div class="darkify-info-label">' .
85 __('Enable dark mode by default on your website.', 'darkify') .
86 '</div>' .
87 '' .
88 '',
89 'text_on' => esc_html__('Enabled', 'darkify'),
90 'text_off' => esc_html__('Disabled', 'darkify'),
91 'text_width' => 100,
92 // Commit instantly (the priority notice depends on it, which would
93 // otherwise force the manual-Save workflow).
94 'auto_save' => true,
95 ),
96 array(
97 'id' => 'enable_os_aware',
98 'type' => 'switcher',
99 'title' => esc_html__('OS Aware Dark Mode', 'darkify'),
100 'title_help' =>
101 '<div class="darkify-info-label">' .
102 __('Toggle dark mode based on the user’s device or operating system preference.', 'darkify') .
103 '</div>' .
104 '' .
105 '',
106 'text_on' => esc_html__('Enabled', 'darkify'),
107 'text_off' => esc_html__('Disabled', 'darkify'),
108 'text_width' => 100,
109 'default' => true,
110 // Commit instantly (the priority notice depends on it).
111 'auto_save' => true,
112 ),
113 // Priority notice: shown only when Default Dark Mode AND OS Aware are both on.
114 array(
115 'type' => 'submessage',
116 'style' => 'info',
117 'content' => '<strong>' . esc_html__('OS Aware takes priority.', 'darkify') . '</strong> ' . esc_html__('Both are on, so visitors following the system “dark” setting get dark mode automatically; Default Dark Mode applies only when no system preference is detected.', 'darkify'),
118 'dependency' => array('enable_default_dark_mode|enable_os_aware', '==|==', 'true|true'),
119 ),
120
121 // ===== ACTIVATION =====
122 array(
123 'type' => 'heading',
124 'title' => esc_html__('Activation', 'darkify'),
125 'section_start' => true,
126 ),
127 array(
128 'id' => 'enable_keyboard_shortcut',
129 'type' => 'switcher',
130 'title' => esc_html__('Keyboard Shortcut', 'darkify'),
131 'title_help' =>
132 '<div class="darkify-info-label">' .
133 __('Let visitors toggle dark mode with a keyboard shortcut.', 'darkify') .
134 '</div>' .
135 '' .
136 '',
137 'text_on' => esc_html__('Enabled', 'darkify'),
138 'text_off' => esc_html__('Disabled', 'darkify'),
139 'text_width' => 100,
140 'default' => true,
141 // Commit instantly (the shortcut-keys field depends on it).
142 'auto_save' => true,
143 ),
144 // Editable shortcut combo (shown when the shortcut is enabled).
145 array(
146 'id' => 'keyboard_shortcut_keys',
147 'type' => 'keyboard_shortcut',
148 'default' => 'ctrl+alt+d',
149 'dependency' => array('enable_keyboard_shortcut', '==', 'true'),
150 ),
151 // Enable Time Based Auto Dark Mode
152 array(
153 'id' => 'enable_time',
154 'type' => 'fieldset',
155 'fields' => array(
156 array(
157 'id' => 'enable_time_based_dark',
158 'type' => 'switcher',
159 'title' => esc_html__('Time Based Auto Dark Mode', 'darkify'),
160 'title_help' =>
161 '<div class="darkify-info-label">' .
162 __('Automatically enable dark mode based on the user’s local time.', 'darkify') .
163 '</div>' .
164 '' .
165 '',
166 'text_on' => esc_html__('Enabled', 'darkify'),
167 'text_off' => esc_html__('Disabled', 'darkify'),
168 'text_width' => 100,
169 ),
170 array(
171 'id' => 'enable_time_fields',
172 'type' => 'fieldset',
173 'class' => 'enable_time_fields',
174 'dependency' => array('enable_time_based_dark', '==', 'true'),
175 'title' => esc_html__('Pick a Time', 'darkify'),
176 'title_help' =>
177 '<div class="darkify-info-label">' .
178 __('Set the exact start and end times when dark mode should be automatically enabled or disabled.', 'darkify') .
179 '</div>' .
180 '' .
181 '',
182 'fields' => array(
183 /*
184 * Which clock drives the schedule. Darkify Lite ships
185 * only "fixed" (the start/end window below); the
186 * sunrise/sunset schedule is a Pro feature, so its
187 * option row carries `pro_only` — the REST layer turns
188 * that into the `pro_options` stamp the React admin
189 * renders as a locked, badged preview, and
190 * strip_pro_keys() refuses to persist the value even
191 * if a crafted request sends it.
192 */
193 array(
194 'id' => 'time_based_dark_mode',
195 'type' => 'button_set',
196 'default' => 'fixed',
197 'options' => array(
198 'fixed' => esc_html__('Fixed times', 'darkify'),
199 'suncycle' => array(
200 'text' => esc_html__('Sunrise & sunset', 'darkify'),
201 'pro_only' => true,
202 ),
203 ),
204 ),
205 array(
206 'id' => 'time_based_dark_start',
207 'type' => 'datetime',
208 'after' => esc_html__('From', 'darkify'),
209 'placeholder' => esc_html__('From', 'darkify'),
210 'settings' => array(
211 'noCalendar' => true,
212 'enableTime' => true,
213 'dateFormat' => 'H:i',
214 'time_24hr' => false,
215 ),
216 ),
217 array(
218 'id' => 'time_based_dark_end',
219 'type' => 'datetime',
220 'after' => esc_html__('To', 'darkify'),
221 'placeholder' => esc_html__('To', 'darkify'),
222 'settings' => array(
223 'noCalendar' => true,
224 'enableTime' => true,
225 'dateFormat' => 'H:i',
226 'time_24hr' => false,
227 ),
228 ),
229 ),
230 ),
231 ),
232 ),
233 ),
234 ),
235 array(
236 'id' => 'admin',
237 'title' => esc_html__('Admin', 'darkify'),
238 'icon' => 'icofont-dashboard-web',
239 'fields' => array(
240 // Intro line with a docs link, rendered plain above the section cards.
241 array(
242 'type' => 'page_hint',
243 'content' => sprintf(
244 /* translators: %s: documentation link */
245 __('Bring dark mode to the WordPress admin dashboard and editors. %s', 'darkify'),
246 '<a href="https://darkifywp.com/docs/" target="_blank" rel="noopener noreferrer">' . esc_html__('View documentation', 'darkify') . '</a>'
247 ),
248 ),
249 // ===== ADMIN APPEARANCE =====
250 array(
251 'type' => 'heading',
252 'title' => esc_html__('Admin Appearance', 'darkify'),
253 'section_start' => true,
254 ),
255 array(
256 'id' => 'enable_admin_panel_dark_mode',
257 'type' => 'switcher',
258 'title' => esc_html__('Admin Panel Dark Mode', 'darkify'),
259 'title_help' =>
260 '<div class="darkify-info-label">' .
261 __('Enable dark mode in the WordPress admin dashboard.', 'darkify') .
262 '</div>' .
263 '' .
264 '',
265 'text_on' => esc_html__('Enabled', 'darkify'),
266 'text_off' => esc_html__('Disabled', 'darkify'),
267 'default' => false,
268 'text_width' => 100,
269 // Commit instantly even though other fields depend on it.
270 'auto_save' => true,
271 ),
272
273 /*
274 * Admin palettes are separate from the frontend's `color_pallets`
275 * and from each other. wp-admin is rendered by Dark Reader, which
276 * derives a colour per source colour; a preset overrides only the
277 * page background and text colour and lets it derive the rest.
278 *
279 * "Auto" is the default and the recommended value: pinning those two
280 * flattens distinctions the derivation would otherwise keep, which
281 * matters most on admin screens built by other plugins.
282 *
283 * Only the five presets darkify_apply_palette() actually defines are
284 * listed. The block editor's toolbar dropdown offers more than that
285 * and silently falls back for the rest — do not copy that list here.
286 *
287 * The swatch colours match the toolbar dropdown (.darkify-dropdown in
288 * src/assets/css/client_main.css) so the same preset is recognisable
289 * in both places. "Auto" shows a gradient: it has no single colour.
290 *
291 * These are the site-wide default. The editor's toolbar dropdown
292 * still writes a per-user choice to localStorage, which wins for
293 * that user — the same relationship the toolbar has always had.
294 */
295 array(
296 'id' => 'admin_panel_palette',
297 'type' => 'select',
298 'title' => esc_html__('Admin Panel Palette', 'darkify'),
299 'title_help' =>
300 '<div class="darkify-info-label">' .
301 __('Color preset for the WordPress admin. Auto lets Darkify derive each color from the original.', 'darkify') .
302 '</div>',
303 'default' => 'auto',
304 'options' => array(
305 'auto' => array(
306 'text' => esc_html__('Auto (recommended)', 'darkify'),
307 'swatch' => 'linear-gradient(135deg, #0f0f0f 0%, #3a3a3a 50%, #8f8f8f 100%)',
308 ),
309 'set1' => array(
310 'text' => esc_html__('Carbon Mist', 'darkify'),
311 'swatch' => '#171717',
312 ),
313 'set3' => array(
314 'text' => esc_html__('Midnight Reverie', 'darkify'),
315 'swatch' => '#4e478d',
316 ),
317 'set9' => array(
318 'text' => esc_html__('Verdant Depths', 'darkify'),
319 'swatch' => '#073d2f',
320 ),
321 'set6' => array(
322 'text' => esc_html__('Celestial Tide', 'darkify'),
323 'swatch' => '#144e78',
324 ),
325 'set10' => array(
326 'text' => esc_html__('Emberwood', 'darkify'),
327 'swatch' => '#372911',
328 ),
329
330 /*
331 * Pro presets, listed after every one that works here so the
332 * usable list is not diluted at the top.
333 *
334 * These are not new upsell surface. The block editor's toolbar
335 * dropdown has always offered all eleven names while
336 * darkify_apply_palette() defines only five, so picking one of
337 * these silently rendered Carbon Mist — they looked broken
338 * rather than gated. Marking them is what makes that honest.
339 *
340 * `pro_only` is the whole mechanism: locked_option_keys() turns
341 * it into the `pro_options` stamp the React admin renders as a
342 * disabled, badged row, and strip_pro_keys() refuses to persist
343 * the value even if a crafted request sends it.
344 */
345 'set2' => array(
346 'text' => esc_html__('Glacier Drift', 'darkify'),
347 'swatch' => '#123d52',
348 'pro_only' => true,
349 ),
350 'set4' => array(
351 'text' => esc_html__('Indigo Veil', 'darkify'),
352 'swatch' => '#46598c',
353 'pro_only' => true,
354 ),
355 'set5' => array(
356 'text' => esc_html__('Duskmire', 'darkify'),
357 'swatch' => '#403953',
358 'pro_only' => true,
359 ),
360 'set7' => array(
361 'text' => esc_html__('Tidal Frost', 'darkify'),
362 'swatch' => '#286f8d',
363 'pro_only' => true,
364 ),
365 'set8' => array(
366 'text' => esc_html__('Blue Bastion', 'darkify'),
367 'swatch' => '#244892',
368 'pro_only' => true,
369 ),
370 'set11' => array(
371 'text' => esc_html__('Crimson Veil', 'darkify'),
372 'swatch' => '#440649',
373 'pro_only' => true,
374 ),
375 ),
376 'dependency' => array('enable_admin_panel_dark_mode', '==', 'true'),
377 ),
378
379 array(
380 'id' => 'block_editor_dark_mode',
381 'type' => 'switcher',
382 'title' => esc_html__('Block Editor Dark Mode', 'darkify'),
383 'title_help' =>
384 '<div class="darkify-info-label">' .
385 __('Enable the dark mode switch in the block editor to toggle between dark and light mode.', 'darkify') .
386 '</div>' .
387 '' .
388 '',
389 'text_on' => esc_html__('Enabled', 'darkify'),
390 'text_off' => esc_html__('Disabled', 'darkify'),
391 'default' => false,
392 'text_width' => 100,
393 ),
394 array(
395 'id' => 'block_editor_palette',
396 'type' => 'select',
397 'title' => esc_html__('Block Editor Palette', 'darkify'),
398 'title_help' =>
399 '<div class="darkify-info-label">' .
400 __('Color preset for the block editor, independent of the rest of the admin.', 'darkify') .
401 '</div>',
402 'default' => 'auto',
403 'options' => array(
404 'auto' => array(
405 'text' => esc_html__('Auto (recommended)', 'darkify'),
406 'swatch' => 'linear-gradient(135deg, #0f0f0f 0%, #3a3a3a 50%, #8f8f8f 100%)',
407 ),
408 'set1' => array(
409 'text' => esc_html__('Carbon Mist', 'darkify'),
410 'swatch' => '#171717',
411 ),
412 'set3' => array(
413 'text' => esc_html__('Midnight Reverie', 'darkify'),
414 'swatch' => '#4e478d',
415 ),
416 'set9' => array(
417 'text' => esc_html__('Verdant Depths', 'darkify'),
418 'swatch' => '#073d2f',
419 ),
420 'set6' => array(
421 'text' => esc_html__('Celestial Tide', 'darkify'),
422 'swatch' => '#144e78',
423 ),
424 'set10' => array(
425 'text' => esc_html__('Emberwood', 'darkify'),
426 'swatch' => '#372911',
427 ),
428
429 /*
430 * Pro presets, listed after every one that works here so the
431 * usable list is not diluted at the top.
432 *
433 * These are not new upsell surface. The block editor's toolbar
434 * dropdown has always offered all eleven names while
435 * darkify_apply_palette() defines only five, so picking one of
436 * these silently rendered Carbon Mist — they looked broken
437 * rather than gated. Marking them is what makes that honest.
438 *
439 * `pro_only` is the whole mechanism: locked_option_keys() turns
440 * it into the `pro_options` stamp the React admin renders as a
441 * disabled, badged row, and strip_pro_keys() refuses to persist
442 * the value even if a crafted request sends it.
443 */
444 'set2' => array(
445 'text' => esc_html__('Glacier Drift', 'darkify'),
446 'swatch' => '#123d52',
447 'pro_only' => true,
448 ),
449 'set4' => array(
450 'text' => esc_html__('Indigo Veil', 'darkify'),
451 'swatch' => '#46598c',
452 'pro_only' => true,
453 ),
454 'set5' => array(
455 'text' => esc_html__('Duskmire', 'darkify'),
456 'swatch' => '#403953',
457 'pro_only' => true,
458 ),
459 'set7' => array(
460 'text' => esc_html__('Tidal Frost', 'darkify'),
461 'swatch' => '#286f8d',
462 'pro_only' => true,
463 ),
464 'set8' => array(
465 'text' => esc_html__('Blue Bastion', 'darkify'),
466 'swatch' => '#244892',
467 'pro_only' => true,
468 ),
469 'set11' => array(
470 'text' => esc_html__('Crimson Veil', 'darkify'),
471 'swatch' => '#440649',
472 'pro_only' => true,
473 ),
474 ),
475 'dependency' => array('block_editor_dark_mode', '==', 'true'),
476 ),
477
478 array(
479 'id' => 'classic_editor_dark_mode',
480 'type' => 'switcher',
481 'title' => esc_html__('Classic Editor Dark Mode', 'darkify'),
482 'title_help' =>
483 '<div class="darkify-info-label">' .
484 __('Enable the dark mode switch in the classic editor to toggle between dark and light modes.', 'darkify') .
485 '</div>' .
486 '' .
487 '',
488 'text_on' => esc_html__('Enabled', 'darkify'),
489 'text_off' => esc_html__('Disabled', 'darkify'),
490
491 'default' => false,
492 'text_width' => 100,
493 ),
494
495 // ===== SCOPE & CUSTOMIZATION =====
496 array(
497 'type' => 'heading',
498 'title' => esc_html__('Scope & Customization', 'darkify'),
499 'section_start' => true,
500 'dependency' => array('enable_admin_panel_dark_mode', '==', 'true'),
501 ),
502 array(
503 'id' => 'disallowed_admin_pages',
504 'type' => 'textarea',
505 'title' => esc_html__('Disallowed Pages', 'darkify'),
506 'title_help' => '<div class="darkify-info-text">' .
507 __('If an admin page URL looks like http://example.com/wp-admin/admin.php?page=darkify, then "darkify" is the page slug.', 'darkify') .
508 '</div>' .
509 '' .
510 '',
511 'placeholder' => esc_html__('Enter comma-separated page slugs. Example: darkify-dashboard, elementor', 'darkify'),
512 'dependency' => array('enable_admin_panel_dark_mode', '==', 'true'),
513 'class' => 'only_pro'
514 ),
515 array(
516 'id' => 'admin_custom_css',
517 'type' => 'code_editor',
518 'title' => esc_html__('Admin Dark Mode CSS', 'darkify'),
519 'title_help' =>
520 '<div class="darkify-info-label">' .
521 __('The CSS code will only be applied when admin dark mode is active.', 'darkify') .
522 '</div>',
523 'settings' => array(
524 'theme' => 'mbo',
525 'mode' => 'css',
526 ),
527 // Only relevant when admin dark mode is active — hide it while off.
528 'dependency' => array('enable_admin_panel_dark_mode', '==', 'true'),
529 ),
530 ),
531 ),
532 ),
533 ),
534 ),
535 ),
536 );
537 }
538 }
539