From 19702f5ad83d53b6f4a7305a158b46938bc3db05 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 29 Aug 2025 01:09:20 +0000 Subject: [PATCH 1/2] Improve admin UI with separators, conversion info, and layout tweaks Co-authored-by: dingoes-51.slots --- assets/admin.css | 7 +++++++ includes/class-avif-suite.php | 12 +++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/assets/admin.css b/assets/admin.css index 1a1dfc8..32905b9 100644 --- a/assets/admin.css +++ b/assets/admin.css @@ -23,3 +23,10 @@ width: 0%; } +/* Simple separators between certain settings rows */ +.form-table tr.aviflosu-separator-top th, +.form-table tr.aviflosu-separator-top td { border-top: 1px solid #dcdcde; } + +/* hr separators inside settings fields */ +.aviflosu-sep { border: 0; border-top: 1px solid #dcdcde; margin: 12px 0; } + diff --git a/includes/class-avif-suite.php b/includes/class-avif-suite.php index 53d2702..ae9c5ff 100644 --- a/includes/class-avif-suite.php +++ b/includes/class-avif-suite.php @@ -148,6 +148,7 @@ function (): void { . ' ' . esc_html__('Add AVIF sources to JPEG images on the front end', 'avif-local-support') . ''; + echo '
'; }, 'avif-local-support', 'aviflosu_main', @@ -187,6 +188,9 @@ function (): void { . esc_html__('Scan daily and convert missing AVIFs', 'avif-local-support') . ' '; echo ''; + // Link to Tools tab for immediate conversion + echo ' ' . esc_html__('Convert missing AVIFs', 'avif-local-support') . ''; + echo '
'; }, 'avif-local-support', 'aviflosu_conversion', @@ -321,7 +325,6 @@ public function render_admin_page(): void echo '
'; echo '
'; echo '
'; - echo '

' . esc_html__('Settings', 'avif-local-support') . '

'; echo '
'; echo '
'; settings_fields('aviflosu_settings'); @@ -358,6 +361,13 @@ public function render_admin_page(): void echo '
'; echo '

' . esc_html__('Test conversion', 'avif-local-support') . '

'; echo '
'; + // Show conversion environment summary + $lib = extension_loaded('imagick') ? 'Imagick' : (function_exists('imageavif') ? 'GD' : 'None'); + $quality = (int) get_option('aviflosu_quality', 85); + $speed = (int) get_option('aviflosu_speed', 1); + $subsampling = (string) get_option('aviflosu_subsampling', '420'); + $bitDepth = (string) get_option('aviflosu_bit_depth', '8'); + echo '

' . esc_html__('Conversion environment', 'avif-local-support') . ': ' . esc_html($lib) . ' · ' . esc_html(sprintf(__('quality %d, speed %d, subsampling %s, %s‑bit', 'avif-local-support'), $quality, min(10, max(0, $speed)), $subsampling, $bitDepth)) . '

'; echo '

' . esc_html__('Upload a JPEG to preview resized images and the AVIFs generated by your current settings. The file is added to the Media Library.', 'avif-local-support') . '

'; echo ' '; echo ' '; From bc68493f22ff8135a37a0e25b3879e9cf56554e0 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 29 Aug 2025 01:28:12 +0000 Subject: [PATCH 2/2] Refactor settings UI, add defaults reset, improve conversion options Co-authored-by: dingoes-51.slots --- assets/admin.css | 3 +- assets/admin.js | 11 ++++ includes/class-avif-suite.php | 121 +++++++++++++++++++++------------- includes/class-converter.php | 2 +- 4 files changed, 89 insertions(+), 48 deletions(-) diff --git a/assets/admin.css b/assets/admin.css index 32905b9..9a16872 100644 --- a/assets/admin.css +++ b/assets/admin.css @@ -27,6 +27,5 @@ .form-table tr.aviflosu-separator-top th, .form-table tr.aviflosu-separator-top td { border-top: 1px solid #dcdcde; } -/* hr separators inside settings fields */ -.aviflosu-sep { border: 0; border-top: 1px solid #dcdcde; margin: 12px 0; } +/* removed hr-based separators; using row border class instead */ diff --git a/assets/admin.js b/assets/admin.js index 6c05d8a..25fd914 100644 --- a/assets/admin.js +++ b/assets/admin.js @@ -90,6 +90,17 @@ function initAll() { initTabs(); initStatus(); + // Disable/enable schedule time based on checkbox + var scheduleToggle = document.querySelector('#aviflosu_convert_via_schedule'); + var scheduleTime = document.querySelector('#aviflosu_schedule_time'); + function syncScheduleState() { + if (!scheduleToggle || !scheduleTime) return; + scheduleTime.disabled = !scheduleToggle.checked; + } + if (scheduleToggle && scheduleTime) { + scheduleToggle.addEventListener('change', syncScheduleState); + syncScheduleState(); + } // Convert-now button (AJAX queue + switch to Status with spinner + polling) var convertBtn = document.querySelector('#avif-local-support-convert-now'); diff --git a/includes/class-avif-suite.php b/includes/class-avif-suite.php index ae9c5ff..564571b 100644 --- a/includes/class-avif-suite.php +++ b/includes/class-avif-suite.php @@ -26,6 +26,7 @@ public function init(): void add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_assets']); add_filter('plugin_action_links_' . plugin_basename(\AVIFLOSU_PLUGIN_FILE), [$this, 'add_settings_link']); add_action('admin_post_aviflosu_upload_test', [$this, 'handle_upload_test']); + add_action('admin_post_aviflosu_reset_defaults', [$this, 'handle_reset_defaults']); add_action('wp_ajax_aviflosu_scan_missing', [$this, 'ajax_scan_missing']); add_action('wp_ajax_aviflosu_convert_now', [$this, 'ajax_convert_now']); add_action('wp_ajax_aviflosu_delete_all_avifs', [$this, 'ajax_delete_all_avifs']); @@ -148,7 +149,7 @@ function (): void { . ' ' . esc_html__('Add AVIF sources to JPEG images on the front end', 'avif-local-support') . ''; - echo '
'; + // spacing handled via CSS row borders }, 'avif-local-support', 'aviflosu_main', @@ -169,12 +170,13 @@ function (): void { $value = (bool) get_option('aviflosu_convert_on_upload', true); echo ''; + echo '

' . esc_html__('Recommended for completeness; can add a small delay to uploads on some servers.', 'avif-local-support') . '

'; }, 'avif-local-support', 'aviflosu_conversion', - [ 'label_for' => 'aviflosu_convert_on_upload' ] + [ 'label_for' => 'aviflosu_convert_on_upload', 'class' => 'aviflosu-separator-top' ] ); add_settings_field( @@ -185,12 +187,11 @@ function (): void { $time = (string) get_option('aviflosu_schedule_time', '01:00'); echo ' '; echo ''; - // Link to Tools tab for immediate conversion echo ' ' . esc_html__('Convert missing AVIFs', 'avif-local-support') . ''; - echo '
'; + echo '

' . esc_html__('Scan daily and convert JPEGs that are missing AVIFs.', 'avif-local-support') . '

'; }, 'avif-local-support', 'aviflosu_conversion', @@ -208,17 +209,17 @@ function (): void { }, 'avif-local-support', 'aviflosu_conversion', - [ 'label_for' => 'aviflosu_quality' ] + [ 'label_for' => 'aviflosu_quality', 'class' => 'aviflosu-separator-top' ] ); - // New: Speed slider (0-10) + // New: Speed slider (0-8) add_settings_field( 'avif_local_support_speed', - __('Speed (0–10)', 'avif-local-support'), + __('Speed (0–8)', 'avif-local-support'), function (): void { $value = (int) get_option('aviflosu_speed', 1); - $value = max(0, min(10, $value)); - echo ' '; + $value = max(0, min(8, $value)); + echo ' '; echo '' . \esc_html((string) $value) . ''; echo '

' . esc_html__('Lower = smaller files (slower). Higher = faster (larger files).', 'avif-local-support') . '

'; }, @@ -226,49 +227,47 @@ function (): void { 'aviflosu_conversion', [ 'label_for' => 'aviflosu_speed' ] ); - - // New: Chroma subsampling (radio) + // Advanced: Group subsampling and bit depth inside disclosure add_settings_field( - 'avif_local_support_subsampling', - __('Chroma subsampling', 'avif-local-support'), + 'avif_local_support_advanced', + __('Advanced', 'avif-local-support'), function (): void { - $value = (string) get_option('aviflosu_subsampling', '420'); - $allowed = ['420' => '4:2:0', '422' => '4:2:2', '444' => '4:4:4']; - echo '
'; - foreach ($allowed as $key => $label) { + $subsampling = (string) get_option('aviflosu_subsampling', '420'); + $bitDepth = (string) get_option('aviflosu_bit_depth', '8'); + $allowedSub = ['420' => '4:2:0', '422' => '4:2:2', '444' => '4:4:4']; + $allowedBits = ['8' => '8-bit', '10' => '10-bit', '12' => '12-bit']; + echo '
'; + echo '' . esc_html__('Chroma subsampling and bit depth', 'avif-local-support') . ''; + echo '
'; + echo '
'; + echo ' '; + echo '
'; + foreach ($allowedSub as $key => $label) { $id = 'aviflosu_subsampling_' . $key; echo ''; } - echo '
'; - echo '

' . esc_html__('4:2:0 is most compatible and smallest; 4:4:4 preserves more color detail.', 'avif-local-support') . '

'; - }, - 'avif-local-support', - 'aviflosu_conversion', - [ 'label_for' => 'aviflosu_subsampling' ] - ); - - // New: Bit depth (radio) - add_settings_field( - 'avif_local_support_bit_depth', - __('Bit depth', 'avif-local-support'), - function (): void { - $value = (string) get_option('aviflosu_bit_depth', '8'); - $allowed = ['8' => '8-bit', '10' => '10-bit', '12' => '12-bit']; - echo '
'; - foreach ($allowed as $key => $label) { + echo '
'; + echo '

' . esc_html__('4:2:0 is most compatible and smallest; 4:4:4 preserves more color detail.', 'avif-local-support') . '

'; + echo '
'; + echo '
'; + echo ' '; + echo '
'; + foreach ($allowedBits as $key => $label) { $id = 'aviflosu_bit_depth_' . $key; echo ''; } - echo '
'; - echo '

' . esc_html__('8-bit is standard; higher bit depths may increase file size and require broader support.', 'avif-local-support') . '

'; + echo '
'; + echo '

' . esc_html__('8-bit is standard; higher bit depths may increase file size and require broader support.', 'avif-local-support') . '

'; + echo '
'; + echo '
'; + echo ''; }, 'avif-local-support', - 'aviflosu_conversion', - [ 'label_for' => 'aviflosu_bit_depth' ] + 'aviflosu_conversion' ); } @@ -331,6 +330,12 @@ public function render_admin_page(): void do_settings_sections('avif-local-support'); submit_button(); echo '
'; + // Restore defaults button + echo '
'; + echo ' '; + wp_nonce_field('aviflosu_reset_defaults'); + echo ' '; + echo '
'; echo '
'; echo '
'; echo '
'; @@ -364,10 +369,11 @@ public function render_admin_page(): void // Show conversion environment summary $lib = extension_loaded('imagick') ? 'Imagick' : (function_exists('imageavif') ? 'GD' : 'None'); $quality = (int) get_option('aviflosu_quality', 85); - $speed = (int) get_option('aviflosu_speed', 1); + $speed = max(0, min(8, (int) get_option('aviflosu_speed', 1))); $subsampling = (string) get_option('aviflosu_subsampling', '420'); + $subLabel = ($subsampling === '444') ? '4:4:4' : (($subsampling === '422') ? '4:2:2' : '4:2:0'); $bitDepth = (string) get_option('aviflosu_bit_depth', '8'); - echo '

' . esc_html__('Conversion environment', 'avif-local-support') . ': ' . esc_html($lib) . ' · ' . esc_html(sprintf(__('quality %d, speed %d, subsampling %s, %s‑bit', 'avif-local-support'), $quality, min(10, max(0, $speed)), $subsampling, $bitDepth)) . '

'; + echo '

' . esc_html__('Conversion environment', 'avif-local-support') . ': ' . esc_html($lib) . ' · ' . esc_html(sprintf(__('quality %d, speed %d, subsampling %s, %s‑bit', 'avif-local-support'), $quality, $speed, $subLabel, $bitDepth)) . '

'; echo '

' . esc_html__('Upload a JPEG to preview resized images and the AVIFs generated by your current settings. The file is added to the Media Library.', 'avif-local-support') . '

'; echo '
'; echo ' '; @@ -387,7 +393,7 @@ public function render_admin_page(): void if ($attachment && $attachment->post_type === 'attachment') { $results = $this->converter->convertAttachmentNow($testId); $editLink = get_edit_post_link($testId); - echo '
'; + echo '
'; echo '

' . esc_html__('Test results for attachment:', 'avif-local-support') . ' ' . sprintf('%s', esc_url($editLink ?: '#'), esc_html(get_the_title($testId) ?: (string) $testId)) . '

'; echo ''; echo ' ' @@ -599,6 +605,31 @@ public function handle_upload_test(): void exit; } + public function handle_reset_defaults(): void + { + if (!current_user_can('manage_options')) { + wp_die(esc_html__('You do not have permission to do this.', 'avif-local-support')); + } + check_admin_referer('aviflosu_reset_defaults'); + + // Reset options to defaults + update_option('aviflosu_enable_support', true); + update_option('aviflosu_convert_on_upload', true); + update_option('aviflosu_convert_via_schedule', true); + update_option('aviflosu_schedule_time', '01:00'); + update_option('aviflosu_quality', 85); + update_option('aviflosu_speed', 1); + update_option('aviflosu_subsampling', '420'); + update_option('aviflosu_bit_depth', '8'); + update_option('aviflosu_cache_duration', 3600); + + // Ensure schedule matches defaults + $this->converter->maybe_schedule_daily(); + + \wp_safe_redirect(\add_query_arg('avif-local-support-reset', '1', \admin_url('options-general.php?page=avif-local-support#settings'))); + exit; + } + public function add_settings_link(array $links): array { $settings_link = sprintf('%s', esc_url(admin_url('options-general.php?page=avif-local-support')), __('Settings', 'avif-local-support')); diff --git a/includes/class-converter.php b/includes/class-converter.php index b933b62..9b5eddd 100644 --- a/includes/class-converter.php +++ b/includes/class-converter.php @@ -139,7 +139,7 @@ private function checkMissingAvif(string $path): void private function convertToAvif(string $sourcePath, string $avifPath, ?array $targetDimensions): void { $quality = max(0, min(100, (int) get_option('aviflosu_quality', 85))); - $speedSetting = max(0, min(10, (int) get_option('aviflosu_speed', 1))); + $speedSetting = max(0, min(8, (int) get_option('aviflosu_speed', 1))); // Always preserve metadata and ICC by default (options removed from UI) $preserveMeta = true; $preserveICC = true;