voiceforge / frontend /components /processing_animation.py
lordofgaming
Initial VoiceForge deployment (clean)
673435a
"""
VoiceForge - Processing Animation Component
Premium animated loading states with time tracking
"""
import streamlit as st
import time
def render_processing_animation(title: str = "PROCESSING", step: str = "Initializing...",
progress: int = 0, elapsed_time: float = 0):
"""
Render a premium ROG-style processing animation with time tracking.
Args:
title: Main title to display
step: Current step description
progress: Progress percentage (0-100)
elapsed_time: Time elapsed in seconds
"""
# Format elapsed time
minutes = int(elapsed_time // 60)
seconds = int(elapsed_time % 60)
time_str = f"{minutes:02d}:{seconds:02d}"
# Calculate gradient position based on progress
gradient_pos = progress * 3.6 # For rotation effect
st.markdown(f"""
<div style="
background: linear-gradient(145deg, #0a0a0a 0%, #1a1a1a 100%);
border: 1px solid #2a2a2a;
border-radius: 12px;
padding: 40px;
text-align: center;
position: relative;
overflow: hidden;
margin: 20px 0;
">
<!-- Animated border glow -->
<div style="
position: absolute;
inset: -2px;
background: linear-gradient({gradient_pos}deg, #ff0033, #00d4ff, #ff0033);
border-radius: 14px;
z-index: -1;
opacity: 0.5;
animation: borderGlow 2s linear infinite;
"></div>
<!-- Inner container -->
<div style="
background: linear-gradient(145deg, #0a0a0a 0%, #1a1a1a 100%);
border-radius: 10px;
padding: 30px;
position: relative;
">
<!-- Spinning ring -->
<div style="
width: 80px;
height: 80px;
margin: 0 auto 20px;
border: 3px solid #2a2a2a;
border-top: 3px solid #ff0033;
border-radius: 50%;
animation: spin 1s linear infinite;
"></div>
<!-- Title -->
<div style="
font-family: 'Orbitron', sans-serif;
font-size: 1.5rem;
font-weight: 700;
color: #ff0033;
text-transform: uppercase;
letter-spacing: 4px;
margin-bottom: 10px;
">{title}</div>
<!-- Step description -->
<div style="
color: #888;
font-size: 0.9rem;
margin-bottom: 20px;
">{step}</div>
<!-- Progress bar -->
<div style="
background: #1a1a1a;
border-radius: 4px;
height: 8px;
overflow: hidden;
margin: 0 auto 15px;
max-width: 300px;
border: 1px solid #333;
">
<div style="
width: {progress}%;
height: 100%;
background: linear-gradient(90deg, #ff0033, #ff6600);
border-radius: 4px;
transition: width 0.3s ease;
box-shadow: 0 0 10px rgba(255, 0, 51, 0.5);
"></div>
</div>
<!-- Stats row -->
<div style="
display: flex;
justify-content: center;
gap: 40px;
margin-top: 20px;
">
<div>
<div style="color: #00d4ff; font-family: 'Orbitron', sans-serif; font-size: 1.5rem; font-weight: 600;">
{progress}%
</div>
<div style="color: #666; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 1px;">
PROGRESS
</div>
</div>
<div>
<div style="color: #ff6600; font-family: 'Orbitron', sans-serif; font-size: 1.5rem; font-weight: 600;">
{time_str}
</div>
<div style="color: #666; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 1px;">
ELAPSED
</div>
</div>
</div>
</div>
</div>
<style>
@keyframes spin {{
0% {{ transform: rotate(0deg); }}
100% {{ transform: rotate(360deg); }}
}}
@keyframes borderGlow {{
0% {{ opacity: 0.3; }}
50% {{ opacity: 0.6; }}
100% {{ opacity: 0.3; }}
}}
</style>
""", unsafe_allow_html=True)
def render_success_animation(title: str = "COMPLETE", subtitle: str = "Processing finished successfully",
stats: dict = None):
"""
Render a success state animation.
Args:
title: Success title
subtitle: Description text
stats: Dictionary of stats to display (e.g., {"Speakers": 3, "Segments": 135})
"""
stats_html = ""
if stats:
stats_items = []
for key, value in stats.items():
stats_items.append(f"""
<div style="text-align: center;">
<div style="color: #00ff88; font-family: 'Orbitron', sans-serif; font-size: 1.8rem; font-weight: 600;">
{value}
</div>
<div style="color: #666; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 1px;">
{key}
</div>
</div>
""")
stats_html = f"""
<div style="display: flex; justify-content: center; gap: 40px; margin-top: 25px;">
{''.join(stats_items)}
</div>
"""
st.markdown(f"""
<div style="
background: linear-gradient(145deg, #0a0a0a 0%, #0d1a0d 100%);
border: 1px solid #00ff88;
border-radius: 12px;
padding: 40px;
text-align: center;
margin: 20px 0;
box-shadow: 0 0 30px rgba(0, 255, 136, 0.2);
">
<!-- Success checkmark -->
<div style="
width: 80px;
height: 80px;
margin: 0 auto 20px;
background: linear-gradient(135deg, #00ff88, #00cc6a);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 2.5rem;
box-shadow: 0 0 20px rgba(0, 255, 136, 0.4);
">✓</div>
<!-- Title -->
<div style="
font-family: 'Orbitron', sans-serif;
font-size: 1.5rem;
font-weight: 700;
color: #00ff88;
text-transform: uppercase;
letter-spacing: 4px;
margin-bottom: 10px;
">{title}</div>
<!-- Subtitle -->
<div style="color: #888; font-size: 0.9rem;">{subtitle}</div>
{stats_html}
</div>
""", unsafe_allow_html=True)