""" UI components for the Magic Story Creator application """ import gradio as gr from config import constants def create_header(): """Create the main header section of the application""" return gr.HTML( '
'
"
This magical tool helps you create personalized stories for children. Follow these simple steps:
Select a story type and tone that your child will enjoy.
Example: Fantasy with Enthusiastic tone
Tell us about the child who will be enjoying the story.
Example: Age 6, English language, interests in dinosaurs and space
Add a subject for your story and how long you'd like it to be.
Example: "Quantum Computing" for 3 minutes of reading time
Click "Create My Magical Story" and watch the magic happen! Once your story appears, click "Create Illustrated Chapters" to add pictures.
First, create your story and then click the "Create Illustrated Chapters!" button to see your story come to life with pictures!
""") def create_chapter_loading_placeholder(): return gr.HTML("""Our wizard is crafting beautiful chapters and illustrations for your story...
{error_message}
Your Adventure Chapters
Click on each chapter to reveal its magical contents!
""") def create_chapter_accordion(index, chapter): """Create an accordion for a story chapter""" with gr.Accordion( label=f"Chapter {index}: {chapter.get('title', 'Untitled')}", open=False, elem_classes="gr-accordion", ): with gr.Blocks(elem_classes="chapter-content-box"): # Chapter content with magical styling gr.HTML(f"""{chapter.get("image_prompt", "")}
{status}
Click the button below to generate a special melody that matches the mood of your adventure!
""") with gr.Blocks(elem_classes="melody-box"): with gr.Row(): with gr.Column(scale=1, min_width=200): generate_melody_button = gr.Button( "๐ต Create Story Soundtrack ๐ต", variant="primary", elem_classes="melody-button", ) melody_status = gr.Markdown("", visible=False) with gr.Column(scale=2): melody_output = gr.Audio( label="Your Story's Magical Soundtrack", interactive=False, autoplay=True, show_download_button=True, show_share_button=False, waveform_options=gr.WaveformOptions( waveform_color="#9c5fff", waveform_progress_color="#6a2fff", skip_length=2, show_controls=True, ), ) return generate_melody_button, melody_status, melody_output # TODO split this further later def create_3d_model_viewer(story: str = "simple yellow duck"): """ Create a 3D model viewer component that displays a mesh from a base64 string. For now, this uses a placeholder HTML with a message and a download link for the mesh. In a real app, you would use a JS 3D viewer (e.g., Three.js) embedded in the HTML. """ gr.HTML("""Click the button below to generate a 3D model from your story!
""") with gr.Blocks(elem_classes="melody-box"): with gr.Row(): with gr.Column(scale=1, min_width=200): generate_model_button = gr.Button( "Create 3D Model ๐จ", variant="primary", elem_classes="melody-button", ) with gr.Column(scale=2): model_viewer = gr.Model3D( label="3D Model Viewer", clear_color=[0.0, 0.0, 0.0, 0.0] ) model_status = gr.Markdown("", visible=False) # Add status message and model display return ( generate_model_button, model_viewer, model_status, ) def create_readme_display(section_titles=None): """ Create a component that displays the project's README file. Optionally filter to show only specific sections by title. Args: section_titles (str or list, optional): If provided, only display these sections of the README. Can be a single string (e.g., "Getting Started") or a list of strings (e.g., ["Getting Started", "Features", "Installation"]). """ import re from pathlib import Path gr.set_static_paths(paths=[Path.cwd().absolute() / "/assets/images"]) # Handle single string for backward compatibility if isinstance(section_titles, str): section_titles = [section_titles] elif section_titles is None: section_titles = [] # Find the README file in the project root directory current_dir = Path(__file__).parent project_root = current_dir.parent readme_paths = [ project_root / "README.md", project_root / "Readme.md", project_root / "readme.md", ] readme_content = "" for path in readme_paths: if path.exists(): with open(path, "r", encoding="utf-8") as f: readme_content = f.read() break if not readme_content: readme_content = "README file not found in the project directory." # If specific sections are requested, extract them if section_titles and readme_content: # Pattern to match headers (# Header, ## Header, etc.) header_pattern = r"^(#+)\s+(.+)$" # Split the content by lines lines = readme_content.split("\n") all_filtered_content = [] # Process each requested section for section_title in section_titles: filtered_content = [] in_target_section = False current_level = 0 for line in lines: # Check if line is a header header_match = re.match(header_pattern, line, re.MULTILINE) if header_match: header_level = len(header_match.group(1)) # Number of # symbols header_text = header_match.group(2).strip() # If we found the target section if header_text.lower() == section_title.lower(): in_target_section = True current_level = header_level filtered_content.append(line) # Include the section header # If we're in the target section and find another header of same or higher level, exit section elif in_target_section and header_level <= current_level: in_target_section = False # Include subsection headers if we're in the target section elif in_target_section: filtered_content.append(line) # Include content if we're in the target section elif in_target_section: filtered_content.append(line) # Add this section's content to our combined content if filtered_content: all_filtered_content.extend(filtered_content) # Add a separator between sections unless it's the last section if section_title != section_titles[-1]: all_filtered_content.append("\n---\n") else: all_filtered_content.append( f"Section '{section_title}' not found in README.\n" ) # Update the content to only the filtered sections if all_filtered_content: readme_content = "\n".join(all_filtered_content) else: readme_content = "None of the requested sections were found in README." # Create a header similar to other components if not section_titles: section_display = "Full Documentation" elif len(section_titles) == 1: section_display = f"{section_titles[0]} Section" else: section_display = "Sections: " + ", ".join(section_titles) # Display the README content using Markdown with gr.Blocks(elem_classes="readme-box"): readme_display = gr.Markdown( value=readme_content, elem_classes="readme-content" ) return readme_display