Slide_gator / app.py
cryogenic22's picture
Update app.py
58e5138 verified
import streamlit as st
# Set page config - must be the first Streamlit command
st.set_page_config(
page_title="SlideGator.AI",
page_icon="🐊",
layout="wide",
initial_sidebar_state="expanded"
)
import uuid
import os
import json
from updated_components import (
render_ideation_stage,
render_storyboard_stage,
render_template_stage,
render_slides_stage,
render_export_stage,
render_ai_settings
)
from multi_llm_provider import get_ai_manager
# Check and display API key status
api_key = os.getenv("ANTHROPIC_API_KEY")
openai_key = os.getenv("OPENAI_API_KEY")
deepseek_key = os.getenv("DEEPSEEK_API_KEY")
perplexity_key = os.getenv("PERPLEXITY_API_KEY")
pexels_key = os.getenv("PEXELS_API_KEY")
# Add custom CSS
st.markdown("""
<style>
.main .block-container {
padding-top: 2rem;
padding-bottom: 2rem;
}
h1, h2, h3 {
margin-bottom: 1rem;
}
.stButton>button {
width: 100%;
}
.stProgress>div>div>div {
background-color: #4CAF50;
}
.css-18e3th9 {
padding-top: 2rem;
}
/* Progress bar styling */
.stProgress {
height: 10px !important;
}
/* Custom slide preview styling */
.slide-preview {
border-radius: 8px !important;
box-shadow: 0 4px 8px rgba(0,0,0,0.1) !important;
transition: transform 0.3s ease, box-shadow 0.3s ease !important;
}
.slide-preview:hover {
transform: translateY(-5px) !important;
box-shadow: 0 6px 12px rgba(0,0,0,0.15) !important;
}
/* SlideGator branding */
.logo-text {
color: #4CAF50;
font-weight: bold;
font-family: 'Arial', sans-serif;
}
/* Stage icons */
.stage-icon {
font-size: 1.5rem;
margin-right: 0.5rem;
}
/* Custom button styles */
.gator-button {
background-color: #4CAF50;
color: white;
border-radius: 5px;
padding: 8px 16px;
font-weight: bold;
transition: all 0.3s;
}
.gator-button:hover {
background-color: #45a049;
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}
/* AI settings panel */
.ai-settings {
background-color: #f9f9f9;
border-radius: 8px;
padding: 12px;
margin-top: 15px;
border: 1px solid #eee;
}
/* Enhanced image cards */
.image-card {
border: 1px solid #ddd;
border-radius: 8px;
overflow: hidden;
transition: transform 0.3s ease;
}
.image-card:hover {
transform: scale(1.03);
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
/* Tabs styling */
.stTabs [data-baseweb="tab-list"] {
gap: 8px;
}
.stTabs [data-baseweb="tab"] {
height: 50px;
white-space: pre-wrap;
background-color: #f0f2f6;
border-radius: 4px 4px 0 0;
padding: 8px 16px;
font-weight: 600;
}
.stTabs [aria-selected="true"] {
background-color: #4CAF50 !important;
color: white !important;
}
</style>
""", unsafe_allow_html=True)
# Initialize session state variables if they don't exist
if "session_id" not in st.session_state:
st.session_state.session_id = str(uuid.uuid4())
if "current_stage" not in st.session_state:
st.session_state.current_stage = "ideation"
if "presentation_title" not in st.session_state:
st.session_state.presentation_title = ""
if "presentation_purpose" not in st.session_state:
st.session_state.presentation_purpose = ""
if "target_audience" not in st.session_state:
st.session_state.target_audience = ""
if "storyboard" not in st.session_state:
st.session_state.storyboard = []
if "selected_template" not in st.session_state:
st.session_state.selected_template = "professional"
if "slides_content" not in st.session_state:
st.session_state.slides_content = []
if "default_model" not in st.session_state:
st.session_state.default_model = "claude-3-sonnet-20250219"
if "ai_temperature" not in st.session_state:
st.session_state.ai_temperature = 0.7
if "enable_web_search" not in st.session_state:
st.session_state.enable_web_search = False
# Initialize AI provider manager
ai_manager = get_ai_manager()
# Sidebar
with st.sidebar:
# Custom SlideGator logo and title
st.markdown("""
<div style="display: flex; align-items: center; margin-bottom: 1rem;">
<div style="font-size: 2.5rem; margin-right: 0.5rem;">🐊</div>
<div>
<div style="font-size: 1.5rem; font-weight: bold; color: #4CAF50;">SlideGator.AI</div>
<div style="font-size: 0.8rem; color: #666;">Snapping up presentation perfection</div>
</div>
</div>
""", unsafe_allow_html=True)
# Display API information
api_status = []
if api_key:
api_status.append("🟒 Claude AI")
else:
api_status.append("πŸ”΄ Claude AI (not connected)")
if openai_key:
api_status.append("🟒 OpenAI")
else:
api_status.append("βšͺ OpenAI (optional)")
if deepseek_key:
api_status.append("🟒 DeepSeek")
else:
api_status.append("βšͺ DeepSeek (optional)")
if perplexity_key:
api_status.append("🟒 Perplexity")
else:
api_status.append("βšͺ Web Search (optional)")
if pexels_key:
api_status.append("🟒 Stock Images")
else:
api_status.append("βšͺ Stock Images (optional)")
st.info("\n".join(api_status))
if not api_key:
st.error("⚠️ ANTHROPIC_API_KEY environment variable not found. The app will use fallback content generation.")
# Display current progress
st.write("## Your Journey")
stages = [
{"name": "Ideation", "icon": "πŸ’‘"},
{"name": "Storyboard", "icon": "πŸ“‹"},
{"name": "Template", "icon": "🎨"},
{"name": "Slides", "icon": "πŸ–ΌοΈ"},
{"name": "Export", "icon": "πŸ“€"}
]
current_stage_idx = stages.index(next((s for s in stages if s["name"].lower() == st.session_state.current_stage), stages[0]))
progress_value = (current_stage_idx) / (len(stages) - 1)
st.progress(progress_value)
# Display all stages and highlight current
for i, stage in enumerate(stages):
if i == current_stage_idx:
st.markdown(f"### {stage['icon']} {stage['name']} β—€")
else:
st.markdown(f"### {stage['icon']} {stage['name']}")
st.write("---")
# Settings accordion
with st.expander("βš™οΈ Settings", expanded=False):
# Show presentation info
if st.session_state.presentation_title:
st.write(f"**Title:** {st.session_state.presentation_title}")
if st.session_state.selected_template:
st.write(f"**Template:** {st.session_state.selected_template.title()}")
# Show slide count
if st.session_state.slides_content:
st.write(f"**Slides:** {len(st.session_state.slides_content)}")
elif st.session_state.storyboard:
st.write(f"**Planned Slides:** {len(st.session_state.storyboard)}")
# Debugging options
show_debug = st.checkbox("Show Debug Info", value=False)
if show_debug:
st.code(json.dumps({k: v for k, v in st.session_state.items() if k not in ["custom_template", "ai_manager", "slides_content", "storyboard"]}, default=str, indent=2))
st.markdown("""
<div style="text-align: center;">
<div>Made with πŸ’š by SlideGator.AI</div>
<div style="font-size: 0.8rem; color: #666;">Powered by Claude AI</div>
</div>
""", unsafe_allow_html=True)
# Jump to stage buttons (for development/testing)
if st.checkbox("Development Mode", value=False):
st.write("Jump to stage:")
col1, col2 = st.columns(2)
for i, stage in enumerate(stages):
with col1 if i % 2 == 0 else col2:
if st.button(f"{stage['icon']} {stage['name']}", key=f"jump_{stage['name']}"):
st.session_state.current_stage = stage['name'].lower()
st.rerun()
# Main content
st.markdown("""
<div style="display: flex; align-items: center; margin-bottom: 1rem;">
<div style="font-size: 3rem; margin-right: 1rem;">🐊</div>
<div>
<h1 style="margin: 0; color: #4CAF50;">SlideGator.AI</h1>
<div style="font-size: 1.2rem;">Create professional presentations with AI-powered storyboarding and content generation</div>
</div>
</div>
""", unsafe_allow_html=True)
# Display different UI based on current stage
if st.session_state.current_stage == "ideation":
render_ideation_stage()
elif st.session_state.current_stage == "storyboard":
render_storyboard_stage()
elif st.session_state.current_stage == "template":
render_template_stage()
elif st.session_state.current_stage == "slides":
render_slides_stage()
elif st.session_state.current_stage == "export":
render_export_stage()