Improve progress bar UX for encode/decode
- Add indeterminate (barber pole) animation during Argon2/initializing phase - Prevent progress from jumping backwards (fixes flash-to-zero bug) - Initial progress write at 5% when embedding actually starts - Reset progress tracking on new operations Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1009,7 +1009,9 @@ const Stegasoo = {
|
|||||||
const percent = progressData.percent || 0;
|
const percent = progressData.percent || 0;
|
||||||
const phase = progressData.phase || 'processing';
|
const phase = progressData.phase || 'processing';
|
||||||
|
|
||||||
this.updateProgress(percent, this.formatPhase(phase));
|
// Use indeterminate mode for initializing/starting phases
|
||||||
|
const isIndeterminate = (phase === 'initializing' || phase === 'starting');
|
||||||
|
this.updateProgress(percent, this.formatPhase(phase), isIndeterminate);
|
||||||
|
|
||||||
// Continue polling
|
// Continue polling
|
||||||
setTimeout(poll, 500);
|
setTimeout(poll, 500);
|
||||||
@@ -1070,8 +1072,9 @@ const Stegasoo = {
|
|||||||
document.body.appendChild(modal);
|
document.body.appendChild(modal);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset progress
|
// Reset progress tracking and start with indeterminate state
|
||||||
this.updateProgress(0, 'Initializing...');
|
this.resetProgressTracking();
|
||||||
|
this.updateProgress(0, 'Initializing...', true);
|
||||||
|
|
||||||
// Show modal
|
// Show modal
|
||||||
const bsModal = new bootstrap.Modal(modal);
|
const bsModal = new bootstrap.Modal(modal);
|
||||||
@@ -1090,16 +1093,47 @@ const Stegasoo = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update progress bar and text
|
* Track max progress to prevent backwards jumps
|
||||||
*/
|
*/
|
||||||
updateProgress(percent, phase) {
|
_maxProgress: 0,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset progress tracking (call when starting new operation)
|
||||||
|
*/
|
||||||
|
resetProgressTracking() {
|
||||||
|
this._maxProgress = 0;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update progress bar and text
|
||||||
|
* Supports indeterminate mode for initializing phase (barber pole at full width)
|
||||||
|
*/
|
||||||
|
updateProgress(percent, phase, indeterminate = false) {
|
||||||
const progressBar = document.getElementById('progressBar');
|
const progressBar = document.getElementById('progressBar');
|
||||||
const progressText = document.getElementById('progressText');
|
const progressText = document.getElementById('progressText');
|
||||||
const phaseText = document.getElementById('progressPhase');
|
const phaseText = document.getElementById('progressPhase');
|
||||||
|
|
||||||
if (progressBar) progressBar.style.width = percent + '%';
|
if (indeterminate) {
|
||||||
if (progressText) progressText.textContent = Math.round(percent) + '%';
|
// Barber pole animation at full width, no percentage
|
||||||
|
if (progressBar) {
|
||||||
|
progressBar.style.width = '100%';
|
||||||
|
progressBar.classList.add('progress-bar-striped', 'progress-bar-animated');
|
||||||
|
}
|
||||||
|
if (progressText) progressText.textContent = '';
|
||||||
if (phaseText) phaseText.textContent = phase;
|
if (phaseText) phaseText.textContent = phase;
|
||||||
|
} else {
|
||||||
|
// Determinate progress - never go backwards
|
||||||
|
const safePercent = Math.max(percent, this._maxProgress);
|
||||||
|
this._maxProgress = safePercent;
|
||||||
|
|
||||||
|
if (progressBar) {
|
||||||
|
progressBar.style.width = safePercent + '%';
|
||||||
|
// Keep animation but show actual progress
|
||||||
|
progressBar.classList.add('progress-bar-striped', 'progress-bar-animated');
|
||||||
|
}
|
||||||
|
if (progressText) progressText.textContent = Math.round(safePercent) + '%';
|
||||||
|
if (phaseText) phaseText.textContent = phase;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
@@ -1187,7 +1221,9 @@ const Stegasoo = {
|
|||||||
const percent = progressData.percent || 0;
|
const percent = progressData.percent || 0;
|
||||||
const phase = progressData.phase || 'processing';
|
const phase = progressData.phase || 'processing';
|
||||||
|
|
||||||
this.updateProgress(percent, this.formatDecodePhase(phase));
|
// Use indeterminate mode for initializing/starting/loading phases
|
||||||
|
const isIndeterminate = (phase === 'initializing' || phase === 'starting' || phase === 'loading');
|
||||||
|
this.updateProgress(percent, this.formatDecodePhase(phase), isIndeterminate);
|
||||||
|
|
||||||
// Continue polling
|
// Continue polling
|
||||||
setTimeout(poll, 500);
|
setTimeout(poll, 500);
|
||||||
|
|||||||
@@ -919,6 +919,10 @@ def _embed_in_channel_safe(
|
|||||||
blocks_needed = (total_bits + bits_per_block - 1) // bits_per_block
|
blocks_needed = (total_bits + bits_per_block - 1) // bits_per_block
|
||||||
blocks_to_process = min(blocks_needed, len(block_order))
|
blocks_to_process = min(blocks_needed, len(block_order))
|
||||||
|
|
||||||
|
# Initial progress write - signals Argon2/prep is done, embedding starting
|
||||||
|
if progress_file:
|
||||||
|
_write_progress(progress_file, 5, 100, "embedding")
|
||||||
|
|
||||||
# Vectorized embedding: process blocks in batches
|
# Vectorized embedding: process blocks in batches
|
||||||
BATCH_SIZE = 500
|
BATCH_SIZE = 500
|
||||||
bit_idx = 0
|
bit_idx = 0
|
||||||
@@ -1113,6 +1117,10 @@ def _embed_jpegio(
|
|||||||
total_bits = len(bits)
|
total_bits = len(bits)
|
||||||
progress_interval = max(total_bits // 20, 100) # Report ~20 times or every 100 bits
|
progress_interval = max(total_bits // 20, 100) # Report ~20 times or every 100 bits
|
||||||
|
|
||||||
|
# Initial progress write - signals prep is done, embedding starting
|
||||||
|
if progress_file:
|
||||||
|
_write_progress(progress_file, 5, 100, "embedding")
|
||||||
|
|
||||||
for bit_idx, pos_idx in enumerate(order):
|
for bit_idx, pos_idx in enumerate(order):
|
||||||
if bit_idx >= len(bits):
|
if bit_idx >= len(bits):
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -746,6 +746,10 @@ def _embed_lsb(
|
|||||||
modified_pixels = 0
|
modified_pixels = 0
|
||||||
total_pixels_to_process = len(selected_indices)
|
total_pixels_to_process = len(selected_indices)
|
||||||
|
|
||||||
|
# Initial progress write - signals prep is done, embedding starting
|
||||||
|
if progress_file:
|
||||||
|
_write_progress(progress_file, 5, 100, "embedding")
|
||||||
|
|
||||||
for progress_idx, pixel_idx in enumerate(selected_indices):
|
for progress_idx, pixel_idx in enumerate(selected_indices):
|
||||||
if bit_idx >= len(binary_data):
|
if bit_idx >= len(binary_data):
|
||||||
break
|
break
|
||||||
|
|||||||
Reference in New Issue
Block a user