From 25a4e64bf284bea8ebacd7d6e8236cbcf74a98a8 Mon Sep 17 00:00:00 2001 From: Alquen Sarmiento Date: Thu, 26 Mar 2026 10:23:56 +0800 Subject: [PATCH 1/4] feat: add toggle optimization --- src/admin/class-admin.php | 16 +++++ src/admin/class-script-loader.php | 4 +- src/admin/css/admin-page.css | 5 ++ src/admin/css/index.css | 76 ++++++++++++++++++++++ src/admin/js/media-manager/drop-zone.js | 4 ++ src/admin/js/media-manager/select-files.js | 4 ++ src/admin/js/page/admin-settings.js | 62 +++++++++++++++++- 7 files changed, 168 insertions(+), 3 deletions(-) diff --git a/src/admin/class-admin.php b/src/admin/class-admin.php index 1ed71e3..06cc8f7 100644 --- a/src/admin/class-admin.php +++ b/src/admin/class-admin.php @@ -83,6 +83,12 @@ public function register_settings() { 'optimize_all_media' => [ 'type' => 'integer', ], + 'show_optimization_toggle' => [ + 'type' => 'integer', + ], + 'persist_optimization_toggle' => [ + 'type' => 'integer', + ], 'disable_wp_scaling' => [ 'type' => 'integer', ], @@ -267,6 +273,16 @@ public function sanitize_options( $options ) { $sanitized['optimize_all_media'] = $options['optimize_all_media'] ? 1 : 0; } + // Sanitize show_optimization_toggle + if ( isset( $options['show_optimization_toggle'] ) ) { + $sanitized['show_optimization_toggle'] = $options['show_optimization_toggle'] ? 1 : 0; + } + + // Sanitize persist_optimization_toggle + if ( isset( $options['persist_optimization_toggle'] ) ) { + $sanitized['persist_optimization_toggle'] = $options['persist_optimization_toggle'] ? 1 : 0; + } + // Sanitize disable_wp_scaling if ( isset( $options['disable_wp_scaling'] ) ) { $sanitized['disable_wp_scaling'] = $options['disable_wp_scaling'] ? 1 : 0; diff --git a/src/admin/class-script-loader.php b/src/admin/class-script-loader.php index f6724ff..e3c5859 100644 --- a/src/admin/class-script-loader.php +++ b/src/admin/class-script-loader.php @@ -86,8 +86,10 @@ public static function enqueue_cimo_assets() { 'nonce' => wp_create_nonce( 'wp_rest' ), 'isFrontend' => ! is_admin(), 'isLoggedIn' => is_user_logged_in(), - 'optimizeAllMedia' => isset( $settings['optimize_all_media'] ) ? (int) $settings['optimize_all_media'] : 0, 'isPremium' => CIMO_BUILD === 'premium', + 'optimizeAllMedia' => isset( $settings['optimize_all_media'] ) ? (int) $settings['optimize_all_media'] : 0, + 'showOptimizationToggle' => isset( $settings['show_optimization_toggle'] ) ? (int) $settings['show_optimization_toggle'] : 0, + 'persistOptimizationToggle' => isset( $settings['persist_optimization_toggle'] ) ? (int) $settings['persist_optimization_toggle'] : 0, 'webpQuality' => ! empty( $settings['webp_quality'] ) ? (int) $settings['webp_quality'] : 80, 'maxImageDimension' => ! empty( $settings['max_image_dimension'] ) ? (int) $settings['max_image_dimension'] : 0, 'videoOptimizationEnabled' => isset( $settings['video_optimization_enabled'] ) ? (int) $settings['video_optimization_enabled'] : 1, diff --git a/src/admin/css/admin-page.css b/src/admin/css/admin-page.css index 9e39448..cc3fdef 100644 --- a/src/admin/css/admin-page.css +++ b/src/admin/css/admin-page.css @@ -914,3 +914,8 @@ .cimo-bulk-optimize-button.is-optimizing { animation: cimo-strobe 1.5s linear infinite; } + +.cimo-divider { + border-top: 1px solid rgba(0, 0, 0, 0.1); + margin: 0 0 24px 0; +} \ No newline at end of file diff --git a/src/admin/css/index.css b/src/admin/css/index.css index 78a43cf..9236239 100644 --- a/src/admin/css/index.css +++ b/src/admin/css/index.css @@ -73,4 +73,80 @@ #cimo-data-meta-box.postbox .inside { padding-top: 12px; +} + +.cimo-optimization-toggle-container { + position: fixed; + bottom: 16px; + right: 16px; + z-index: 99999; + display: flex; + align-items: center; + gap: 8px; + padding: 8px 10px; + border-radius: 999px; + + background-color: rgba(0, 0, 0, 0.65); + backdrop-filter: blur(6px); + + color: #fff; + font-size: 12px; + font-family: system-ui, -apple-system, sans-serif; + + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); +} + +.cimo-optimization-toggle-label { + white-space: nowrap; + opacity: 0.9; +} + +.cimo-optimization-toggle-switch { + position: relative; + display: inline-block; + width: 34px; + height: 18px; +} + +/* Hide default checkbox */ +.cimo-optimization-toggle-switch input { + opacity: 0; + width: 0; + height: 0; +} + +/* Slider */ +.cimo-optimization-toggle-slider { + position: absolute; + inset: 0; + background-color: #888; + border-radius: 34px; + transition: background-color 0.2s ease; + cursor: pointer; +} + +.cimo-optimization-toggle-slider::before { + content: ""; + position: absolute; + height: 14px; + width: 14px; + left: 2px; + bottom: 2px; + + background-color: #fff; + border-radius: 50%; + + transition: transform 0.2s ease; +} + +.cimo-optimization-toggle-switch input:checked + .cimo-optimization-toggle-slider { + background-color: #0EBA35; +} + +.cimo-optimization-toggle-switch input:checked + .cimo-optimization-toggle-slider::before { + transform: translateX(16px); +} + +.cimo-optimization-toggle:hover { + background: rgba(0, 0, 0, 0.7); } \ No newline at end of file diff --git a/src/admin/js/media-manager/drop-zone.js b/src/admin/js/media-manager/drop-zone.js index 4d28f89..3653a69 100644 --- a/src/admin/js/media-manager/drop-zone.js +++ b/src/admin/js/media-manager/drop-zone.js @@ -38,6 +38,10 @@ function addDropZoneListenerToMediaManager( targetDocument ) { } const customDropHandler = async event => { + if ( window.cimoSettings?.disableOptimization ) { + return + } + // If this is a synthetic change event dispatched by us after conversion, skip conversion. if ( event.__cimo_converted ) { return diff --git a/src/admin/js/media-manager/select-files.js b/src/admin/js/media-manager/select-files.js index e941600..e684b5a 100644 --- a/src/admin/js/media-manager/select-files.js +++ b/src/admin/js/media-manager/select-files.js @@ -32,6 +32,10 @@ function addSelectFilesListenerToFileUploads( targetDocument ) { } const selectFilesListener = async event => { + if ( window.cimoSettings?.disableOptimization ) { + return + } + // Check if it's a file select. if ( event.target.type !== 'file' ) { return diff --git a/src/admin/js/page/admin-settings.js b/src/admin/js/page/admin-settings.js index 8b1d506..e81fd06 100644 --- a/src/admin/js/page/admin-settings.js +++ b/src/admin/js/page/admin-settings.js @@ -18,6 +18,8 @@ const AdminSettings = () => { const [ settings, setSettings ] = useState( { // General settings optimizeAllMedia: 0, + showOptimizationToggle: 0, + persistOptimizationToggle: 0, disableWpScaling: 1, disableThumbnailGeneration: 0, thumbnailSizes: [], // Stores DISABLED thumbnail sizes @@ -84,6 +86,8 @@ const AdminSettings = () => { const fetchedSettings = { // General Settings optimizeAllMedia: cimoOptions.optimize_all_media !== undefined ? cimoOptions.optimize_all_media : 0, + showOptimizationToggle: cimoOptions.show_optimization_toggle !== undefined ? cimoOptions.show_optimization_toggle : 0, + persistOptimizationToggle: cimoOptions.persist_optimization_toggle !== undefined ? cimoOptions.persist_optimization_toggle : 0, disableWpScaling: cimoOptions.disable_wp_scaling !== undefined ? cimoOptions.disable_wp_scaling : 1, disableThumbnailGeneration: cimoOptions.disable_thumbnail_generation !== undefined ? cimoOptions.disable_thumbnail_generation : 0, thumbnailSizes: cimoOptions.thumbnail_sizes || [], @@ -155,6 +159,8 @@ const AdminSettings = () => { return { ...settings, optimizeAllMedia: 0, + showOptimizationToggle: 0, + persistOptimizationToggle: 0, disableWpScaling: 1, disableThumbnailGeneration: 1, thumbnailSizes: [], @@ -167,6 +173,8 @@ const AdminSettings = () => { return { ...settings, optimizeAllMedia: 0, + showOptimizationToggle: 0, + persistOptimizationToggle: 0, disableWpScaling: 1, disableThumbnailGeneration: 0, thumbnailSizes: [], @@ -289,6 +297,8 @@ const AdminSettings = () => { cimo_options: { // General settings optimize_all_media: settings.optimizeAllMedia, + show_optimization_toggle: settings.showOptimizationToggle, + persist_optimization_toggle: settings.persistOptimizationToggle, disable_wp_scaling: settings.disableWpScaling, disable_thumbnail_generation: settings.disableThumbnailGeneration, thumbnail_sizes: settings.thumbnailSizes, @@ -468,7 +478,7 @@ const AdminSettings = () => { - { /* Optimize All Media Uploads*/ } + { /* Optimize All Media Uploads */ }
{ ) } } - checked={ settings.optimizeAllMedia === 1 } + checked={ buildType === 'premium' ? settings.optimizeAllMedia === 1 : 0 } disabled={ buildType === 'free' } onChange={ checked => handleInputChange( 'optimizeAllMedia', checked ? 1 : 0 ) } help={ __( 'Enable to optimize all files uploaded via any input type="file" on your website, including those in the admin pages, plugin forms and custom HTML upload forms in the frontend of your stie. When disabled, only uploads handled by Cimo\'s official integrations will be optimized.', 'cimo-image-optimizer' ) } />
+ { buildType === 'premium' &&
} + + { /* Show Optimization Toggle */ } +
+ + { __( 'Show Optimization Toggle', 'cimo-image-optimizer' ) } + { buildType === 'free' && ( + + { __( 'Premium', 'cimo-image-optimizer' ) } + + ) } + + } + checked={ buildType === 'premium' ? settings.showOptimizationToggle === 1 : 0 } + disabled={ buildType === 'free' } + onChange={ checked => handleInputChange( 'showOptimizationToggle', checked ? 1 : 0 ) } + help={ __( 'Enable to show a small floating toggle near the corner of the screen that you can untick to disable media optimization for the current window.', 'cimo-image-optimizer' ) } + /> +
+ + { /* Persist Optimization Toggle */ } + { settings.showOptimizationToggle === 1 && buildType === 'premium' && +
+ + { __( 'Persist Optimization Toggle State Across Pages', 'cimo-image-optimizer' ) } + { buildType === 'free' && ( + + { __( 'Premium', 'cimo-image-optimizer' ) } + + ) } + + } + checked={ buildType === 'premium' ? settings.persistOptimizationToggle === 1 : 0 } + disabled={ buildType === 'free' } + onChange={ checked => handleInputChange( 'persistOptimizationToggle', checked ? 1 : 0 ) } + help={ __( 'Enable to persist the current state of the Optimization Toggle across different pages and window.', 'cimo-image-optimizer' ) } + /> +
+ } + + { buildType === 'premium' &&
} + { /* WordPress Auto-Scaling */ }
Date: Thu, 26 Mar 2026 10:47:55 +0800 Subject: [PATCH 2/4] fix: typo in css --- src/admin/css/index.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/admin/css/index.css b/src/admin/css/index.css index 9236239..23f762d 100644 --- a/src/admin/css/index.css +++ b/src/admin/css/index.css @@ -147,6 +147,6 @@ transform: translateX(16px); } -.cimo-optimization-toggle:hover { +.cimo-optimization-toggle-container:hover { background: rgba(0, 0, 0, 0.7); } \ No newline at end of file From c3a17391e1428d566ce8fa4b4e1a55e0544e8f63 Mon Sep 17 00:00:00 2001 From: Alquen Sarmiento Date: Tue, 31 Mar 2026 11:10:26 +0800 Subject: [PATCH 3/4] fix: add show in frontend --- src/admin/class-admin.php | 8 ++++++++ src/admin/class-script-loader.php | 1 + src/admin/js/page/admin-settings.js | 28 ++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/src/admin/class-admin.php b/src/admin/class-admin.php index 06cc8f7..761cba2 100644 --- a/src/admin/class-admin.php +++ b/src/admin/class-admin.php @@ -86,6 +86,9 @@ public function register_settings() { 'show_optimization_toggle' => [ 'type' => 'integer', ], + 'show_optimization_toggle_frontend' => [ + 'type' => 'integer', + ], 'persist_optimization_toggle' => [ 'type' => 'integer', ], @@ -278,6 +281,11 @@ public function sanitize_options( $options ) { $sanitized['show_optimization_toggle'] = $options['show_optimization_toggle'] ? 1 : 0; } + // Sanitize show_optimization_toggle_frontend + if ( isset( $options['show_optimization_toggle_frontend'] ) ) { + $sanitized['show_optimization_toggle_frontend'] = $options['show_optimization_toggle_frontend'] ? 1 : 0; + } + // Sanitize persist_optimization_toggle if ( isset( $options['persist_optimization_toggle'] ) ) { $sanitized['persist_optimization_toggle'] = $options['persist_optimization_toggle'] ? 1 : 0; diff --git a/src/admin/class-script-loader.php b/src/admin/class-script-loader.php index 94c970d..2fe5d17 100644 --- a/src/admin/class-script-loader.php +++ b/src/admin/class-script-loader.php @@ -89,6 +89,7 @@ public static function enqueue_cimo_assets() { 'isPremium' => CIMO_BUILD === 'premium', 'optimizeAllMedia' => isset( $settings['optimize_all_media'] ) ? (int) $settings['optimize_all_media'] : 0, 'showOptimizationToggle' => isset( $settings['show_optimization_toggle'] ) ? (int) $settings['show_optimization_toggle'] : 0, + 'showOptimizationToggleFrontend' => isset( $settings['show_optimization_toggle_frontend'] ) ? (int) $settings['show_optimization_toggle_frontend'] : 0, 'persistOptimizationToggle' => isset( $settings['persist_optimization_toggle'] ) ? (int) $settings['persist_optimization_toggle'] : 0, 'webpQuality' => ! empty( $settings['webp_quality'] ) ? (int) $settings['webp_quality'] : 80, 'maxImageDimension' => ! empty( $settings['max_image_dimension'] ) ? (int) $settings['max_image_dimension'] : 0, diff --git a/src/admin/js/page/admin-settings.js b/src/admin/js/page/admin-settings.js index e81fd06..1b1489a 100644 --- a/src/admin/js/page/admin-settings.js +++ b/src/admin/js/page/admin-settings.js @@ -19,6 +19,7 @@ const AdminSettings = () => { // General settings optimizeAllMedia: 0, showOptimizationToggle: 0, + showOptimizationToggleFrontend: 0, persistOptimizationToggle: 0, disableWpScaling: 1, disableThumbnailGeneration: 0, @@ -87,6 +88,7 @@ const AdminSettings = () => { // General Settings optimizeAllMedia: cimoOptions.optimize_all_media !== undefined ? cimoOptions.optimize_all_media : 0, showOptimizationToggle: cimoOptions.show_optimization_toggle !== undefined ? cimoOptions.show_optimization_toggle : 0, + showOptimizationToggleFrontend: cimoOptions.show_optimization_toggle_frontend !== undefined ? cimoOptions.show_optimization_toggle_frontend : 0, persistOptimizationToggle: cimoOptions.persist_optimization_toggle !== undefined ? cimoOptions.persist_optimization_toggle : 0, disableWpScaling: cimoOptions.disable_wp_scaling !== undefined ? cimoOptions.disable_wp_scaling : 1, disableThumbnailGeneration: cimoOptions.disable_thumbnail_generation !== undefined ? cimoOptions.disable_thumbnail_generation : 0, @@ -160,6 +162,7 @@ const AdminSettings = () => { ...settings, optimizeAllMedia: 0, showOptimizationToggle: 0, + showOptimizationToggleFrontend: 0, persistOptimizationToggle: 0, disableWpScaling: 1, disableThumbnailGeneration: 1, @@ -174,6 +177,7 @@ const AdminSettings = () => { ...settings, optimizeAllMedia: 0, showOptimizationToggle: 0, + showOptimizationToggleFrontend: 0, persistOptimizationToggle: 0, disableWpScaling: 1, disableThumbnailGeneration: 0, @@ -298,6 +302,7 @@ const AdminSettings = () => { // General settings optimize_all_media: settings.optimizeAllMedia, show_optimization_toggle: settings.showOptimizationToggle, + show_optimization_toggle_frontend: settings.showOptimizationToggleFrontend, persist_optimization_toggle: settings.persistOptimizationToggle, disable_wp_scaling: settings.disableWpScaling, disable_thumbnail_generation: settings.disableThumbnailGeneration, @@ -522,6 +527,29 @@ const AdminSettings = () => { />
+ { /* Show in Frontend */ } + { settings.showOptimizationToggle === 1 && buildType === 'premium' && +
+ + { __( 'Show in Frontend', 'cimo-image-optimizer' ) } + { buildType === 'free' && ( + + { __( 'Premium', 'cimo-image-optimizer' ) } + + ) } + + } + checked={ buildType === 'premium' ? settings.showOptimizationToggleFrontend === 1 : 0 } + disabled={ buildType === 'free' } + onChange={ checked => handleInputChange( 'showOptimizationToggleFrontend', checked ? 1 : 0 ) } + help={ __( 'Enable to show the optimization toggle in frontend If enabled, the floating toggle will also be shown in the frontend. Website visitors will also be able to see the floating toggle for user-facing forms.', 'cimo-image-optimizer' ) } + /> +
+ } + { /* Persist Optimization Toggle */ } { settings.showOptimizationToggle === 1 && buildType === 'premium' &&
From 4252f9ed04e8d0d7da809b30be7b63b8b25e869b Mon Sep 17 00:00:00 2001 From: bfintal Date: Thu, 2 Apr 2026 02:37:06 +0800 Subject: [PATCH 4/4] fix: tweaked wordings --- src/admin/js/page/admin-settings.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/admin/js/page/admin-settings.js b/src/admin/js/page/admin-settings.js index 1b1489a..d07c1a2 100644 --- a/src/admin/js/page/admin-settings.js +++ b/src/admin/js/page/admin-settings.js @@ -523,7 +523,7 @@ const AdminSettings = () => { checked={ buildType === 'premium' ? settings.showOptimizationToggle === 1 : 0 } disabled={ buildType === 'free' } onChange={ checked => handleInputChange( 'showOptimizationToggle', checked ? 1 : 0 ) } - help={ __( 'Enable to show a small floating toggle near the corner of the screen that you can untick to disable media optimization for the current window.', 'cimo-image-optimizer' ) } + help={ __( 'Enable to show a small floating toggle near the lower right-hand corner of your screen in the WordPress backend. This can be used to temporarily disable media optimization for the current tab.', 'cimo-image-optimizer' ) } />
@@ -545,7 +545,7 @@ const AdminSettings = () => { checked={ buildType === 'premium' ? settings.showOptimizationToggleFrontend === 1 : 0 } disabled={ buildType === 'free' } onChange={ checked => handleInputChange( 'showOptimizationToggleFrontend', checked ? 1 : 0 ) } - help={ __( 'Enable to show the optimization toggle in frontend If enabled, the floating toggle will also be shown in the frontend. Website visitors will also be able to see the floating toggle for user-facing forms.', 'cimo-image-optimizer' ) } + help={ __( 'Enable to show the optimization toggle also in frontend. Website visitors will also be able to see the floating toggle for visitor-facing forms and whenever there is a file upload input.', 'cimo-image-optimizer' ) } /> } @@ -557,7 +557,7 @@ const AdminSettings = () => { __nextHasNoMarginBottom label={ - { __( 'Persist Optimization Toggle State Across Pages', 'cimo-image-optimizer' ) } + { __( 'Remember Toggle On/Off After Page Reload', 'cimo-image-optimizer' ) } { buildType === 'free' && ( { __( 'Premium', 'cimo-image-optimizer' ) } @@ -568,7 +568,7 @@ const AdminSettings = () => { checked={ buildType === 'premium' ? settings.persistOptimizationToggle === 1 : 0 } disabled={ buildType === 'free' } onChange={ checked => handleInputChange( 'persistOptimizationToggle', checked ? 1 : 0 ) } - help={ __( 'Enable to persist the current state of the Optimization Toggle across different pages and window.', 'cimo-image-optimizer' ) } + help={ __( 'If enabled, your optimization toggle will remain the same even after you refresh the page or visit other pages. If disabled, the toggle will always reset to ON after reloading the page.', 'cimo-image-optimizer' ) } /> }