File size: 6,866 Bytes
8246252
0a9c605
227495f
 
 
 
 
 
0a9c605
a73275a
0a9c605
9b8ec81
227495f
 
8246252
227495f
 
 
4ad460d
227495f
4ad460d
 
227495f
 
 
 
 
 
 
 
 
 
8246252
227495f
 
 
 
 
 
4ad460d
227495f
4ad460d
 
227495f
 
 
9b8ec81
227495f
 
 
 
 
 
 
 
 
8246252
 
 
9b8ec81
 
 
227495f
 
 
 
 
 
a73275a
227495f
 
 
 
 
 
46c562f
227495f
 
 
 
 
46c562f
227495f
 
 
46c562f
227495f
 
 
 
a73275a
 
8246252
 
a73275a
8246252
 
 
 
 
227495f
46c562f
 
227495f
 
 
46c562f
9b8ec81
 
 
 
 
a73275a
 
 
227495f
a73275a
227495f
 
 
 
 
a73275a
 
8246252
9b8ec81
227495f
a73275a
227495f
 
 
0a9c605
a73275a
 
 
 
 
 
 
 
0a9c605
227495f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# /app.py (Final Corrected Version)

"""
Main Gradio application for AnyCoder.

This file defines the user interface, handles user interactions, and orchestrates
the calls to the backend logic in other modules.
"""
import gradio as gr
import os

from config import AVAILABLE_MODELS, MULTIMODAL_MODELS
from core import generate_code
from deployment import deploy_to_hf_space
from utils import get_gradio_language, history_to_chatbot_messages

# --- UI Helper Functions ---
def send_to_sandbox(code: str, language: str) -> str:
    """Generates an iframe for the preview tab, safely handling quotes."""
    if language == "html" and code:
        safe_code = code.replace('"', '"')
        return f'<iframe srcdoc="{safe_code}" width="100%" height="920px" style="border:0;"></iframe>'
    return "<div style='padding:1em;color:#888;text-align:center;'>Preview is only for HTML.</div>"

# --- Event Handlers ---
def on_generate_click(
    query: str, image: gr.Image, file: gr.File, website_url: str,
    history: list, model_name: str, enable_search: bool, language: str
):
    if not query and not image and not file and not website_url:
        yield {
            code_output: gr.update(value="Please provide a prompt, image, file, or URL.", language="text"),
            history_output: history_to_chatbot_messages(history)
        }
        return

    model_config = next((m for m in AVAILABLE_MODELS if m['name'] == model_name), AVAILABLE_MODELS[0])

    for response in generate_code(query, image, file.name if file else None, website_url, history, model_config, enable_search, language):
        preview_code = response.get("code_output", "")
        ui_update = {
            code_output: gr.update(value=preview_code, language=get_gradio_language(language)),
            sandbox: send_to_sandbox(preview_code, language)
        }
        if "history" in response:
            ui_update[history_state] = response["history"]
            ui_update[history_output] = history_to_chatbot_messages(response["history"])
        yield ui_update

def on_model_change(model_name: str):
    model_id = next((m['id'] for m in AVAILABLE_MODELS if m['name'] == model_name), None)
    return gr.update(visible=model_id in MULTIMODAL_MODELS)

def on_language_change(language: str):
    return gr.update(language=get_gradio_language(language))

def on_deploy_click(code: str, space_name: str, sdk_name: str, request: gr.Request):
    """Handler for the deploy button, now correctly using gr.Request."""
    hf_token = request.token
    if not hf_token:
        return gr.update(value="⚠️ Please log in with your Hugging Face account to deploy.", visible=True)
    
    sdk_map = {"Static (HTML)": "static", "Gradio (Python)": "gradio"}
    sdk = sdk_map.get(sdk_name, "static")
    return gr.update(value=deploy_to_hf_space(code, space_name, sdk, hf_token), visible=True)

# --- Gradio UI Layout ---
with gr.Blocks(theme=gr.themes.Default(primary_hue="blue"), title="AnyCoder") as demo:
    # 1. DEFINE ALL COMPONENTS FIRST
    history_state = gr.State([])

    gr.Markdown("# 🤖 AnyCoder - AI Code Generator")
    gr.Markdown("Describe what you want to build, upload a design, or provide a URL to redesign. The AI will generate the code for you.")

    with gr.Row():
        with gr.Column(scale=1):
            input_prompt = gr.Textbox(label="Prompt", placeholder="e.g., a login form with a blue button", lines=3)
            language_dropdown = gr.Dropdown(choices=["html", "python", "javascript", "css"], value="html", label="Language")
            website_url_input = gr.Textbox(label="URL to Redesign", placeholder="https://example.com")
            file_input = gr.File(label="Reference File (PDF, TXT, DOCX, image)")
            image_input = gr.Image(label="UI Design Image", type="numpy", visible=False)
            
            with gr.Accordion("Settings", open=False):
                model_dropdown = gr.Dropdown(choices=[m['name'] for m in AVAILABLE_MODELS], value=AVAILABLE_MODELS[0]['name'], label="Model")
                search_toggle = gr.Checkbox(label="Enable Web Search", value=False)
            
            with gr.Row():
                clear_btn = gr.Button("Clear")
                generate_btn = gr.Button("Generate", variant="primary", scale=2)

            # Conditionally define the deployment components
            # We must define them here so they exist for the event wiring later.
            if os.getenv("SPACE_ID"):
                with gr.Accordion("🚀 Deploy to Hugging Face", open=False):
                    login_button = gr.LoginButton() # This is just a placeholder in this context
                    space_name_input = gr.Textbox(label="New App Name", placeholder="my-cool-app")
                    sdk_dropdown = gr.Dropdown(choices=["Static (HTML)", "Gradio (Python)"], value="Static (HTML)", label="App Type")
                    deploy_btn = gr.Button("Deploy")
                    deploy_status = gr.Markdown(visible=False)
            
        with gr.Column(scale=2):
            with gr.Tabs():
                with gr.Tab("Preview"):
                    sandbox = gr.HTML(label="Live Preview", elem_id="sandbox-preview")
                with gr.Tab("Code"):
                    code_output = gr.Code(label="Generated Code", language="html", interactive=True)
                with gr.Tab("History"):
                    history_output = gr.Chatbot(
                        label="Conversation History", 
                        type="messages",
                        height=500
                    )

    # 2. WIRE UP ALL EVENTS AT THE END
    # This ensures all component variables (like 'code_output') are defined before being used.
    
    # Main generation event
    generate_btn.click(
        fn=on_generate_click,
        inputs=[input_prompt, image_input, file_input, website_url_input, history_state, model_dropdown, search_toggle, language_dropdown],
        outputs=[code_output, sandbox, history_state, history_output]
    )

    # Clear button event
    clear_btn.click(lambda: ([], [], None, None, None, "", ""), 
                    outputs=[history_state, history_output, input_prompt, image_input, file_input, website_url_input, code_output])
    
    # UI change events
    model_dropdown.change(on_model_change, inputs=model_dropdown, outputs=image_input)
    language_dropdown.change(on_language_change, inputs=language_dropdown, outputs=code_output)
    language_dropdown.change(lambda code, lang: send_to_sandbox(code, lang), inputs=[code_output, language_dropdown], outputs=sandbox)

    # Conditionally wire up the deployment event
    if os.getenv("SPACE_ID"):
        deploy_btn.click(
            on_deploy_click,
            inputs=[code_output, space_name_input, sdk_dropdown],
            outputs=deploy_status
        )

if __name__ == "__main__":
    demo.queue().launch()