diff --git a/src/admin/class-admin.php b/src/admin/class-admin.php index 8eb6125..063865e 100644 --- a/src/admin/class-admin.php +++ b/src/admin/class-admin.php @@ -37,10 +37,16 @@ public function __construct() { */ public function add_admin_menu() { $settings = get_option( 'cimo_options', [] ); + $menu_title = __( 'Cimo', 'cimo-image-optimizer' ); + + // Use cached stats here so every admin page load does not scan attachment metadata. + if ( class_exists( 'Cimo_Stats' ) && Cimo_Stats::should_show_rating_notice() ) { + $menu_title .= ' ' . number_format_i18n( 1 ) . ''; + } add_options_page( __( 'Cimo Settings', 'cimo-image-optimizer' ), - __( 'Cimo', 'cimo-image-optimizer' ), + $menu_title, 'manage_options', CIMO_SETTINGS_SLUG, [ $this, 'admin_page_callback' ] @@ -269,6 +275,7 @@ public function enqueue_admin_scripts( $hook ) { // Get statistics data $stats = Cimo_Stats::get_formatted_stats(); + $show_rating_notice = Cimo_Stats::should_show_rating_notice(); // Get image sizes $image_sizes = $this->get_all_image_sizes(); @@ -286,6 +293,7 @@ public function enqueue_admin_scripts( $hook ) { 'stats' => $stats, 'imageSizes' => $formatted_sizes, 'ratingDismissed' => '1' === get_option( 'cimo_rating_dismissed', '0' ) ? '1' : '0', + 'showRatingNotice' => $show_rating_notice ? '1' : '0', 'isPremium' => CIMO_BUILD === 'premium', 'uploadsUrl' => wp_upload_dir()['baseurl'], ] ); diff --git a/src/admin/class-metadata.php b/src/admin/class-metadata.php index bb96be0..1c4a1bd 100644 --- a/src/admin/class-metadata.php +++ b/src/admin/class-metadata.php @@ -266,6 +266,11 @@ public function add_attachment_metadata( $attachment_id ) { // Update the attachment metadata. update_post_meta( $attachment_id, '_wp_attachment_metadata', $metadata ); + + // Trigger a stats update after adding a new metadata. + if ( class_exists( 'Cimo_Stats' ) ) { + Cimo_Stats::get_stats(); + } } /** diff --git a/src/admin/class-stats.php b/src/admin/class-stats.php index ab398b3..18d1d4e 100644 --- a/src/admin/class-stats.php +++ b/src/admin/class-stats.php @@ -12,6 +12,7 @@ class Cimo_Stats { const OPTION_KEY = 'cimo_stats_data'; const CIMO_META_STRING = 's:4:"cimo";'; + const RATING_NOTICE_THRESHOLD_BYTES = 5242880; // 5 MB. /** * Get all media optimization statistics @@ -155,6 +156,37 @@ public static function get_formatted_stats() { ]; } + /** + * Check if the rating notice should be shown using cached stats only. + * + * This intentionally avoids calling get_stats() so admin menu rendering + * does not trigger attachment metadata compute on every admin page load. + */ + public static function should_show_rating_notice() { + if ( '1' === get_option( 'cimo_rating_dismissed', '0' ) ) { + return false; + } + + return self::get_cached_saved_bytes() >= self::RATING_NOTICE_THRESHOLD_BYTES; + } + + /** + * Get cached total saved bytes without recomputing stats. + */ + private static function get_cached_saved_bytes() { + $stats = get_option( self::OPTION_KEY ); + + if ( ! is_array( $stats ) ) { + return 0; + } + + $kb_before = (float) ( $stats['total_original_size'] ?? 0 ); + $kb_after = (float) ( $stats['total_optimized_size'] ?? 0 ); + $kb_saved = max( 0, $kb_before - $kb_after ); + + return (int) round( $kb_saved * 1024 ); + } + /** * Format bytes into human readable format */ diff --git a/src/admin/js/page/admin-settings.js b/src/admin/js/page/admin-settings.js index 1558808..6005999 100644 --- a/src/admin/js/page/admin-settings.js +++ b/src/admin/js/page/admin-settings.js @@ -286,6 +286,9 @@ const AdminSettings = () => { cimo_rating_dismissed: '1', }, } ) + // Keep the current admin menu in sync without waiting for a page reload. + document.querySelectorAll( '#adminmenu a[href*="page=cimo-settings"] .update-plugins' ) + .forEach( indicator => indicator.remove() ) } catch ( error ) { setIsRatingDismissed( false ) } @@ -404,20 +407,8 @@ const AdminSettings = () => { { ( () => { - const savedStr = window.cimoAdmin?.stats?.total_storage_saved - let showRating = false - if ( typeof savedStr === 'string' ) { - const match = savedStr.match( /^([\d.]+)\s*([a-zA-Z]+)/ ) - if ( match ) { - const num = parseFloat( match[ 1 ] ) - const unit = match[ 2 ].toUpperCase() - if ( unit === 'MB' && num > 5 ) { - showRating = true - } - } - } - - if ( showRating && ! isRatingDismissed ) { + // Show rating notice if user has saved at least 5MB and has not dismissed the notice before. + if ( window.cimoAdmin?.showRatingNotice === '1' && ! isRatingDismissed ) { return (
@@ -438,6 +429,7 @@ const AdminSettings = () => { target="_blank" rel="noopener noreferrer" className="cimo-rating-rate-now" + onClick={ handleDismissRating } __next40pxDefaultSize >