diff --git a/frontends/web/static/js/stegasoo.js b/frontends/web/static/js/stegasoo.js index 21cc2df..21ddefb 100644 --- a/frontends/web/static/js/stegasoo.js +++ b/frontends/web/static/js/stegasoo.js @@ -1009,7 +1009,9 @@ const Stegasoo = { const percent = progressData.percent || 0; 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 setTimeout(poll, 500); @@ -1070,8 +1072,9 @@ const Stegasoo = { document.body.appendChild(modal); } - // Reset progress - this.updateProgress(0, 'Initializing...'); + // Reset progress tracking and start with indeterminate state + this.resetProgressTracking(); + this.updateProgress(0, 'Initializing...', true); // Show 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 progressText = document.getElementById('progressText'); const phaseText = document.getElementById('progressPhase'); - if (progressBar) progressBar.style.width = percent + '%'; - if (progressText) progressText.textContent = Math.round(percent) + '%'; - if (phaseText) phaseText.textContent = phase; + if (indeterminate) { + // 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; + } 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 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 setTimeout(poll, 500); diff --git a/src/stegasoo/dct_steganography.py b/src/stegasoo/dct_steganography.py index f2849a3..71040b6 100644 --- a/src/stegasoo/dct_steganography.py +++ b/src/stegasoo/dct_steganography.py @@ -919,6 +919,10 @@ def _embed_in_channel_safe( blocks_needed = (total_bits + bits_per_block - 1) // bits_per_block 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 BATCH_SIZE = 500 bit_idx = 0 @@ -1113,6 +1117,10 @@ def _embed_jpegio( total_bits = len(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): if bit_idx >= len(bits): break diff --git a/src/stegasoo/steganography.py b/src/stegasoo/steganography.py index ad31342..4111d08 100644 --- a/src/stegasoo/steganography.py +++ b/src/stegasoo/steganography.py @@ -746,6 +746,10 @@ def _embed_lsb( modified_pixels = 0 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): if bit_idx >= len(binary_data): break