| @@ -181,9 +181,19 @@ | ||
| 181 | 181 | <?php $this->print_template( 'part-settings-webp-missing-message', [ 'count' => $count ] ); ?> |
| 182 | 182 | |
| 183 | 183 | <button id="imagify-generate-webp-versions" class="button imagify-button-primary imagify-button-mini" type="button"> |
| 184 | 184 | <span class="dashicons dashicons-admin-generic"></span> |
| 185 | - <span class="button-text"><?php esc_html_e( 'Generate missing Next-Gen images versions', 'imagify' ); ?></span> | |
| 185 | + <?php | |
| 186 | + /* | |
| 187 | + * Keep this string byte-identical to the ability label in | |
| 188 | + * classes/Abilities/GenerateMissingNextgen.php: same wording means one shared | |
| 189 | + * entry on translate.wordpress.org rather than two. The casing looks off next | |
| 190 | + * to the rest of the UI, but the button is uppercased by CSS, so it renders as | |
| 191 | + * "GENERATE MISSING NEXT-GEN VERSIONS" either way. Re-casing it here would | |
| 192 | + * silently fork the two into separate strings to translate. | |
| 193 | + */ | |
| 194 | + ?> | |
| 195 | + <span class="button-text"><?php esc_html_e( 'Generate missing next-gen versions', 'imagify' ); ?></span> | |
| 186 | 196 | </button> |
| 187 | 197 | |
| 188 | 198 | <?php |
| 189 | 199 | $remaining = OptimizedMediaWithoutNextGen::get_instance()->get_stat(); |
| @@ -197,14 +207,25 @@ | ||
| 197 | 207 | false !== $total |
| 198 | 208 | && |
| 199 | 209 | $total > 0 |
| 200 | 210 | ) { |
| 201 | - $aria = ''; | |
| 202 | - $class = ''; | |
| 203 | - $processed = $total - $remaining; | |
| 204 | - $progress = $processed . '/' . $total; | |
| 205 | - $percent = $processed / $total * 100; | |
| 206 | - $style = 'style="width:' . $percent . '%;"'; | |
| 211 | + $aria = ''; | |
| 212 | + $class = ''; | |
| 213 | + | |
| 214 | + /* | |
| 215 | + * `$total` is a snapshot taken when the run started, while `$remaining` is | |
| 216 | + * recounted on every page load. Anything growing the workload mid-run (new | |
| 217 | + * uploads, or switching the Next-Gen format so every media is missing one) | |
| 218 | + * pushes `$remaining` above `$total`, and `$total - $remaining` goes negative. | |
| 219 | + * Report against the largest workload seen instead. Mirrors getProgress() in | |
| 220 | + * assets/js/options.js. | |
| 221 | + */ | |
| 222 | + $remaining = max( (int) $remaining, 0 ); | |
| 223 | + $effective_total = max( (int) $total, $remaining ); | |
| 224 | + $processed = $effective_total - $remaining; | |
| 225 | + $progress = $processed . '/' . $effective_total; | |
| 226 | + $percent = $effective_total > 0 ? floor( $processed / $effective_total * 100 ) : 0; | |
| 227 | + $style = 'style="width:' . $percent . '%;"'; | |
| 207 | 228 | } |
| 208 | 229 | ?> |
| 209 | 230 | |
| 210 | 231 | <div <?php echo $aria; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> class="imagify-progress <?php echo esc_attr( $class ); ?>"> |