Llama-3.2-1B-Codex / code_shower.py
Eeppa's picture
Create code_shower.py
0d19d5e verified
import gradio as gr
from typing import Dict, Optional, Tuple
from file_manager import FileManager, CodeFile, Language
from preview_handler import PreviewHandler
class CodeShower:
"""Right panel component for code display, file tree, and previews"""
def __init__(self):
self.current_files: Dict[str, CodeFile] = {}
self.active_file: Optional[str] = None
self.preview_handler = PreviewHandler()
self.file_manager = FileManager()
def create_ui(self):
"""Create the Gradio UI components for the code shower"""
with gr.Column(visible=True, elem_classes="code-shower") as code_column:
gr.Markdown("### 📁 Code Shower")
with gr.Tabs():
with gr.TabItem("📂 Files"):
self.file_tree = gr.HTML(
label="",
value='<div class="file-tree-empty">No files yet.<br>Generate code to see files here.</div>'
)
with gr.TabItem("👁️ Preview"):
self.preview_area = gr.HTML(
label="",
value='<div class="preview-placeholder">Select a file to preview</div>'
)
with gr.TabItem("📝 View Code"):
self.code_area = gr.Code(
label="",
language="python",
value="# Select a file to view code",
interactive=False
)
# Language selector for new files
with gr.Row():
self.new_lang = gr.Dropdown(
choices=["python", "javascript", "html", "css", "json"],
value="python",
label="New file language"
)
self.new_filename = gr.Textbox(
placeholder="filename.py",
label="Filename",
scale=2
)
self.add_file_btn = gr.Button("➕ Add File", size="sm", scale=1)
return {
"file_tree": self.file_tree,
"preview_area": self.preview_area,
"code_area": self.code_area,
"new_lang": self.new_lang,
"new_filename": self.new_filename,
"add_file_btn": self.add_file_btn
}
def update_files_display(self):
"""Update the file tree HTML based on current files"""
if not self.current_files:
return '<div class="file-tree-empty">📂 No files yet<br><small>Generate code to see files here</small></div>'
html = '<div class="file-tree">'
for name, file in self.current_files.items():
active_class = "active" if self.active_file == name else ""
html += f'''
<div class="file-item {active_class}"
data-filename="{name}"
data-language="{file.language.value}"
onclick="window.selectFileFromTree('{name}')">
<span class="file-logo">{file.logo}</span>
<span class="file-name">{name}</span>
<span class="file-badge">{file.language.value}</span>
<button class="file-delete" onclick="event.stopPropagation(); window.deleteFileFromTree('{name}')">🗑️</button>
</div>
'''
html += '</div>'
# Add JavaScript handlers (will be injected via Gradio's JS)
html += '''
<script>
window.selectFileFromTree = function(filename) {
const gradioEl = document.querySelector('gradio-app');
const data = { fn: "select_file", data: [filename] };
gradioEl.dispatchEvent(new CustomEvent('gradio', { detail: data }));
};
window.deleteFileFromTree = function(filename) {
const gradioEl = document.querySelector('gradio-app');
const data = { fn: "delete_file", data: [filename] };
gradioEl.dispatchEvent(new CustomEvent('gradio', { detail: data }));
};
</script>
'''
return html
def display_file(self, filename: str):
"""Display a file's content and preview"""
if filename not in self.current_files:
return "File not found", "File not found", ""
file = self.current_files[filename]
self.active_file = filename
# Generate preview
preview = self.preview_handler.create_preview(file)
# Format code
code_view = self.preview_handler.format_code_with_syntax(file.content, file.language.value)
return preview, code_view, file.content
def add_new_file(self, lang: str, filename: str):
"""Add a new empty file"""
if not filename:
# Generate default filename
ext_map = {
"python": "new_file.py",
"javascript": "new_file.js",
"html": "new_file.html",
"css": "new_file.css",
"json": "new_file.json",
}
filename = ext_map.get(lang, "new_file.txt")
# Template content based on language
templates = {
"python": '# New Python file\n\n\ndef main():\n print("Hello World")\n\nif __name__ == "__main__":\n main()',
"javascript": '// New JavaScript file\n\nconsole.log("Hello World");',
"html": '<!DOCTYPE html>\n<html>\n<head>\n <title>New Page</title>\n</head>\n<body>\n <h1>Hello World</h1>\n</body>\n</html>',
"css": '/* New CSS file */\n\nbody {\n font-family: Arial, sans-serif;\n margin: 0;\n padding: 20px;\n}',
"json": '{\n "name": "example",\n "version": "1.0.0"\n}',
}
content = templates.get(lang, "# New file")
language = self.file_manager.detect_language(filename, content)
self.current_files[filename] = CodeFile(
name=filename,
content=content,
language=language,
logo=self.file_manager.get_logo(language),
extension="." + lang if lang != "javascript" else ".js",
can_preview=language in self.file_manager.PREVIEWABLE
)
return self.update_files_display(), *self.display_file(filename)
def delete_file(self, filename: str):
"""Delete a file from the current collection"""
if filename in self.current_files:
del self.current_files[filename]
if self.active_file == filename:
self.active_file = None
if self.current_files:
first_file = list(self.current_files.keys())[0]
return self.update_files_display(), *self.display_file(first_file)
else:
empty_preview = '<div class="preview-placeholder">No files to preview</div>'
empty_code = '# No files to view'
return self.update_files_display(), empty_preview, empty_code, ""
def extract_and_add_files(self, response_text: str):
"""Parse AI response and extract code blocks as files"""
files = self.file_manager.extract_files_from_code(response_text)
# Add/update files
for name, file in files.items():
self.current_files[name] = file
# Select first file if any
if self.current_files:
first_file = list(self.current_files.keys())[0]
self.active_file = first_file
return self.update_files_display(), *self.display_file(first_file)
return self.update_files_display(), '<div>No code blocks found</div>', '# No code', ""