PluginProbe
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder / 51.1.87
King Addons for Elementor – 100+ Elementor Widgets, 4 000+ Elementor Templates, WooCommerce Builder, Mega Menu, Popup Builder v51.1.87
51.1.87 51.1.86 51.1.84 51.1.85 51.1.83 51.1.82 51.1.81 51.1.79 51.1.78 51.1.77 51.1.76 51.1.74 51.1.75 51.1.65 51.1.64 51.1.63 trunk 51.1.14 51.1.2 51.1.35 51.1.36 51.1.37 51.1.38 51.1.39 51.1.44 All 41 releases
← All changes | includes/admin/layouts/ai-settings-page.php +387 -26 51.1.36 → 51.1.87 View file →
@@ -1,38 +1,399 @@
1 1 <?php
2 +/**
3 + * AI Settings page - V3 Premium style inspired Design.
4 + *
5 + * @package King_Addons
6 + */
7 +
2 8 if (!defined('ABSPATH')) {
3 9 exit;
4 10 }
11 +
12 +$ka_ai_provider = \King_Addons\AI_Provider::getProvider();
13 +$ka_ai_provider_label = \King_Addons\AI_Provider::getLabel($ka_ai_provider);
14 +
15 +// Theme mode is per-user
16 +$theme_mode = get_user_meta(get_current_user_id(), 'king_addons_theme_mode', true);
17 +$allowed_theme_modes = ['dark', 'light', 'auto'];
18 +if (!in_array($theme_mode, $allowed_theme_modes, true)) {
19 + $theme_mode = 'auto';
20 +}
21 +
22 +// Enqueue shared V3 styles
23 +wp_enqueue_style(
24 + 'king-addons-admin-v3',
25 + KING_ADDONS_URL . 'includes/admin/layouts/shared/admin-v3-styles.css',
26 + [],
27 + KING_ADDONS_VERSION
28 +);
5 29 ?>
6 -<div class="wrap king-addons-ai-settings king-addons-admin">
7 - <!-- Header Section -->
8 - <div class="king-addons-settings-header">
9 - <div class="king-addons-settings-header-content">
10 - <div class="king-addons-settings-header-icon">
11 - <img width="32px" height="32px" src="<?php echo esc_url(KING_ADDONS_URL . 'includes/admin/img/ai.svg'); ?>" alt="AI" />
30 +<script>
31 +(function() {
32 + document.body.classList.add('ka-admin-v3');
33 +
34 + const mode = '<?php echo esc_js($theme_mode); ?>';
35 + const mql = window.matchMedia ? window.matchMedia('(prefers-color-scheme: dark)') : null;
36 + const isDark = mode === 'auto' ? !!(mql && mql.matches) : mode === 'dark';
37 +
38 + document.documentElement.classList.toggle('ka-v3-dark', isDark);
39 + document.body.classList.toggle('ka-v3-dark', isDark);
40 +})();
41 +</script>
42 +
43 +<style>
44 +/*
45 + * Rows of the provider that is not selected. The class is applied server side so
46 + * there is no flash of both providers' fields, and the settings script toggles
47 + * the same class when the provider changes.
48 + */
49 +.ka-ai-settings .ka-ai-row-hidden {
50 + display: none;
51 +}
52 +
53 +/* AI Settings V3 */
54 +.ka-ai-settings .form-table {
55 + margin: 0;
56 + width: 100%;
57 +}
58 +
59 +.ka-ai-settings .form-table th,
60 +.ka-ai-settings .form-table td {
61 + padding: 18px 0;
62 + border-bottom: 1px solid rgba(0, 0, 0, 0.04);
63 + vertical-align: top;
64 +}
65 +
66 +body.ka-v3-dark .ka-ai-settings .form-table th,
67 +body.ka-v3-dark .ka-ai-settings .form-table td {
68 + border-bottom-color: rgba(255, 255, 255, 0.04);
69 +}
70 +
71 +.ka-ai-settings .form-table tr:last-child th,
72 +.ka-ai-settings .form-table tr:last-child td {
73 + border-bottom: none;
74 +}
75 +
76 +.ka-ai-settings .form-table th {
77 + width: 200px;
78 + font-size: 15px;
79 + font-weight: 500;
80 + color: #1d1d1f;
81 + padding-right: 20px;
82 +}
83 +
84 +body.ka-v3-dark .ka-ai-settings .form-table th {
85 + color: #f5f5f7;
86 +}
87 +
88 +.ka-ai-settings .form-table td {
89 + color: #1d1d1f;
90 +}
91 +
92 +body.ka-v3-dark .ka-ai-settings .form-table td {
93 + color: #f5f5f7;
94 +}
95 +
96 +.ka-ai-settings input[type="text"],
97 +.ka-ai-settings input[type="password"],
98 +.ka-ai-settings input[type="number"],
99 +.ka-ai-settings textarea,
100 +.ka-ai-settings select {
101 + width: 100%;
102 + max-width: 400px;
103 + padding: 12px 16px;
104 + border: 1px solid rgba(0, 0, 0, 0.1);
105 + border-radius: 12px;
106 + font-size: 15px;
107 + font-family: inherit;
108 + background-color: #fff;
109 + transition: border-color 0.2s, box-shadow 0.2s;
110 +}
111 +
112 +body.ka-v3-dark .ka-ai-settings input[type="text"],
113 +body.ka-v3-dark .ka-ai-settings input[type="password"],
114 +body.ka-v3-dark .ka-ai-settings input[type="number"],
115 +body.ka-v3-dark .ka-ai-settings textarea,
116 +body.ka-v3-dark .ka-ai-settings select {
117 + background-color: #2c2c2e;
118 + border-color: rgba(255, 255, 255, 0.1);
119 + color: #f5f5f7;
120 +}
121 +
122 +.ka-ai-settings input:focus,
123 +.ka-ai-settings textarea:focus,
124 +.ka-ai-settings select:focus {
125 + outline: none;
126 + border-color: #8b5cf6;
127 + box-shadow: 0 0 0 4px rgba(139, 92, 246, 0.1);
128 +}
129 +
130 +body.ka-v3-dark .ka-ai-settings input:focus,
131 +body.ka-v3-dark .ka-ai-settings textarea:focus,
132 +body.ka-v3-dark .ka-ai-settings select:focus {
133 + border-color: #a78bfa;
134 + box-shadow: 0 0 0 4px rgba(139, 92, 246, 0.2);
135 +}
136 +
137 +.ka-ai-settings .description {
138 + font-size: 13px;
139 + color: #86868b;
140 + margin-top: 8px;
141 + line-height: 1.5;
142 +}
143 +
144 +.ka-admin-wrap.ka-ai-settings select {
145 + -webkit-appearance: none;
146 + -moz-appearance: none;
147 + appearance: none;
148 + background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3e%3cpath fill='%2386868b' d='M6 8L0 0h12z'/%3e%3c/svg%3e");
149 + background-repeat: no-repeat;
150 + background-position: right 16px center;
151 + background-size: 10px 6px;
152 + padding-right: 44px;
153 +}
154 +
155 +body.ka-v3-dark .ka-admin-wrap.ka-ai-settings select {
156 + background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3e%3cpath fill='%23a1a1a6' d='M6 8L0 0h12z'/%3e%3c/svg%3e");
157 +}
158 +
159 +/* Section titles */
160 +.ka-ai-settings .ka-card-body h2 {
161 + font-size: 17px;
162 + font-weight: 600;
163 + color: #1d1d1f;
164 + margin: 24px 0 8px 0;
165 + padding: 24px 0 0 0;
166 + border-top: 1px solid rgba(0, 0, 0, 0.04);
167 +}
168 +
169 +body.ka-v3-dark .ka-ai-settings .ka-card-body h2 {
170 + color: #f5f5f7;
171 + border-top-color: rgba(255, 255, 255, 0.04);
172 +}
173 +
174 +.ka-ai-settings .ka-card-body h2:first-of-type {
175 + margin-top: 0;
176 + padding-top: 0;
177 + border-top: none;
178 +}
179 +
180 +.ka-ai-settings .ka-card-body h2 + p {
181 + color: #86868b;
182 + font-size: 14px;
183 + margin: 0 0 16px 0;
184 +}
185 +
186 +/* Button styles */
187 +.ka-ai-settings .button {
188 + padding: 10px 20px;
189 + border-radius: 980px;
190 + font-size: 14px;
191 + font-weight: 400;
192 + background: rgba(0, 0, 0, 0.06);
193 + border: none;
194 + color: #1d1d1f;
195 + cursor: pointer;
196 + transition: all 0.2s;
197 +}
198 +
199 +body.ka-v3-dark .ka-ai-settings .button {
200 + background: rgba(255, 255, 255, 0.1);
201 + color: #f5f5f7;
202 +}
203 +
204 +.ka-ai-settings .button:hover {
205 + background: rgba(0, 0, 0, 0.1);
206 +}
207 +
208 +body.ka-v3-dark .ka-ai-settings .button:hover {
209 + background: rgba(255, 255, 255, 0.15);
210 +}
211 +</style>
212 +
213 +<div class="ka-admin-wrap ka-ai-settings">
214 + <?php settings_errors('king_addons_ai'); ?>
215 + <!-- Header -->
216 + <div class="ka-admin-header">
217 + <div class="ka-admin-header-left">
218 + <div class="ka-admin-header-icon purple">
219 + <span class="dashicons dashicons-admin-generic"></span>
12 220 </div>
13 - <div class="king-addons-settings-header-text">
14 - <h1 class="king-addons-settings-title"><?php esc_html_e('AI Settings', 'king-addons'); ?></h1>
15 - <p class="king-addons-settings-subtitle"><?php esc_html_e('Configure OpenAI integration and AI features for Elementor editor', 'king-addons'); ?></p>
221 + <div>
222 + <h1 class="ka-admin-title"><?php esc_html_e('AI Settings', 'king-addons'); ?></h1>
223 + <p class="ka-admin-subtitle"><?php esc_html_e('Configure your AI provider and AI features for the Elementor editor', 'king-addons'); ?></p>
16 224 </div>
17 225 </div>
226 + <div class="ka-admin-header-actions">
227 + <div class="ka-v3-segmented" id="ka-v3-theme-segment" role="radiogroup" aria-label="<?php echo esc_attr(esc_html__('Theme', 'king-addons')); ?>" data-active="<?php echo esc_attr($theme_mode); ?>">
228 + <span class="ka-v3-segmented-indicator" aria-hidden="true"></span>
229 + <button type="button" class="ka-v3-segmented-btn" data-theme="light" aria-pressed="<?php echo $theme_mode === 'light' ? 'true' : 'false'; ?>">
230 + <span class="ka-v3-segmented-icon" aria-hidden="true">☀︎</span>
231 + <?php esc_html_e('Light', 'king-addons'); ?>
232 + </button>
233 + <button type="button" class="ka-v3-segmented-btn" data-theme="dark" aria-pressed="<?php echo $theme_mode === 'dark' ? 'true' : 'false'; ?>">
234 + <span class="ka-v3-segmented-icon" aria-hidden="true">☾</span>
235 + <?php esc_html_e('Dark', 'king-addons'); ?>
236 + </button>
237 + <button type="button" class="ka-v3-segmented-btn" data-theme="auto" aria-pressed="<?php echo $theme_mode === 'auto' ? 'true' : 'false'; ?>">
238 + <span class="ka-v3-segmented-icon" aria-hidden="true">◐</span>
239 + <?php esc_html_e('Auto', 'king-addons'); ?>
240 + </button>
241 + </div>
242 + <a href="<?php echo esc_url(\King_Addons\AI_Provider::getDashboardUrl($ka_ai_provider)); ?>" target="_blank" rel="noopener noreferrer" class="ka-btn ka-btn-secondary">
243 + <span class="dashicons dashicons-external"></span>
244 + <?php
245 + printf(
246 + /* translators: %s: provider name */
247 + esc_html__('%s Dashboard', 'king-addons'),
248 + esc_html($ka_ai_provider_label)
249 + );
250 + ?>
251 + </a>
252 + </div>
18 253 </div>
19 254
255 + <!-- Info Card -->
256 + <div class="ka-card">
257 + <div class="ka-card-header">
258 + <span class="dashicons dashicons-info" style="color: #0071e3;"></span>
259 + <h3><?php esc_html_e('How to use AI features', 'king-addons'); ?></h3>
260 + </div>
261 + <div class="ka-card-body">
262 + <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 24px;">
263 + <div>
264 + <h4 style="margin: 0 0 8px; font-size: 15px; font-weight: 600; color: inherit;">1. <?php esc_html_e('Pick a Provider', 'king-addons'); ?></h4>
265 + <p class="ka-row-desc" style="margin: 0;"><?php esc_html_e('Choose OpenAI to use the OpenAI API directly, or OpenRouter to reach models from many vendors — including free ones — with one key.', 'king-addons'); ?></p>
266 + </div>
267 + <div>
268 + <h4 style="margin: 0 0 8px; font-size: 15px; font-weight: 600; color: inherit;">2. <?php esc_html_e('Enter Key & Test', 'king-addons'); ?></h4>
269 + <p class="ka-row-desc" style="margin: 0;"><?php esc_html_e('Paste the API key in the field below, press Test Connection to verify it, then select your preferred models.', 'king-addons'); ?></p>
270 + </div>
271 + <div>
272 + <h4 style="margin: 0 0 8px; font-size: 15px; font-weight: 600; color: inherit;">3. <?php esc_html_e('Use', 'king-addons'); ?></h4>
273 + <p class="ka-row-desc" style="margin: 0;"><?php esc_html_e('AI features will be available in the Elementor editor, widgets, and other supported areas.', 'king-addons'); ?></p>
274 + </div>
275 + </div>
276 + </div>
277 + </div>
278 +
20 279 <!-- Settings Form -->
21 - <div class="king-addons-settings-container">
22 - <form method="post" action="options.php" class="king-addons-settings-form">
23 - <?php
24 - // Output settings fields for the registered option group
25 - settings_fields('king_addons_ai');
26 - // Output all sections and fields for this page
27 - do_settings_sections('king-addons-ai-settings');
28 - ?>
29 -
30 - <!-- Custom Save Button -->
31 - <div class="king-addons-settings-footer">
32 - <button type="submit" class="king-addons-save-button">
33 - <?php esc_html_e('Save Settings', 'king-addons'); ?>
34 - </button>
35 - </div>
36 - </form>
280 + <div class="ka-card">
281 + <div class="ka-card-header">
282 + <span class="dashicons dashicons-admin-settings" style="color: #8b5cf6;"></span>
283 + <h2><?php esc_html_e('AI Configuration', 'king-addons'); ?></h2>
284 + </div>
285 + <div class="ka-card-body">
286 + <form method="post" action="options.php">
287 + <?php
288 + settings_fields('king_addons_ai');
289 + do_settings_sections('king-addons-ai-settings');
290 + ?>
291 +
292 + <div style="margin-top: 24px; padding-top: 24px; border-top: 1px solid rgba(0,0,0,0.04);">
293 + <button type="submit" class="ka-btn ka-btn-primary">
294 + <?php esc_html_e('Save Settings', 'king-addons'); ?>
295 + </button>
296 + </div>
297 + </form>
298 + </div>
37 299 </div>
38 -</div>
300 +
301 +</div>
302 +
303 +<script>
304 +// Dashboard-style segmented theme control
305 +(function() {
306 + const segment = document.getElementById('ka-v3-theme-segment');
307 + if (!segment) {
308 + return;
309 + }
310 +
311 + const ajaxUrl = '<?php echo esc_url(admin_url('admin-ajax.php')); ?>';
312 + const nonce = '<?php echo esc_js(wp_create_nonce('king_addons_dashboard_ui')); ?>';
313 + const buttons = segment.querySelectorAll('.ka-v3-segmented-btn');
314 +
315 + const mql = window.matchMedia ? window.matchMedia('(prefers-color-scheme: dark)') : null;
316 + let mode = (segment.getAttribute('data-active') || 'dark').toString();
317 + let mqlHandler = null;
318 +
319 + function setPressedState(activeMode) {
320 + segment.setAttribute('data-active', activeMode);
321 + buttons.forEach((btn) => {
322 + const theme = btn.getAttribute('data-theme');
323 + btn.setAttribute('aria-pressed', theme === activeMode ? 'true' : 'false');
324 + });
325 + }
326 +
327 + function saveUISetting(key, value) {
328 + try {
329 + const body = new URLSearchParams();
330 + body.set('action', 'king_addons_save_dashboard_ui');
331 + body.set('nonce', nonce);
332 + body.set('key', key);
333 + body.set('value', value);
334 +
335 + fetch(ajaxUrl, {
336 + method: 'POST',
337 + headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
338 + body: body.toString(),
339 + credentials: 'same-origin'
340 + });
341 + } catch (e) {}
342 + }
343 +
344 + function applyTheme(isDark) {
345 + document.body.classList.toggle('ka-v3-dark', isDark);
346 + document.documentElement.classList.toggle('ka-v3-dark', isDark);
347 + }
348 +
349 + function setThemeMode(nextMode, save) {
350 + mode = nextMode;
351 + setPressedState(nextMode);
352 +
353 + if (mqlHandler && mql) {
354 + if (mql.removeEventListener) {
355 + mql.removeEventListener('change', mqlHandler);
356 + } else if (mql.removeListener) {
357 + mql.removeListener(mqlHandler);
358 + }
359 + mqlHandler = null;
360 + }
361 +
362 + if (nextMode === 'auto') {
363 + applyTheme(!!(mql && mql.matches));
364 + mqlHandler = (e) => {
365 + if (mode !== 'auto') {
366 + return;
367 + }
368 + applyTheme(!!e.matches);
369 + };
370 + if (mql) {
371 + if (mql.addEventListener) {
372 + mql.addEventListener('change', mqlHandler);
373 + } else if (mql.addListener) {
374 + mql.addListener(mqlHandler);
375 + }
376 + }
377 + } else {
378 + applyTheme(nextMode === 'dark');
379 + }
380 +
381 + if (save) {
382 + saveUISetting('theme_mode', nextMode);
383 + }
384 + }
385 +
386 + segment.addEventListener('click', (e) => {
387 + const btn = e.target && e.target.closest ? e.target.closest('.ka-v3-segmented-btn') : null;
388 + if (!btn) {
389 + return;
390 + }
391 + e.preventDefault();
392 + const theme = (btn.getAttribute('data-theme') || 'dark').toString();
393 + setThemeMode(theme, true);
394 + });
395 +
396 + // Ensure mode applies for Auto (listener + system state)
397 + setThemeMode(mode, false);
398 +})();
399 +</script>