diff --git a/src/admin/class-admin.php b/src/admin/class-admin.php index eb584e0..6f9e418 100644 --- a/src/admin/class-admin.php +++ b/src/admin/class-admin.php @@ -123,6 +123,15 @@ public function register_settings() { 'optimize_all_media' => [ 'type' => 'integer', ], + 'show_optimization_toggle' => [ + 'type' => 'integer', + ], + 'show_optimization_toggle_frontend' => [ + 'type' => 'integer', + ], + 'persist_optimization_toggle' => [ + 'type' => 'integer', + ], 'disable_wp_scaling' => [ 'type' => 'integer', ], @@ -307,6 +316,21 @@ 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 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; + } + // 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 8b67131..56de75e 100644 --- a/src/admin/class-script-loader.php +++ b/src/admin/class-script-loader.php @@ -90,6 +90,10 @@ public static function enqueue_cimo_assets() { 'canManageOptions' => current_user_can( 'manage_options' ), '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, + '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, '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 85bfdf5..62da78f 100644 --- a/src/admin/css/admin-page.css +++ b/src/admin/css/admin-page.css @@ -926,3 +926,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 7066909..42e93d9 100644 --- a/src/admin/css/index.css +++ b/src/admin/css/index.css @@ -126,4 +126,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-container: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 57cee8b..5df51e8 100644 --- a/src/admin/js/media-manager/drop-zone.js +++ b/src/admin/js/media-manager/drop-zone.js @@ -39,6 +39,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 270f000..37d5157 100644 --- a/src/admin/js/page/admin-settings.js +++ b/src/admin/js/page/admin-settings.js @@ -19,6 +19,9 @@ const AdminSettings = () => { const [ settings, setSettings ] = useState( { // General settings optimizeAllMedia: 0, + showOptimizationToggle: 0, + showOptimizationToggleFrontend: 0, + persistOptimizationToggle: 0, disableWpScaling: 1, disableThumbnailGeneration: 0, thumbnailSizes: [], // Stores DISABLED thumbnail sizes @@ -85,6 +88,9 @@ 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, + 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, thumbnailSizes: cimoOptions.thumbnail_sizes || [], @@ -156,6 +162,9 @@ const AdminSettings = () => { return { ...settings, optimizeAllMedia: 0, + showOptimizationToggle: 0, + showOptimizationToggleFrontend: 0, + persistOptimizationToggle: 0, disableWpScaling: 1, disableThumbnailGeneration: 1, thumbnailSizes: [], @@ -168,6 +177,9 @@ const AdminSettings = () => { return { ...settings, optimizeAllMedia: 0, + showOptimizationToggle: 0, + showOptimizationToggleFrontend: 0, + persistOptimizationToggle: 0, disableWpScaling: 1, disableThumbnailGeneration: 0, thumbnailSizes: [], @@ -290,6 +302,9 @@ const AdminSettings = () => { cimo_options: { // 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, thumbnail_sizes: settings.thumbnailSizes, @@ -469,7 +484,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 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' ) } + /> +
+ + { /* 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 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' ) } + /> +
+ } + + { /* Persist Optimization Toggle */ } + { settings.showOptimizationToggle === 1 && buildType === 'premium' && +
+ + { __( 'Remember Toggle On/Off After Page Reload', '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={ __( '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' ) } + /> +
+ } + + { buildType === 'premium' &&
} + { /* WordPress Auto-Scaling */ }