Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/admin/class-admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 .= ' <span class="update-plugins count-1"><span class="plugin-count">' . number_format_i18n( 1 ) . '</span></span>';
}

add_options_page(
__( 'Cimo Settings', 'cimo-image-optimizer' ),
__( 'Cimo', 'cimo-image-optimizer' ),
$menu_title,
'manage_options',
CIMO_SETTINGS_SLUG,
[ $this, 'admin_page_callback' ]
Expand Down Expand Up @@ -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();
Expand All @@ -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'],
] );
Expand Down
5 changes: 5 additions & 0 deletions src/admin/class-metadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}

/**
Expand Down
32 changes: 32 additions & 0 deletions src/admin/class-stats.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
*/
Expand Down
20 changes: 6 additions & 14 deletions src/admin/js/page/admin-settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 )
}
Expand Down Expand Up @@ -404,20 +407,8 @@ const AdminSettings = () => {
</div>

{ ( () => {
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 (
<div className="cimo-header cimo-rating-notice">
<div className="cimo-rating-notice-content">
Expand All @@ -438,6 +429,7 @@ const AdminSettings = () => {
target="_blank"
rel="noopener noreferrer"
className="cimo-rating-rate-now"
onClick={ handleDismissRating }
__next40pxDefaultSize
>
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="lucide lucide-star-icon lucide-star"><path d="M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z" /></svg>
Expand Down
Loading