Plugin Directory

Changeset 3361418


Ignore:
Timestamp:
09/14/2025 11:06:46 PM (7 months ago)
Author:
mohsinwebs
Message:

update

Location:
speedox
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • speedox/tags/1.1.2/admin-dashboard-ui.php

    r3325637 r3361418  
    44
    55?>
    6 <div class="wrap">
     6<div class="wrap speedox-wrap">
    77  <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>">
    88    <input type="hidden" name="action" value="speedox_save_settings" />
    99    <?php wp_nonce_field('speedox_save_action', 'speedox_save_nonce'); ?>
     10   
     11    <?php
     12    // Include hidden fields for all settings to preserve them across tabs
     13    $all_options = [
     14        'speedox_page_caching', 'speedox_cache_preloading', 'speedox_scheduled_cache_clearing',
     15        'speedox_exclude_cache_urls', 'speedox_mobile_cache_splitting', 'speedox_woocommerce_cart_exclusion',
     16        'speedox_html_css_js_minify', 'speedox_combine_css_js', 'speedox_defer_js', 'speedox_remove_unused_css',
     17        'speedox_lazyload', 'speedox_image_optimization', 'speedox_database_optimization',
     18        'speedox_gzip_compression', 'speedox_brotli_compression', 'speedox_browser_cache',
     19        'speedox_basic_cdn_support', 'speedox_cloudflare_bunny', 'speedox_dns_prefetch',
     20        'speedox_disable_emojis_embeds_heartbeat', 'speedox_priority_support_panel'
     21    ];
     22   
     23    foreach ($all_options as $option) {
     24        $value = get_option($option, 0);
     25        echo '<input type="hidden" name="' . esc_attr($option) . '_preserve" value="' . esc_attr($value) . '" />';
     26    }
     27   
     28    // Preserve current tab
     29    echo '<input type="hidden" name="current_tab" value="' . esc_attr($active_tab) . '" />';
     30    ?>
    1031
    1132  <h1>⚡ SpeedOx Optimization Dashboard</h1>
     
    6182                <td>
    6283                  <?php if(!$pro): ?>
    63                     <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, get_option($opt)); ?>> Enable</label>
     84                    <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, intval(get_option($opt, 0))); ?>> Enable</label>
    6485                  <?php else: ?>
    6586                    <input type="checkbox" disabled /> <em style="color: gray;">Upgrade to Pro to enable this.</em>
     
    99120                <td>
    100121                  <?php if(!$pro): ?>
    101                     <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, get_option($opt)); ?>> Enable</label>
     122                    <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, intval(get_option($opt, 0))); ?>> Enable</label>
    102123                  <?php else: ?>
    103124                    <input type="checkbox" disabled /> <em style="color: gray;">Upgrade to Pro to enable this.</em>
     
    134155                <td>
    135156                  <?php if(!$pro): ?>
    136                     <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, get_option($opt)); ?>> Enable</label>
     157                    <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, intval(get_option($opt, 0))); ?>> Enable</label>
    137158                  <?php else: ?>
    138159                    <input type="checkbox" disabled /> <em style="color: gray;">Upgrade to Pro to enable this.</em>
     
    153174              <tr>
    154175                <th scope="row"><?php echo esc_html('Database Optimization'); ?></th>
    155                 <td><label><input type="checkbox" name="speedox_database_optimization" value="1" <?php checked(1, get_option('speedox_database_optimization')); ?>> Enable</label></td>
     176                <td><label><input type="checkbox" name="speedox_database_optimization" value="1" <?php checked(1, intval(get_option('speedox_database_optimization', 0))); ?>> Enable</label></td>
    156177              </tr>
    157178            </table>
     
    186207                <td>
    187208                  <?php if(!$pro): ?>
    188                     <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, get_option($opt)); ?>> Enable</label>
     209                    <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, intval(get_option($opt, 0))); ?>> Enable</label>
    189210                  <?php else: ?>
    190211                    <input type="checkbox" disabled /> <em style="color: gray;">Upgrade to Pro to enable this.</em>
     
    202223          <h2 class="hndle"><span>Activity Logs</span></h2>
    203224          <div class="inside">
    204             <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>">
    205                 <input type="hidden" name="action" value="speedox_clear_logs" />
    206                 <?php wp_nonce_field( 'speedox_clear_logs', 'speedox_clear_logs_nonce' ); ?>
    207                 <textarea readonly style="width:100%;height:300px;"><?php
    208                     $logs = SpeedOx_Logger::get_logs(200);
     225            <textarea readonly style="width:100%;height:300px;"><?php
     226                $logs = SpeedOx_Logger::get_logs(200);
     227                if (is_array($logs) && !empty($logs)) {
    209228                    echo esc_textarea(implode("\n", $logs));
    210                 ?></textarea>
    211                 <p><button type="submit" class="button">Clear Logs</button></p>
    212             </form>
     229                } else {
     230                    echo esc_textarea("No logs available yet. Plugin activity will be logged here.");
     231                }
     232            ?></textarea>
     233            <p>
     234              <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" style="display:inline;">
     235                  <input type="hidden" name="action" value="speedox_clear_logs" />
     236                  <?php wp_nonce_field( 'speedox_clear_logs', 'speedox_clear_logs_nonce' ); ?>
     237                  <button type="submit" class="button">Clear Logs</button>
     238              </form>
     239            </p>
    213240          </div>
    214241        </div>
  • speedox/tags/1.1.2/assets/css/admin-dashboard.css

    r3325637 r3361418  
    1 .speedox-dashboard {
    2   font-family: "Segoe UI", sans-serif;
    3   padding: 20px;
    4 }
    5 .speedox-header {
    6   background: linear-gradient(to right, #4f46e5, #6d28d9);
     1/* SpeedOx Dashboard - LiteSpeed Inspired but Better */
     2.speedox-wrap {
     3  background: #f8f9fa;
     4  border-radius: 0;
     5  padding: 0;
     6  box-shadow: none;
     7  margin-top: 0;
     8  min-height: 100vh;
     9  display: flex;
     10  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
     11}
     12
     13/* Sidebar Navigation */
     14.speedox-wrap::before {
     15  content: '';
     16  position: fixed;
     17  top: 0;
     18  left: 0;
     19  width: 250px;
     20  height: 100vh;
     21  background: linear-gradient(180deg, #2c3e50 0%, #34495e 100%);
     22  z-index: 1000;
     23  box-shadow: 2px 0 10px rgba(0,0,0,0.1);
     24}
     25
     26.speedox-wrap::after {
     27  content: '';
     28  position: fixed;
     29  top: 0;
     30  left: 0;
     31  width: 250px;
     32  height: 100vh;
     33  background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grain" width="100" height="100" patternUnits="userSpaceOnUse"><circle cx="25" cy="25" r="1" fill="rgba(255,255,255,0.05)"/><circle cx="75" cy="75" r="1" fill="rgba(255,255,255,0.03)"/><circle cx="50" cy="10" r="0.5" fill="rgba(255,255,255,0.04)"/></pattern></defs><rect width="100" height="100" fill="url(%23grain)"/></svg>');
     34  z-index: 1001;
     35  pointer-events: none;
     36}
     37
     38/* Main Content Area */
     39.speedox-wrap > * {
     40  margin-left: 250px;
     41  width: calc(100% - 250px);
     42  background: #ffffff;
     43  min-height: 100vh;
     44  padding: 30px;
     45}
     46
     47/* Header Section */
     48.speedox-wrap h1 {
     49  color: #2c3e50;
     50  font-size: 28px;
     51  margin-bottom: 30px;
     52  border-bottom: none;
     53  padding-bottom: 0;
     54  font-weight: 700;
     55  display: flex;
     56  align-items: center;
     57  gap: 15px;
     58}
     59
     60.speedox-wrap h1::before {
     61  content: '⚡';
     62  font-size: 32px;
     63  background: linear-gradient(135deg, #667eea, #764ba2);
     64  -webkit-background-clip: text;
     65  -webkit-text-fill-color: transparent;
     66  background-clip: text;
     67  animation: pulse 2s infinite;
     68}
     69
     70@keyframes pulse {
     71  0%, 100% { transform: scale(1); }
     72  50% { transform: scale(1.1); }
     73}
     74
     75/* Navigation Tabs - Sidebar Style */
     76.speedox-wrap .nav-tab-wrapper {
     77  position: fixed;
     78  top: 0;
     79  left: 0;
     80  width: 250px;
     81  height: 100vh;
     82  background: transparent;
     83  padding: 0;
     84  margin: 0;
     85  z-index: 1002;
     86  display: flex;
     87  flex-direction: column;
     88  padding-top: 80px;
     89}
     90
     91.speedox-wrap .nav-tab {
     92  background: transparent;
     93  color: #bdc3c7;
     94  border: none;
     95  padding: 15px 25px;
     96  text-decoration: none;
     97  border-radius: 0;
     98  margin: 0;
     99  transition: all 0.3s ease;
     100  font-weight: 500;
     101  font-size: 14px;
     102  display: flex;
     103  align-items: center;
     104  gap: 12px;
     105  position: relative;
     106  border-left: 3px solid transparent;
     107}
     108
     109.speedox-wrap .nav-tab::before {
     110  content: '';
     111  position: absolute;
     112  left: 0;
     113  top: 0;
     114  bottom: 0;
     115  width: 3px;
     116  background: #667eea;
     117  transform: scaleY(0);
     118  transition: transform 0.3s ease;
     119}
     120
     121.speedox-wrap .nav-tab:hover {
     122  background: rgba(255, 255, 255, 0.1);
    7123  color: white;
    8   padding: 20px;
     124  transform: translateX(5px);
     125}
     126
     127.speedox-wrap .nav-tab:hover::before {
     128  transform: scaleY(1);
     129}
     130
     131.speedox-wrap .nav-tab-active {
     132  background: rgba(255, 255, 255, 0.15);
     133  color: white;
     134  border-left-color: #667eea;
     135}
     136
     137.speedox-wrap .nav-tab-active::before {
     138  transform: scaleY(1);
     139}
     140
     141/* Add icons to nav tabs */
     142.speedox-wrap .nav-tab:nth-child(1)::after { content: '🚀'; }
     143.speedox-wrap .nav-tab:nth-child(2)::after { content: '⚡'; }
     144.speedox-wrap .nav-tab:nth-child(3)::after { content: '🖼️'; }
     145.speedox-wrap .nav-tab:nth-child(4)::after { content: '🗄️'; }
     146.speedox-wrap .nav-tab:nth-child(5)::after { content: '🔧'; }
     147.speedox-wrap .nav-tab:nth-child(6)::after { content: '📊'; }
     148
     149/* Content Cards */
     150.speedox-wrap .postbox {
     151  border: none;
    9152  border-radius: 12px;
    10   display: flex;
    11   align-items: center;
     153  margin-bottom: 25px;
     154  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
     155  background: white;
     156  overflow: hidden;
     157  position: relative;
     158}
     159
     160.speedox-wrap .postbox::before {
     161  content: '';
     162  position: absolute;
     163  top: 0;
     164  left: 0;
     165  right: 0;
     166  height: 4px;
     167  background: linear-gradient(135deg, #667eea, #764ba2);
     168}
     169
     170.speedox-wrap .postbox .hndle {
     171  background: linear-gradient(135deg, #f8fafc, #e2e8f0);
     172  border-bottom: 1px solid #e5e7eb;
     173  padding: 20px 25px;
     174  margin: 0;
     175  font-size: 18px;
     176  font-weight: 700;
     177  color: #1f2937;
     178  position: relative;
     179}
     180
     181.speedox-wrap .postbox .hndle::before {
     182  content: '';
     183  position: absolute;
     184  left: 0;
     185  top: 0;
     186  bottom: 0;
     187  width: 4px;
     188  background: linear-gradient(135deg, #667eea, #764ba2);
     189}
     190
     191.speedox-wrap .postbox .inside {
     192  padding: 25px;
     193  background: #fafbfc;
     194}
     195
     196/* Statistics Cards Grid */
     197.speedox-wrap .form-table {
     198  display: grid;
     199  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    12200  gap: 20px;
    13 }
    14 .speedox-header h1 {
    15   margin: 0;
    16   font-size: 26px;
    17 }
    18 .speedox-cards {
    19   display: grid;
    20   grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    21   gap: 20px;
    22   margin-top: 30px;
    23 }
    24 .speedox-card {
     201  background: transparent;
     202  border: none;
     203  box-shadow: none;
     204}
     205
     206.speedox-wrap .form-table tr {
    25207  background: white;
    26208  border-radius: 12px;
     209  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.08);
     210  display: flex;
     211  flex-direction: column;
    27212  padding: 20px;
    28   box-shadow: 0 4px 12px rgba(0,0,0,0.06);
    29   text-align: center;
    30 }
    31 .speedox-circle {
    32   width: 80px;
    33   height: 80px;
     213  transition: all 0.3s ease;
     214  border: 1px solid #e5e7eb;
     215}
     216
     217.speedox-wrap .form-table tr:hover {
     218  transform: translateY(-5px);
     219  box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
     220}
     221
     222.speedox-wrap .form-table th {
     223  width: auto;
     224  padding: 0 0 15px 0;
     225  font-weight: 700;
     226  color: #1f2937;
     227  background: transparent;
     228  border: none;
     229  font-size: 16px;
     230  text-align: left;
     231}
     232
     233.speedox-wrap .form-table td {
     234  padding: 0;
     235  background: transparent;
     236  border: none;
     237}
     238
     239/* Feature Cards with Statistics */
     240.speedox-wrap .form-table tr {
     241  position: relative;
     242  overflow: hidden;
     243}
     244
     245.speedox-wrap .form-table tr::before {
     246  content: '';
     247  position: absolute;
     248  top: 0;
     249  left: 0;
     250  right: 0;
     251  height: 4px;
     252  background: linear-gradient(135deg, #667eea, #764ba2);
     253}
     254
     255/* Enhanced Checkboxes */
     256.speedox-wrap input[type="checkbox"] {
     257  margin-right: 12px;
     258  transform: scale(1.4);
     259  accent-color: #667eea;
     260}
     261
     262.speedox-wrap label {
     263  font-weight: 600;
     264  color: #374151;
     265  cursor: pointer;
     266  font-size: 14px;
     267  transition: color 0.3s ease;
     268  display: flex;
     269  align-items: center;
     270}
     271
     272.speedox-wrap label:hover {
     273  color: #667eea;
     274}
     275
     276/* Status Indicators */
     277.speedox-wrap .form-table tr {
     278  position: relative;
     279}
     280
     281.speedox-wrap .form-table tr::after {
     282  content: '';
     283  position: absolute;
     284  top: 20px;
     285  right: 20px;
     286  width: 12px;
     287  height: 12px;
    34288  border-radius: 50%;
    35   background: #eef2ff;
    36   margin: 0 auto 10px;
    37   display: flex;
    38   align-items: center;
    39   justify-content: center;
    40   font-size: 20px;
    41 }
    42 .speedox-circle p {
    43   margin: 0;
    44   font-size: 18px;
    45   font-weight: bold;
    46 }
     289  background: #10b981;
     290  box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.2);
     291}
     292
     293/* Buttons */
     294.speedox-wrap .button-primary {
     295  background: linear-gradient(135deg, #10b981, #059669);
     296  border: none;
     297  color: white;
     298  padding: 12px 25px;
     299  font-size: 15px;
     300  font-weight: 700;
     301  border-radius: 8px;
     302  transition: all 0.3s ease;
     303  box-shadow: 0 4px 15px rgba(16, 185, 129, 0.3);
     304  text-transform: uppercase;
     305  letter-spacing: 0.5px;
     306  position: fixed;
     307  bottom: 30px;
     308  right: 30px;
     309  z-index: 1003;
     310}
     311
     312.speedox-wrap .button-primary:hover {
     313  background: linear-gradient(135deg, #059669, #047857);
     314  transform: translateY(-2px);
     315  box-shadow: 0 8px 25px rgba(16, 185, 129, 0.4);
     316}
     317
     318.speedox-wrap .button {
     319  background: linear-gradient(135deg, #6b7280, #4b5563);
     320  border: none;
     321  color: white;
     322  padding: 10px 20px;
     323  font-size: 13px;
     324  font-weight: 600;
     325  border-radius: 6px;
     326  transition: all 0.3s ease;
     327  box-shadow: 0 2px 8px rgba(107, 114, 128, 0.3);
     328}
     329
     330.speedox-wrap .button:hover {
     331  background: linear-gradient(135deg, #4b5563, #374151);
     332  transform: translateY(-1px);
     333  box-shadow: 0 4px 15px rgba(107, 114, 128, 0.4);
     334}
     335
     336/* Textarea */
     337.speedox-wrap textarea {
     338  border: 2px solid #e5e7eb;
     339  border-radius: 8px;
     340  padding: 15px;
     341  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
     342  font-size: 13px;
     343  background: #1f2937;
     344  color: #e5e7eb;
     345  box-shadow: inset 0 2px 4px rgba(0,0,0,0.1);
     346  transition: border-color 0.3s ease;
     347  width: 100%;
     348  height: 300px;
     349}
     350
     351.speedox-wrap textarea:focus {
     352  border-color: #667eea;
     353  outline: none;
     354  box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
     355}
     356
     357/* Footer */
     358.speedox-wrap .speedox-footer {
     359  margin-top: 30px;
     360  padding: 20px;
     361  background: linear-gradient(135deg, #f8fafc, #e2e8f0);
     362  border-radius: 12px;
     363  border-top: 3px solid #667eea;
     364  box-shadow: 0 4px 15px rgba(0,0,0,0.1);
     365}
     366
     367.speedox-wrap .speedox-footer a {
     368  color: #667eea;
     369  text-decoration: none;
     370  font-weight: 600;
     371  transition: color 0.3s ease;
     372}
     373
     374.speedox-wrap .speedox-footer a:hover {
     375  color: #764ba2;
     376  text-decoration: underline;
     377}
     378
     379/* Pro badge styling */
     380.speedox-wrap span[style*="background: #444"] {
     381  background: linear-gradient(135deg, #f59e0b, #d97706) !important;
     382  color: white !important;
     383  padding: 4px 10px !important;
     384  border-radius: 15px !important;
     385  font-size: 10px !important;
     386  font-weight: 800 !important;
     387  text-transform: uppercase !important;
     388  letter-spacing: 0.8px !important;
     389  box-shadow: 0 2px 8px rgba(245, 158, 11, 0.3) !important;
     390  animation: pulse 2s infinite !important;
     391}
     392
     393/* Responsive Design */
     394@media (max-width: 768px) {
     395  .speedox-wrap::before,
     396  .speedox-wrap::after {
     397    display: none;
     398  }
     399 
     400  .speedox-wrap > * {
     401    margin-left: 0;
     402    width: 100%;
     403    padding: 20px;
     404  }
     405 
     406  .speedox-wrap .nav-tab-wrapper {
     407    position: static;
     408    width: 100%;
     409    height: auto;
     410    flex-direction: row;
     411    padding-top: 0;
     412    margin-bottom: 20px;
     413    background: white;
     414    border-radius: 8px;
     415    box-shadow: 0 2px 10px rgba(0,0,0,0.1);
     416    overflow-x: auto;
     417  }
     418 
     419  .speedox-wrap .nav-tab {
     420    white-space: nowrap;
     421    border-left: none;
     422    border-bottom: 3px solid transparent;
     423    padding: 12px 20px;
     424    color: #6b7280;
     425  }
     426 
     427  .speedox-wrap .nav-tab::before {
     428    display: none;
     429  }
     430 
     431  .speedox-wrap .nav-tab-active {
     432    border-bottom-color: #667eea;
     433    background: transparent;
     434  }
     435 
     436  .speedox-wrap .form-table {
     437    grid-template-columns: 1fr;
     438  }
     439 
     440  .speedox-wrap .button-primary {
     441    position: static;
     442    margin-top: 20px;
     443  }
     444}
     445
     446@media (max-width: 480px) {
     447  .speedox-wrap > * {
     448    padding: 15px;
     449  }
     450 
     451  .speedox-wrap h1 {
     452    font-size: 24px;
     453  }
     454 
     455  .speedox-wrap .postbox .hndle {
     456    padding: 15px 20px;
     457    font-size: 16px;
     458  }
     459 
     460  .speedox-wrap .postbox .inside {
     461    padding: 20px;
     462  }
     463}
  • speedox/tags/1.1.2/includes/dashboard.php

    r3325637 r3361418  
    88        wp_enqueue_style(
    99            'speedox-dashboard-style',
    10             plugin_dir_url(__FILE__) . 'assets/css/admin-dashboard.css',
     10            plugin_dir_url(dirname(__FILE__)) . 'assets/css/admin-dashboard.css',
    1111            [],
    1212            '1.0.0'
  • speedox/tags/1.1.2/speedox.php

    r3325677 r3361418  
    200200
    201201    foreach ($options as $opt) {
    202         $value = isset($_POST[$opt]) ? 1 : 0;
     202        // Check if the option is explicitly set in the current tab
     203        if (isset($_POST[$opt]) && $_POST[$opt] == '1') {
     204            $value = 1;
     205        } else {
     206            // If not explicitly set, check if this option exists in the current tab
     207            // If it exists in current tab but not in POST, it means it was unchecked (set to 0)
     208            $current_tab_options = [];
     209            if (isset($_POST['current_tab'])) {
     210                $tab = $_POST['current_tab'];
     211                switch($tab) {
     212                    case 'cache':
     213                        $current_tab_options = ['speedox_page_caching', 'speedox_cache_preloading', 'speedox_scheduled_cache_clearing', 'speedox_exclude_cache_urls', 'speedox_mobile_cache_splitting', 'speedox_woocommerce_cart_exclusion', 'speedox_gzip_compression', 'speedox_brotli_compression', 'speedox_browser_cache'];
     214                        break;
     215                    case 'cssjs':
     216                        $current_tab_options = ['speedox_html_css_js_minify', 'speedox_combine_css_js', 'speedox_defer_js', 'speedox_remove_unused_css'];
     217                        break;
     218                    case 'media':
     219                        $current_tab_options = ['speedox_lazyload'];
     220                        break;
     221                    case 'database':
     222                        $current_tab_options = ['speedox_database_optimization'];
     223                        break;
     224                    case 'advanced':
     225                        $current_tab_options = ['speedox_disable_emojis_embeds_heartbeat', 'speedox_basic_cdn_support'];
     226                        break;
     227                }
     228            }
     229           
     230            if (in_array($opt, $current_tab_options)) {
     231                // This option is in current tab but not in POST, so it was unchecked
     232                $value = 0;
     233            } else {
     234                // This option is not in current tab, preserve its value
     235                $preserved_value = isset($_POST[$opt . '_preserve']) ? intval($_POST[$opt . '_preserve']) : 0;
     236                $value = $preserved_value;
     237            }
     238        }
    203239        update_option($opt, $value);
    204     }
    205 
    206     $tab = isset($_GET['tab']) ? sanitize_text_field(wp_unslash($_GET['tab'])) : 'cache';
     240       
     241        // Debug: Log what's being saved
     242        SpeedOx_Logger::log("Setting $opt = $value (POST: " . (isset($_POST[$opt]) ? $_POST[$opt] : 'not set') . ", Preserve: " . (isset($_POST[$opt . '_preserve']) ? $_POST[$opt . '_preserve'] : 'not set') . ")");
     243    }
     244
     245    // Get the current tab from POST data (preserved from the form)
     246    $tab = isset($_POST['current_tab']) ? sanitize_text_field(wp_unslash($_POST['current_tab'])) : 'cache';
     247   
    207248    wp_safe_redirect(admin_url('admin.php?page=speedox-dashboard&tab=' . $tab));
    208249    exit;
  • speedox/trunk/admin-dashboard-ui.php

    r3325213 r3361418  
    44
    55?>
    6 <div class="wrap">
     6<div class="wrap speedox-wrap">
    77  <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>">
    88    <input type="hidden" name="action" value="speedox_save_settings" />
    99    <?php wp_nonce_field('speedox_save_action', 'speedox_save_nonce'); ?>
     10   
     11    <?php
     12    // Include hidden fields for all settings to preserve them across tabs
     13    $all_options = [
     14        'speedox_page_caching', 'speedox_cache_preloading', 'speedox_scheduled_cache_clearing',
     15        'speedox_exclude_cache_urls', 'speedox_mobile_cache_splitting', 'speedox_woocommerce_cart_exclusion',
     16        'speedox_html_css_js_minify', 'speedox_combine_css_js', 'speedox_defer_js', 'speedox_remove_unused_css',
     17        'speedox_lazyload', 'speedox_image_optimization', 'speedox_database_optimization',
     18        'speedox_gzip_compression', 'speedox_brotli_compression', 'speedox_browser_cache',
     19        'speedox_basic_cdn_support', 'speedox_cloudflare_bunny', 'speedox_dns_prefetch',
     20        'speedox_disable_emojis_embeds_heartbeat', 'speedox_priority_support_panel'
     21    ];
     22   
     23    foreach ($all_options as $option) {
     24        $value = get_option($option, 0);
     25        echo '<input type="hidden" name="' . esc_attr($option) . '_preserve" value="' . esc_attr($value) . '" />';
     26    }
     27   
     28    // Preserve current tab
     29    echo '<input type="hidden" name="current_tab" value="' . esc_attr($active_tab) . '" />';
     30    ?>
    1031
    1132  <h1>⚡ SpeedOx Optimization Dashboard</h1>
     
    6182                <td>
    6283                  <?php if(!$pro): ?>
    63                     <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, get_option($opt)); ?>> Enable</label>
     84                    <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, intval(get_option($opt, 0))); ?>> Enable</label>
    6485                  <?php else: ?>
    6586                    <input type="checkbox" disabled /> <em style="color: gray;">Upgrade to Pro to enable this.</em>
     
    99120                <td>
    100121                  <?php if(!$pro): ?>
    101                     <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, get_option($opt)); ?>> Enable</label>
     122                    <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, intval(get_option($opt, 0))); ?>> Enable</label>
    102123                  <?php else: ?>
    103124                    <input type="checkbox" disabled /> <em style="color: gray;">Upgrade to Pro to enable this.</em>
     
    134155                <td>
    135156                  <?php if(!$pro): ?>
    136                     <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, get_option($opt)); ?>> Enable</label>
     157                    <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, intval(get_option($opt, 0))); ?>> Enable</label>
    137158                  <?php else: ?>
    138159                    <input type="checkbox" disabled /> <em style="color: gray;">Upgrade to Pro to enable this.</em>
     
    153174              <tr>
    154175                <th scope="row"><?php echo esc_html('Database Optimization'); ?></th>
    155                 <td><label><input type="checkbox" name="speedox_database_optimization" value="1" <?php checked(1, get_option('speedox_database_optimization')); ?>> Enable</label></td>
     176                <td><label><input type="checkbox" name="speedox_database_optimization" value="1" <?php checked(1, intval(get_option('speedox_database_optimization', 0))); ?>> Enable</label></td>
    156177              </tr>
    157178            </table>
     
    186207                <td>
    187208                  <?php if(!$pro): ?>
    188                     <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, get_option($opt)); ?>> Enable</label>
     209                    <label><input type="checkbox" name="<?php echo esc_attr($opt); ?>" value="1" <?php checked(1, intval(get_option($opt, 0))); ?>> Enable</label>
    189210                  <?php else: ?>
    190211                    <input type="checkbox" disabled /> <em style="color: gray;">Upgrade to Pro to enable this.</em>
     
    202223          <h2 class="hndle"><span>Activity Logs</span></h2>
    203224          <div class="inside">
    204             <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>">
    205                 <input type="hidden" name="action" value="speedox_clear_logs" />
    206                 <?php wp_nonce_field( 'speedox_clear_logs', 'speedox_clear_logs_nonce' ); ?>
    207                 <textarea readonly style="width:100%;height:300px;"><?php
    208                     $logs = SpeedOx_Logger::get_logs(200);
     225            <textarea readonly style="width:100%;height:300px;"><?php
     226                $logs = SpeedOx_Logger::get_logs(200);
     227                if (is_array($logs) && !empty($logs)) {
    209228                    echo esc_textarea(implode("\n", $logs));
    210                 ?></textarea>
    211                 <p><button type="submit" class="button">Clear Logs</button></p>
    212             </form>
     229                } else {
     230                    echo esc_textarea("No logs available yet. Plugin activity will be logged here.");
     231                }
     232            ?></textarea>
     233            <p>
     234              <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" style="display:inline;">
     235                  <input type="hidden" name="action" value="speedox_clear_logs" />
     236                  <?php wp_nonce_field( 'speedox_clear_logs', 'speedox_clear_logs_nonce' ); ?>
     237                  <button type="submit" class="button">Clear Logs</button>
     238              </form>
     239            </p>
    213240          </div>
    214241        </div>
  • speedox/trunk/assets/css/admin-dashboard.css

    r3325213 r3361418  
    1 .speedox-dashboard {
    2   font-family: "Segoe UI", sans-serif;
    3   padding: 20px;
    4 }
    5 .speedox-header {
    6   background: linear-gradient(to right, #4f46e5, #6d28d9);
     1/* SpeedOx Dashboard - LiteSpeed Inspired but Better */
     2.speedox-wrap {
     3  background: #f8f9fa;
     4  border-radius: 0;
     5  padding: 0;
     6  box-shadow: none;
     7  margin-top: 0;
     8  min-height: 100vh;
     9  display: flex;
     10  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
     11}
     12
     13/* Sidebar Navigation */
     14.speedox-wrap::before {
     15  content: '';
     16  position: fixed;
     17  top: 0;
     18  left: 0;
     19  width: 250px;
     20  height: 100vh;
     21  background: linear-gradient(180deg, #2c3e50 0%, #34495e 100%);
     22  z-index: 1000;
     23  box-shadow: 2px 0 10px rgba(0,0,0,0.1);
     24}
     25
     26.speedox-wrap::after {
     27  content: '';
     28  position: fixed;
     29  top: 0;
     30  left: 0;
     31  width: 250px;
     32  height: 100vh;
     33  background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grain" width="100" height="100" patternUnits="userSpaceOnUse"><circle cx="25" cy="25" r="1" fill="rgba(255,255,255,0.05)"/><circle cx="75" cy="75" r="1" fill="rgba(255,255,255,0.03)"/><circle cx="50" cy="10" r="0.5" fill="rgba(255,255,255,0.04)"/></pattern></defs><rect width="100" height="100" fill="url(%23grain)"/></svg>');
     34  z-index: 1001;
     35  pointer-events: none;
     36}
     37
     38/* Main Content Area */
     39.speedox-wrap > * {
     40  margin-left: 250px;
     41  width: calc(100% - 250px);
     42  background: #ffffff;
     43  min-height: 100vh;
     44  padding: 30px;
     45}
     46
     47/* Header Section */
     48.speedox-wrap h1 {
     49  color: #2c3e50;
     50  font-size: 28px;
     51  margin-bottom: 30px;
     52  border-bottom: none;
     53  padding-bottom: 0;
     54  font-weight: 700;
     55  display: flex;
     56  align-items: center;
     57  gap: 15px;
     58}
     59
     60.speedox-wrap h1::before {
     61  content: '⚡';
     62  font-size: 32px;
     63  background: linear-gradient(135deg, #667eea, #764ba2);
     64  -webkit-background-clip: text;
     65  -webkit-text-fill-color: transparent;
     66  background-clip: text;
     67  animation: pulse 2s infinite;
     68}
     69
     70@keyframes pulse {
     71  0%, 100% { transform: scale(1); }
     72  50% { transform: scale(1.1); }
     73}
     74
     75/* Navigation Tabs - Sidebar Style */
     76.speedox-wrap .nav-tab-wrapper {
     77  position: fixed;
     78  top: 0;
     79  left: 0;
     80  width: 250px;
     81  height: 100vh;
     82  background: transparent;
     83  padding: 0;
     84  margin: 0;
     85  z-index: 1002;
     86  display: flex;
     87  flex-direction: column;
     88  padding-top: 80px;
     89}
     90
     91.speedox-wrap .nav-tab {
     92  background: transparent;
     93  color: #bdc3c7;
     94  border: none;
     95  padding: 15px 25px;
     96  text-decoration: none;
     97  border-radius: 0;
     98  margin: 0;
     99  transition: all 0.3s ease;
     100  font-weight: 500;
     101  font-size: 14px;
     102  display: flex;
     103  align-items: center;
     104  gap: 12px;
     105  position: relative;
     106  border-left: 3px solid transparent;
     107}
     108
     109.speedox-wrap .nav-tab::before {
     110  content: '';
     111  position: absolute;
     112  left: 0;
     113  top: 0;
     114  bottom: 0;
     115  width: 3px;
     116  background: #667eea;
     117  transform: scaleY(0);
     118  transition: transform 0.3s ease;
     119}
     120
     121.speedox-wrap .nav-tab:hover {
     122  background: rgba(255, 255, 255, 0.1);
    7123  color: white;
    8   padding: 20px;
     124  transform: translateX(5px);
     125}
     126
     127.speedox-wrap .nav-tab:hover::before {
     128  transform: scaleY(1);
     129}
     130
     131.speedox-wrap .nav-tab-active {
     132  background: rgba(255, 255, 255, 0.15);
     133  color: white;
     134  border-left-color: #667eea;
     135}
     136
     137.speedox-wrap .nav-tab-active::before {
     138  transform: scaleY(1);
     139}
     140
     141/* Add icons to nav tabs */
     142.speedox-wrap .nav-tab:nth-child(1)::after { content: '🚀'; }
     143.speedox-wrap .nav-tab:nth-child(2)::after { content: '⚡'; }
     144.speedox-wrap .nav-tab:nth-child(3)::after { content: '🖼️'; }
     145.speedox-wrap .nav-tab:nth-child(4)::after { content: '🗄️'; }
     146.speedox-wrap .nav-tab:nth-child(5)::after { content: '🔧'; }
     147.speedox-wrap .nav-tab:nth-child(6)::after { content: '📊'; }
     148
     149/* Content Cards */
     150.speedox-wrap .postbox {
     151  border: none;
    9152  border-radius: 12px;
    10   display: flex;
    11   align-items: center;
     153  margin-bottom: 25px;
     154  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
     155  background: white;
     156  overflow: hidden;
     157  position: relative;
     158}
     159
     160.speedox-wrap .postbox::before {
     161  content: '';
     162  position: absolute;
     163  top: 0;
     164  left: 0;
     165  right: 0;
     166  height: 4px;
     167  background: linear-gradient(135deg, #667eea, #764ba2);
     168}
     169
     170.speedox-wrap .postbox .hndle {
     171  background: linear-gradient(135deg, #f8fafc, #e2e8f0);
     172  border-bottom: 1px solid #e5e7eb;
     173  padding: 20px 25px;
     174  margin: 0;
     175  font-size: 18px;
     176  font-weight: 700;
     177  color: #1f2937;
     178  position: relative;
     179}
     180
     181.speedox-wrap .postbox .hndle::before {
     182  content: '';
     183  position: absolute;
     184  left: 0;
     185  top: 0;
     186  bottom: 0;
     187  width: 4px;
     188  background: linear-gradient(135deg, #667eea, #764ba2);
     189}
     190
     191.speedox-wrap .postbox .inside {
     192  padding: 25px;
     193  background: #fafbfc;
     194}
     195
     196/* Statistics Cards Grid */
     197.speedox-wrap .form-table {
     198  display: grid;
     199  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    12200  gap: 20px;
    13 }
    14 .speedox-header h1 {
    15   margin: 0;
    16   font-size: 26px;
    17 }
    18 .speedox-cards {
    19   display: grid;
    20   grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    21   gap: 20px;
    22   margin-top: 30px;
    23 }
    24 .speedox-card {
     201  background: transparent;
     202  border: none;
     203  box-shadow: none;
     204}
     205
     206.speedox-wrap .form-table tr {
    25207  background: white;
    26208  border-radius: 12px;
     209  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.08);
     210  display: flex;
     211  flex-direction: column;
    27212  padding: 20px;
    28   box-shadow: 0 4px 12px rgba(0,0,0,0.06);
    29   text-align: center;
    30 }
    31 .speedox-circle {
    32   width: 80px;
    33   height: 80px;
     213  transition: all 0.3s ease;
     214  border: 1px solid #e5e7eb;
     215}
     216
     217.speedox-wrap .form-table tr:hover {
     218  transform: translateY(-5px);
     219  box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
     220}
     221
     222.speedox-wrap .form-table th {
     223  width: auto;
     224  padding: 0 0 15px 0;
     225  font-weight: 700;
     226  color: #1f2937;
     227  background: transparent;
     228  border: none;
     229  font-size: 16px;
     230  text-align: left;
     231}
     232
     233.speedox-wrap .form-table td {
     234  padding: 0;
     235  background: transparent;
     236  border: none;
     237}
     238
     239/* Feature Cards with Statistics */
     240.speedox-wrap .form-table tr {
     241  position: relative;
     242  overflow: hidden;
     243}
     244
     245.speedox-wrap .form-table tr::before {
     246  content: '';
     247  position: absolute;
     248  top: 0;
     249  left: 0;
     250  right: 0;
     251  height: 4px;
     252  background: linear-gradient(135deg, #667eea, #764ba2);
     253}
     254
     255/* Enhanced Checkboxes */
     256.speedox-wrap input[type="checkbox"] {
     257  margin-right: 12px;
     258  transform: scale(1.4);
     259  accent-color: #667eea;
     260}
     261
     262.speedox-wrap label {
     263  font-weight: 600;
     264  color: #374151;
     265  cursor: pointer;
     266  font-size: 14px;
     267  transition: color 0.3s ease;
     268  display: flex;
     269  align-items: center;
     270}
     271
     272.speedox-wrap label:hover {
     273  color: #667eea;
     274}
     275
     276/* Status Indicators */
     277.speedox-wrap .form-table tr {
     278  position: relative;
     279}
     280
     281.speedox-wrap .form-table tr::after {
     282  content: '';
     283  position: absolute;
     284  top: 20px;
     285  right: 20px;
     286  width: 12px;
     287  height: 12px;
    34288  border-radius: 50%;
    35   background: #eef2ff;
    36   margin: 0 auto 10px;
    37   display: flex;
    38   align-items: center;
    39   justify-content: center;
    40   font-size: 20px;
    41 }
    42 .speedox-circle p {
    43   margin: 0;
    44   font-size: 18px;
    45   font-weight: bold;
    46 }
     289  background: #10b981;
     290  box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.2);
     291}
     292
     293/* Buttons */
     294.speedox-wrap .button-primary {
     295  background: linear-gradient(135deg, #10b981, #059669);
     296  border: none;
     297  color: white;
     298  padding: 12px 25px;
     299  font-size: 15px;
     300  font-weight: 700;
     301  border-radius: 8px;
     302  transition: all 0.3s ease;
     303  box-shadow: 0 4px 15px rgba(16, 185, 129, 0.3);
     304  text-transform: uppercase;
     305  letter-spacing: 0.5px;
     306  position: fixed;
     307  bottom: 30px;
     308  right: 30px;
     309  z-index: 1003;
     310}
     311
     312.speedox-wrap .button-primary:hover {
     313  background: linear-gradient(135deg, #059669, #047857);
     314  transform: translateY(-2px);
     315  box-shadow: 0 8px 25px rgba(16, 185, 129, 0.4);
     316}
     317
     318.speedox-wrap .button {
     319  background: linear-gradient(135deg, #6b7280, #4b5563);
     320  border: none;
     321  color: white;
     322  padding: 10px 20px;
     323  font-size: 13px;
     324  font-weight: 600;
     325  border-radius: 6px;
     326  transition: all 0.3s ease;
     327  box-shadow: 0 2px 8px rgba(107, 114, 128, 0.3);
     328}
     329
     330.speedox-wrap .button:hover {
     331  background: linear-gradient(135deg, #4b5563, #374151);
     332  transform: translateY(-1px);
     333  box-shadow: 0 4px 15px rgba(107, 114, 128, 0.4);
     334}
     335
     336/* Textarea */
     337.speedox-wrap textarea {
     338  border: 2px solid #e5e7eb;
     339  border-radius: 8px;
     340  padding: 15px;
     341  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
     342  font-size: 13px;
     343  background: #1f2937;
     344  color: #e5e7eb;
     345  box-shadow: inset 0 2px 4px rgba(0,0,0,0.1);
     346  transition: border-color 0.3s ease;
     347  width: 100%;
     348  height: 300px;
     349}
     350
     351.speedox-wrap textarea:focus {
     352  border-color: #667eea;
     353  outline: none;
     354  box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
     355}
     356
     357/* Footer */
     358.speedox-wrap .speedox-footer {
     359  margin-top: 30px;
     360  padding: 20px;
     361  background: linear-gradient(135deg, #f8fafc, #e2e8f0);
     362  border-radius: 12px;
     363  border-top: 3px solid #667eea;
     364  box-shadow: 0 4px 15px rgba(0,0,0,0.1);
     365}
     366
     367.speedox-wrap .speedox-footer a {
     368  color: #667eea;
     369  text-decoration: none;
     370  font-weight: 600;
     371  transition: color 0.3s ease;
     372}
     373
     374.speedox-wrap .speedox-footer a:hover {
     375  color: #764ba2;
     376  text-decoration: underline;
     377}
     378
     379/* Pro badge styling */
     380.speedox-wrap span[style*="background: #444"] {
     381  background: linear-gradient(135deg, #f59e0b, #d97706) !important;
     382  color: white !important;
     383  padding: 4px 10px !important;
     384  border-radius: 15px !important;
     385  font-size: 10px !important;
     386  font-weight: 800 !important;
     387  text-transform: uppercase !important;
     388  letter-spacing: 0.8px !important;
     389  box-shadow: 0 2px 8px rgba(245, 158, 11, 0.3) !important;
     390  animation: pulse 2s infinite !important;
     391}
     392
     393/* Responsive Design */
     394@media (max-width: 768px) {
     395  .speedox-wrap::before,
     396  .speedox-wrap::after {
     397    display: none;
     398  }
     399 
     400  .speedox-wrap > * {
     401    margin-left: 0;
     402    width: 100%;
     403    padding: 20px;
     404  }
     405 
     406  .speedox-wrap .nav-tab-wrapper {
     407    position: static;
     408    width: 100%;
     409    height: auto;
     410    flex-direction: row;
     411    padding-top: 0;
     412    margin-bottom: 20px;
     413    background: white;
     414    border-radius: 8px;
     415    box-shadow: 0 2px 10px rgba(0,0,0,0.1);
     416    overflow-x: auto;
     417  }
     418 
     419  .speedox-wrap .nav-tab {
     420    white-space: nowrap;
     421    border-left: none;
     422    border-bottom: 3px solid transparent;
     423    padding: 12px 20px;
     424    color: #6b7280;
     425  }
     426 
     427  .speedox-wrap .nav-tab::before {
     428    display: none;
     429  }
     430 
     431  .speedox-wrap .nav-tab-active {
     432    border-bottom-color: #667eea;
     433    background: transparent;
     434  }
     435 
     436  .speedox-wrap .form-table {
     437    grid-template-columns: 1fr;
     438  }
     439 
     440  .speedox-wrap .button-primary {
     441    position: static;
     442    margin-top: 20px;
     443  }
     444}
     445
     446@media (max-width: 480px) {
     447  .speedox-wrap > * {
     448    padding: 15px;
     449  }
     450 
     451  .speedox-wrap h1 {
     452    font-size: 24px;
     453  }
     454 
     455  .speedox-wrap .postbox .hndle {
     456    padding: 15px 20px;
     457    font-size: 16px;
     458  }
     459 
     460  .speedox-wrap .postbox .inside {
     461    padding: 20px;
     462  }
     463}
  • speedox/trunk/includes/dashboard.php

    r3325213 r3361418  
    88        wp_enqueue_style(
    99            'speedox-dashboard-style',
    10             plugin_dir_url(__FILE__) . 'assets/css/admin-dashboard.css',
     10            plugin_dir_url(dirname(__FILE__)) . 'assets/css/admin-dashboard.css',
    1111            [],
    1212            '1.0.0'
  • speedox/trunk/speedox.php

    r3325677 r3361418  
    200200
    201201    foreach ($options as $opt) {
    202         $value = isset($_POST[$opt]) ? 1 : 0;
     202        // Check if the option is explicitly set in the current tab
     203        if (isset($_POST[$opt]) && $_POST[$opt] == '1') {
     204            $value = 1;
     205        } else {
     206            // If not explicitly set, check if this option exists in the current tab
     207            // If it exists in current tab but not in POST, it means it was unchecked (set to 0)
     208            $current_tab_options = [];
     209            if (isset($_POST['current_tab'])) {
     210                $tab = $_POST['current_tab'];
     211                switch($tab) {
     212                    case 'cache':
     213                        $current_tab_options = ['speedox_page_caching', 'speedox_cache_preloading', 'speedox_scheduled_cache_clearing', 'speedox_exclude_cache_urls', 'speedox_mobile_cache_splitting', 'speedox_woocommerce_cart_exclusion', 'speedox_gzip_compression', 'speedox_brotli_compression', 'speedox_browser_cache'];
     214                        break;
     215                    case 'cssjs':
     216                        $current_tab_options = ['speedox_html_css_js_minify', 'speedox_combine_css_js', 'speedox_defer_js', 'speedox_remove_unused_css'];
     217                        break;
     218                    case 'media':
     219                        $current_tab_options = ['speedox_lazyload'];
     220                        break;
     221                    case 'database':
     222                        $current_tab_options = ['speedox_database_optimization'];
     223                        break;
     224                    case 'advanced':
     225                        $current_tab_options = ['speedox_disable_emojis_embeds_heartbeat', 'speedox_basic_cdn_support'];
     226                        break;
     227                }
     228            }
     229           
     230            if (in_array($opt, $current_tab_options)) {
     231                // This option is in current tab but not in POST, so it was unchecked
     232                $value = 0;
     233            } else {
     234                // This option is not in current tab, preserve its value
     235                $preserved_value = isset($_POST[$opt . '_preserve']) ? intval($_POST[$opt . '_preserve']) : 0;
     236                $value = $preserved_value;
     237            }
     238        }
    203239        update_option($opt, $value);
    204     }
    205 
    206     $tab = isset($_GET['tab']) ? sanitize_text_field(wp_unslash($_GET['tab'])) : 'cache';
     240       
     241        // Debug: Log what's being saved
     242        SpeedOx_Logger::log("Setting $opt = $value (POST: " . (isset($_POST[$opt]) ? $_POST[$opt] : 'not set') . ", Preserve: " . (isset($_POST[$opt . '_preserve']) ? $_POST[$opt . '_preserve'] : 'not set') . ")");
     243    }
     244
     245    // Get the current tab from POST data (preserved from the form)
     246    $tab = isset($_POST['current_tab']) ? sanitize_text_field(wp_unslash($_POST['current_tab'])) : 'cache';
     247   
    207248    wp_safe_redirect(admin_url('admin.php?page=speedox-dashboard&tab=' . $tab));
    208249    exit;
Note: See TracChangeset for help on using the changeset viewer.