|
""" |
|
Main application entry point file for the Magic Story Creator |
|
""" |
|
|
|
import gradio as gr |
|
import logging |
|
from dotenv import load_dotenv |
|
from pathlib import Path |
|
from ui.styles import main_css |
|
from ui.components import ( |
|
create_chapter_loading_placeholder, |
|
create_header, |
|
create_instructions_accordion, |
|
create_story_tab_header, |
|
create_step_heading, |
|
create_story_options, |
|
create_reader_details, |
|
create_story_details, |
|
create_story_action_buttons, |
|
create_loading_container, |
|
story_ready_header, |
|
create_story_output_container, |
|
create_chapter_loading_container, |
|
create_empty_chapters_placeholder, |
|
create_chapter_error_display, |
|
create_story_title_display, |
|
create_chapter_navigation, |
|
create_chapter_accordion, |
|
create_story_melody_section, |
|
create_3d_model_viewer, |
|
create_readme_display, |
|
) |
|
|
|
|
|
from controllers.app_controller import ( |
|
generate_audio_with_status, |
|
generate_melody_from_story_with_status, |
|
generate_3d_model, |
|
) |
|
from ui.events import setup_event_handlers |
|
|
|
|
|
logging.basicConfig( |
|
level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s" |
|
) |
|
logger = logging.getLogger(__name__) |
|
|
|
|
|
load_dotenv() |
|
|
|
|
|
gr.set_static_paths(paths=[Path.cwd().absolute() / "assets/images"]) |
|
|
|
|
|
def create_app(): |
|
"""Create the main Gradio app for Magic Story Creator""" |
|
with gr.Blocks( |
|
css=main_css, |
|
theme=gr.themes.Ocean(), |
|
title="Magic Tales", |
|
) as demo: |
|
|
|
create_header() |
|
|
|
|
|
create_instructions_accordion() |
|
|
|
|
|
tabs = gr.Tabs() |
|
with tabs: |
|
|
|
with gr.Tab("Story Generator"): |
|
create_story_tab_header() |
|
|
|
|
|
with gr.Column(elem_classes="gr-form"): |
|
gr.HTML(create_step_heading(1, "Choose your adventure!")) |
|
story_type, tone = create_story_options() |
|
|
|
|
|
with gr.Column(elem_classes="gr-form"): |
|
gr.HTML(create_step_heading(2, "Tell us about the reader!")) |
|
kid_age, kid_language, kid_interests = create_reader_details() |
|
|
|
|
|
with gr.Column(elem_classes="gr-form"): |
|
gr.HTML(create_step_heading(3, "Story details")) |
|
subject, reading_time, pdf_upload, model_selector = ( |
|
create_story_details() |
|
) |
|
|
|
|
|
generate_button, clear_button = create_story_action_buttons() |
|
|
|
|
|
with gr.Row(visible=False): |
|
create_loading_container() |
|
|
|
|
|
with gr.Blocks(elem_classes="gr-form", visible=False): |
|
story_ready_header() |
|
story_title, story_text, process_chapters_button = ( |
|
create_story_output_container() |
|
) |
|
|
|
|
|
with gr.Tab("Chapters & Image Prompts"): |
|
|
|
chapters_state = gr.State(value=None) |
|
|
|
|
|
chapter_loading_container = create_chapter_loading_container() |
|
|
|
|
|
def show_chapter_progress_container(): |
|
return gr.update(visible=True) |
|
|
|
|
|
process_chapters_button.click( |
|
show_chapter_progress_container, |
|
inputs=[], |
|
outputs=[chapter_loading_container], |
|
) |
|
|
|
@gr.render(inputs=[chapters_state]) |
|
def render_chapters(chapters_data): |
|
if chapters_data is None: |
|
return create_empty_chapters_placeholder() |
|
|
|
|
|
if isinstance(chapters_data, str) and chapters_data.startswith( |
|
"Error:" |
|
): |
|
return create_chapter_error_display(chapters_data) |
|
elif isinstance(chapters_data, dict) and "error" in chapters_data: |
|
return create_chapter_error_display(chapters_data["error"]) |
|
|
|
|
|
if isinstance(chapters_data, dict) and chapters_data.get( |
|
"processing", False |
|
): |
|
|
|
chapters = chapters_data.get("chapters", []) |
|
if chapters: |
|
|
|
create_story_title_display( |
|
chapters_data.get("title", "Story Chapters") |
|
) |
|
|
|
|
|
create_chapter_navigation() |
|
|
|
|
|
for i, chapter in enumerate(chapters, 1): |
|
status = chapter.get( |
|
"status", "Creating your magical illustration..." |
|
) |
|
|
|
( |
|
read_aloud_btn, |
|
read_aloud_audio, |
|
chapter_content_state, |
|
audio_statuss, |
|
) = create_chapter_accordion(index=i, chapter=chapter) |
|
|
|
|
|
read_aloud_btn.click( |
|
generate_audio_with_status, |
|
inputs=[chapter_content_state], |
|
outputs=[read_aloud_audio, audio_statuss], |
|
) |
|
|
|
return gr.update() |
|
else: |
|
|
|
return create_chapter_loading_placeholder() |
|
|
|
|
|
create_story_title_display( |
|
chapters_data.get("title", "Story Chapters") |
|
) |
|
|
|
|
|
create_chapter_navigation() |
|
|
|
|
|
for i, chapter in enumerate(chapters_data.get("chapters", []), 1): |
|
( |
|
read_aloud_btn, |
|
read_aloud_audio, |
|
chapter_content_state, |
|
audio_statuss, |
|
) = create_chapter_accordion(index=i, chapter=chapter) |
|
|
|
read_aloud_btn.click( |
|
generate_audio_with_status, |
|
inputs=[chapter_content_state], |
|
outputs=[read_aloud_audio, audio_statuss], |
|
) |
|
|
|
|
|
generate_melody_button, melody_status, melody_output = ( |
|
create_story_melody_section() |
|
) |
|
|
|
generate_melody_button.click( |
|
generate_melody_from_story_with_status, |
|
inputs=[story_text], |
|
outputs=[melody_output, melody_status], |
|
) |
|
|
|
|
|
generate_model_button, model_viewer, model_status = ( |
|
create_3d_model_viewer(story_text) |
|
) |
|
|
|
generate_model_button.click( |
|
generate_3d_model, |
|
inputs=[story_text], |
|
outputs=[model_viewer, model_status], |
|
) |
|
|
|
with gr.Tab("README"): |
|
create_readme_display( |
|
["π Magical Tales: Where Imagination Comes Alive! πβ¨"] |
|
) |
|
|
|
|
|
""" with gr.Tab("Character Counter"): |
|
letter_counter_component() """ |
|
|
|
|
|
setup_event_handlers( |
|
generate_button=generate_button, |
|
clear_button=clear_button, |
|
process_chapters_button=process_chapters_button, |
|
story_type=story_type, |
|
tone=tone, |
|
kid_age=kid_age, |
|
kid_language=kid_language, |
|
kid_interests=kid_interests, |
|
subject=subject, |
|
reading_time=reading_time, |
|
pdf_upload=pdf_upload, |
|
model_selector=model_selector, |
|
story_title=story_title, |
|
story_text=story_text, |
|
chapters_state=chapters_state, |
|
chapter_loading_container=chapter_loading_container, |
|
) |
|
|
|
return demo |
|
|
|
|
|
|
|
demo = create_app() |
|
|
|
|
|
if __name__ == "__main__": |
|
try: |
|
logger.info("Starting Magic Story Creator app") |
|
demo.launch(mcp_server=True) |
|
except Exception as e: |
|
logger.error(f"Failed to start app: {e}", exc_info=True) |
|
|