XXXMARK commited on
Commit
fdac33d
·
verified ·
1 Parent(s): 86ea54c

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +832 -19
index.html CHANGED
@@ -1,19 +1,832 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>AI Code Creator - Qwen & DeepSeek Edition</title>
7
+
8
+ <!-- Icons -->
9
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
10
+ <!-- JSZip for Exporting -->
11
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
12
+ <!-- FileSaver for Saving -->
13
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"></script>
14
+
15
+ <style>
16
+ :root {
17
+ --bg-dark: #0f0f0f;
18
+ --bg-panel: #1a1a1a;
19
+ --bg-panel-hover: #252525;
20
+ --primary: #FFD700; /* Gold/Yellow */
21
+ --primary-dim: #b39700;
22
+ --text-main: #ffffff;
23
+ --text-muted: #a0a0a0;
24
+ --border: #333;
25
+ --code-bg: #111;
26
+ --accent-blue: #3b82f6;
27
+ --success: #10b981;
28
+ }
29
+
30
+ * {
31
+ box-sizing: border-box;
32
+ margin: 0;
33
+ padding: 0;
34
+ scrollbar-width: thin;
35
+ scrollbar-color: var(--primary) var(--bg-dark);
36
+ }
37
+
38
+ body {
39
+ font-family: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
40
+ background-color: var(--bg-dark);
41
+ color: var(--text-main);
42
+ height: 100vh;
43
+ display: flex;
44
+ flex-direction: column;
45
+ overflow: hidden;
46
+ }
47
+
48
+ /* --- Header --- */
49
+ header {
50
+ height: 60px;
51
+ background-color: var(--bg-panel);
52
+ border-bottom: 1px solid var(--border);
53
+ display: flex;
54
+ align-items: center;
55
+ justify-content: space-between;
56
+ padding: 0 20px;
57
+ z-index: 10;
58
+ }
59
+
60
+ .logo {
61
+ font-size: 1.2rem;
62
+ font-weight: bold;
63
+ color: var(--primary);
64
+ display: flex;
65
+ align-items: center;
66
+ gap: 10px;
67
+ text-decoration: none;
68
+ }
69
+
70
+ .logo span { color: white; }
71
+
72
+ .header-controls {
73
+ display: flex;
74
+ gap: 15px;
75
+ }
76
+
77
+ button {
78
+ background-color: var(--bg-panel);
79
+ border: 1px solid var(--border);
80
+ color: var(--text-main);
81
+ padding: 8px 16px;
82
+ border-radius: 6px;
83
+ cursor: pointer;
84
+ transition: all 0.2s;
85
+ font-size: 0.9rem;
86
+ display: flex;
87
+ align-items: center;
88
+ gap: 8px;
89
+ }
90
+
91
+ button:hover {
92
+ background-color: var(--bg-panel-hover);
93
+ border-color: var(--primary);
94
+ }
95
+
96
+ button.primary {
97
+ background-color: var(--primary);
98
+ color: #000;
99
+ font-weight: bold;
100
+ border: none;
101
+ }
102
+
103
+ button.primary:hover {
104
+ background-color: var(--primary-dim);
105
+ }
106
+
107
+ /* --- Main Layout --- */
108
+ .app-container {
109
+ display: flex;
110
+ flex: 1;
111
+ height: calc(100vh - 60px);
112
+ }
113
+
114
+ /* --- Sidebar (Files, History) --- */
115
+ .sidebar {
116
+ width: 250px;
117
+ background-color: var(--bg-panel);
118
+ border-right: 1px solid var(--border);
119
+ display: flex;
120
+ flex-direction: column;
121
+ }
122
+
123
+ .sidebar-header {
124
+ padding: 15px;
125
+ border-bottom: 1px solid var(--border);
126
+ font-weight: bold;
127
+ color: var(--primary);
128
+ }
129
+
130
+ .file-list, .history-list {
131
+ flex: 1;
132
+ overflow-y: auto;
133
+ padding: 10px;
134
+ }
135
+
136
+ .file-item {
137
+ padding: 10px;
138
+ margin-bottom: 5px;
139
+ border-radius: 4px;
140
+ cursor: pointer;
141
+ display: flex;
142
+ align-items: center;
143
+ gap: 10px;
144
+ font-size: 0.9rem;
145
+ }
146
+
147
+ .file-item:hover, .file-item.active {
148
+ background-color: var(--bg-panel-hover);
149
+ color: var(--primary);
150
+ }
151
+
152
+ /* --- Editor Area --- */
153
+ .editor-section {
154
+ flex: 1;
155
+ display: flex;
156
+ flex-direction: column;
157
+ border-right: 1px solid var(--border);
158
+ }
159
+
160
+ .tabs {
161
+ display: flex;
162
+ background-color: var(--bg-dark);
163
+ border-bottom: 1px solid var(--border);
164
+ }
165
+
166
+ .tab {
167
+ padding: 12px 20px;
168
+ cursor: pointer;
169
+ border-right: 1px solid var(--border);
170
+ color: var(--text-muted);
171
+ font-size: 0.9rem;
172
+ }
173
+
174
+ .tab.active {
175
+ background-color: var(--bg-panel);
176
+ color: var(--primary);
177
+ border-top: 2px solid var(--primary);
178
+ }
179
+
180
+ .code-area {
181
+ flex: 1;
182
+ background-color: var(--code-bg);
183
+ display: flex;
184
+ flex-direction: column;
185
+ }
186
+
187
+ textarea#codeEditor {
188
+ flex: 1;
189
+ background-color: transparent;
190
+ color: #e0e0e0;
191
+ border: none;
192
+ resize: none;
193
+ padding: 20px;
194
+ font-family: 'Consolas', 'Monaco', monospace;
195
+ font-size: 14px;
196
+ line-height: 1.5;
197
+ outline: none;
198
+ }
199
+
200
+ /* --- AI Panel --- */
201
+ .ai-panel {
202
+ height: 40%;
203
+ border-top: 1px solid var(--border);
204
+ background-color: var(--bg-panel);
205
+ display: flex;
206
+ flex-direction: column;
207
+ }
208
+
209
+ .ai-input-container {
210
+ padding: 15px;
211
+ border-top: 1px solid var(--border);
212
+ background-color: var(--bg-dark);
213
+ }
214
+
215
+ .enhance-tools {
216
+ display: flex;
217
+ gap: 10px;
218
+ margin-bottom: 10px;
219
+ }
220
+
221
+ .enhance-btn {
222
+ font-size: 0.8rem;
223
+ padding: 4px 10px;
224
+ border-radius: 20px;
225
+ background: var(--bg-panel);
226
+ border: 1px solid var(--primary);
227
+ color: var(--primary);
228
+ }
229
+
230
+ .input-wrapper {
231
+ display: flex;
232
+ gap: 10px;
233
+ position: relative;
234
+ }
235
+
236
+ #aiInput {
237
+ flex: 1;
238
+ background-color: var(--bg-panel);
239
+ border: 1px solid var(--border);
240
+ color: white;
241
+ padding: 12px;
242
+ border-radius: 8px;
243
+ outline: none;
244
+ }
245
+
246
+ #aiInput:focus {
247
+ border-color: var(--primary);
248
+ }
249
+
250
+ .ai-output {
251
+ flex: 1;
252
+ padding: 15px;
253
+ overflow-y: auto;
254
+ font-family: 'Consolas', monospace;
255
+ font-size: 0.9rem;
256
+ color: var(--text-muted);
257
+ }
258
+
259
+ .ai-message {
260
+ margin-bottom: 15px;
261
+ padding: 10px;
262
+ border-radius: 6px;
263
+ background-color: rgba(255, 255, 255, 0.05);
264
+ border-left: 3px solid var(--primary);
265
+ }
266
+
267
+ /* --- Preview Pane --- */
268
+ .preview-section {
269
+ width: 40%;
270
+ display: flex;
271
+ flex-direction: column;
272
+ background-color: white;
273
+ }
274
+
275
+ .preview-header {
276
+ background-color: var(--bg-panel);
277
+ padding: 10px 15px;
278
+ border-bottom: 1px solid var(--border);
279
+ display: flex;
280
+ justify-content: space-between;
281
+ align-items: center;
282
+ }
283
+
284
+ iframe {
285
+ flex: 1;
286
+ border: none;
287
+ width: 100%;
288
+ height: 100%;
289
+ }
290
+
291
+ /* --- Modals --- */
292
+ .modal {
293
+ display: none;
294
+ position: fixed;
295
+ top: 0; left: 0; width: 100%; height: 100%;
296
+ background: rgba(0,0,0,0.8);
297
+ z-index: 100;
298
+ justify-content: center;
299
+ align-items: center;
300
+ }
301
+
302
+ .modal-content {
303
+ background: var(--bg-panel);
304
+ padding: 25px;
305
+ border-radius: 10px;
306
+ border: 1px solid var(--primary);
307
+ width: 500px;
308
+ max-width: 90%;
309
+ }
310
+
311
+ .modal h2 {
312
+ color: var(--primary);
313
+ margin-bottom: 20px;
314
+ }
315
+
316
+ .form-group {
317
+ margin-bottom: 15px;
318
+ }
319
+
320
+ .form-group label {
321
+ display: block;
322
+ margin-bottom: 5px;
323
+ color: var(--text-muted);
324
+ }
325
+
326
+ .form-group input, .form-group select {
327
+ width: 100%;
328
+ padding: 10px;
329
+ background: var(--bg-dark);
330
+ border: 1px solid var(--border);
331
+ color: white;
332
+ border-radius: 4px;
333
+ }
334
+
335
+ .color-picker-row {
336
+ display: flex;
337
+ gap: 15px;
338
+ align-items: center;
339
+ margin-bottom: 10px;
340
+ }
341
+
342
+ input[type="color"] {
343
+ width: 40px;
344
+ height: 40px;
345
+ border: none;
346
+ padding: 0;
347
+ background: none;
348
+ }
349
+
350
+ /* Loader */
351
+ .loader {
352
+ border: 3px solid rgba(255,255,255,0.1);
353
+ border-top: 3px solid var(--primary);
354
+ border-radius: 50%;
355
+ width: 20px;
356
+ height: 20px;
357
+ animation: spin 1s linear infinite;
358
+ display: none;
359
+ }
360
+
361
+ @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
362
+
363
+ </style>
364
+ </head>
365
+ <body>
366
+
367
+ <!-- Header -->
368
+ <header>
369
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="logo">
370
+ <i class="fas fa-microchip"></i> <span>AI Code Creator</span> <small style="font-size: 0.6em; color: #666;">Built with Anycoder</small>
371
+ </a>
372
+ <div class="header-controls">
373
+ <button onclick="openSettings()"><i class="fas fa-robot"></i> AI Config</button>
374
+ <button onclick="openThemeTool()"><i class="fas fa-palette"></i> Theme</button>
375
+ <button onclick="exportProject()"><i class="fas fa-download"></i> Export ZIP</button>
376
+ <button class="primary" onclick="runAI()"><i class="fas fa-magic"></i> Generate</button>
377
+ </div>
378
+ </header>
379
+
380
+ <!-- Main App -->
381
+ <div class="app-container">
382
+
383
+ <!-- Left Sidebar -->
384
+ <aside class="sidebar">
385
+ <div class="sidebar-header">
386
+ <i class="fas fa-project-diagram"></i> Project Files
387
+ </div>
388
+ <div class="file-list" id="fileList">
389
+ <!-- Generated by JS -->
390
+ </div>
391
+
392
+ <div class="sidebar-header" style="border-top: 1px solid var(--border); margin-top: auto;">
393
+ <i class="fas fa-history"></i> History
394
+ </div>
395
+ <div class="history-list" id="historyList">
396
+ <!-- Generated by JS -->
397
+ </div>
398
+ </aside>
399
+
400
+ <!-- Center Editor -->
401
+ <section class="editor-section">
402
+ <div class="tabs">
403
+ <div class="tab active" onclick="switchTab('index.html')">index.html</div>
404
+ <div class="tab" onclick="switchTab('style.css')">style.css</div>
405
+ <div class="tab" onclick="switchTab('script.js')">script.js</div>
406
+ <div class="tab" style="margin-left: auto; border-left: 1px solid var(--border);" onclick="saveToHistory()">
407
+ <i class="fas fa-save"></i> Save Snapshot
408
+ </div>
409
+ </div>
410
+
411
+ <div class="code-area">
412
+ <textarea id="codeEditor" spellcheck="false" oninput="updateFileContent()"></textarea>
413
+ </div>
414
+
415
+ <!-- AI Chat / Enhancer -->
416
+ <div class="ai-panel">
417
+ <div style="padding: 10px; background: var(--bg-dark); border-bottom: 1px solid var(--border); display: flex; justify-content: space-between;">
418
+ <span style="color: var(--primary); font-weight: bold;">AI Assistant</span>
419
+ <span id="modelStatus" style="font-size: 0.8rem; color: var(--text-muted);">Model: Mock (Ready)</span>
420
+ </div>
421
+ <div class="ai-output" id="aiOutput">
422
+ <div class="ai-message">System: Ready. Describe your web app, or use the enhancer tools below.</div>
423
+ </div>
424
+ <div class="ai-input-container">
425
+ <div class="enhance-tools">
426
+ <button class="enhance-btn" onclick="enhancePrompt('Fix Code', 'Fix syntax errors in the following code:')">Fix Code</button>
427
+ <button class="enhance-btn" onclick="enhancePrompt('Optimize', 'Optimize the CSS for better performance:')">Optimize</button>
428
+ <button class="enhance-btn" onclick="enhancePrompt('Add Feature', 'Add a responsive navigation bar:')">Add Feature</button>
429
+ </div>
430
+ <div class="input-wrapper">
431
+ <input type="text" id="aiInput" placeholder="Ask AI to generate or edit code..." autocomplete="off">
432
+ <div class="loader" id="aiLoader"></div>
433
+ <button class="primary" style="padding: 8px 15px;" onclick="runAI()"><i class="fas fa-paper-plane"></i></button>
434
+ </div>
435
+ </div>
436
+ </div>
437
+ </section>
438
+
439
+ <!-- Right Preview -->
440
+ <section class="preview-section">
441
+ <div class="preview-header">
442
+ <span style="color: #333; font-weight: bold;">Live Preview</span>
443
+ <div style="display: flex; gap: 5px;">
444
+ <i class="fas fa-mobile-alt" style="color: #666; cursor: pointer;" onclick="setDevice('mobile')"></i>
445
+ <i class="fas fa-desktop" style="color: #000; cursor: pointer;" onclick="setDevice('desktop')"></i>
446
+ </div>
447
+ </div>
448
+ <iframe id="previewFrame" title="Live Preview"></iframe>
449
+ </section>
450
+ </div>
451
+
452
+ <!-- Settings Modal -->
453
+ <div id="settingsModal" class="modal">
454
+ <div class="modal-content">
455
+ <h2>AI Configuration</h2>
456
+ <div class="form-group">
457
+ <label>Select Model Provider</label>
458
+ <select id="aiProvider">
459
+ <option value="mock">Mock AI (Demo Mode)</option>
460
+ <option value="openai">OpenAI Compatible (Qwen/DeepSeek)</option>
461
+ <option value="huggingface">HuggingFace Inference</option>
462
+ </select>
463
+ </div>
464
+ <div class="form-group">
465
+ <label>API Endpoint / URL</label>
466
+ <input type="text" id="apiEndpoint" placeholder="https://api.openai.com/v1/...">
467
+ </div>
468
+ <div class="form-group">
469
+ <label>API Key</label>
470
+ <input type="password" id="apiKey" placeholder="sk-...">
471
+ </div>
472
+ <div style="display: flex; justify-content: flex-end; gap: 10px;">
473
+ <button onclick="closeModal('settingsModal')">Cancel</button>
474
+ <button class="primary" onclick="saveSettings()">Save Config</button>
475
+ </div>
476
+ </div>
477
+ </div>
478
+
479
+ <!-- Theme Modal -->
480
+ <div id="themeModal" class="modal">
481
+ <div class="modal-content">
482
+ <h2>Theme Customizer</h2>
483
+ <div class="color-picker-row">
484
+ <label>Primary (Yellow):</label>
485
+ <input type="color" id="themePrimary" value="#FFD700">
486
+ </div>
487
+ <div class="color-picker-row">
488
+ <label>Background:</label>
489
+ <input type="color" id="themeBg" value="#0f0f0f">
490
+ </div>
491
+ <div class="color-picker-row">
492
+ <label>Text Color:</label>
493
+ <input type="color" id="themeText" value="#ffffff">
494
+ </div>
495
+ <div style="display: flex; justify-content: flex-end; gap: 10px;">
496
+ <button onclick="resetTheme()">Reset Default</button>
497
+ <button class="primary" onclick="applyTheme()">Apply Theme</button>
498
+ </div>
499
+ </div>
500
+ </div>
501
+
502
+ <script>
503
+ // --- State Management ---
504
+ const state = {
505
+ files: {
506
+ 'index.html': '<!DOCTYPE html>\n<html>\n<head>\n <title>My App</title>\n <link rel="stylesheet" href="style.css">\n</head>\n<body>\n <div class="container">\n <h1>Hello AI Creator!</h1>\n <p>Start coding or ask the AI to build something.</p>\n <button id="btn">Click Me</button>\n </div>\n <script src="script.js"><\/script>\n</body>\n</html>',
507
+ 'style.css': 'body {\n background: #111;\n color: #fff;\n font-family: sans-serif;\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100vh;\n margin: 0;\n}\n\n.container {\n text-align: center;\n border: 2px solid #FFD700;\n padding: 40px;\n border-radius: 10px;\n}\n\nbutton {\n background: #FFD700;\n color: #000;\n border: none;\n padding: 10px 20px;\n font-size: 1.2rem;\n cursor: pointer;\n margin-top: 20px;\n border-radius: 5px;\n}',
508
+ 'script.js': 'document.getElementById("btn").addEventListener("click", () => {\n alert("Button Clicked!");\n});'
509
+ },
510
+ activeFile: 'index.html',
511
+ history: [],
512
+ config: {
513
+ provider: 'mock',
514
+ endpoint: '',
515
+ key: ''
516
+ }
517
+ };
518
+
519
+ // --- Initialization ---
520
+ document.addEventListener('DOMContentLoaded', () => {
521
+ renderFileList();
522
+ loadEditor();
523
+ renderPreview();
524
+ loadHistory();
525
+
526
+ // Enter key for AI Input
527
+ document.getElementById('aiInput').addEventListener('keypress', function (e) {
528
+ if (e.key === 'Enter') {
529
+ runAI();
530
+ }
531
+ });
532
+ });
533
+
534
+ // --- Core Editor Functions ---
535
+ function switchTab(filename) {
536
+ state.activeFile = filename;
537
+
538
+ // Update UI
539
+ document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
540
+ // Find the tab element by text content (simple way) or index logic
541
+ // In a real app, assign IDs to tabs. Here we just reload editor content.
542
+
543
+ // Highlight active tab logic (simplified)
544
+ const tabs = document.querySelectorAll('.tab');
545
+ if(filename === 'index.html') tabs[0].classList.add('active');
546
+ if(filename === 'style.css') tabs[1].classList.add('active');
547
+ if(filename === 'script.js') tabs[2].classList.add('active');
548
+
549
+ loadEditor();
550
+ }
551
+
552
+ function loadEditor() {
553
+ const editor = document.getElementById('codeEditor');
554
+ editor.value = state.files[state.activeFile];
555
+ }
556
+
557
+ function updateFileContent() {
558
+ state.files[state.activeFile] = document.getElementById('codeEditor').value;
559
+ renderPreview();
560
+ }
561
+
562
+ function renderFileList() {
563
+ const list = document.getElementById('fileList');
564
+ list.innerHTML = '';
565
+ Object.keys(state.files).forEach(filename => {
566
+ const div = document.createElement('div');
567
+ div.className = `file-item ${filename === state.activeFile ? 'active' : ''}`;
568
+ div.innerHTML = `<i class="fas ${getFileIcon(filename)}"></i> ${filename}`;
569
+ div.onclick = () => switchTab(filename);
570
+ list.appendChild(div);
571
+ });
572
+ }
573
+
574
+ function getFileIcon(filename) {
575
+ if(filename.endsWith('.html')) return 'fa-html5 text-orange-500';
576
+ if(filename.endsWith('.css')) return 'fa-css3-alt text-blue-500';
577
+ if(filename.endsWith('.js')) return 'fa-js text-yellow-500';
578
+ return 'fa-file-code';
579
+ }
580
+
581
+ // --- Preview System ---
582
+ function renderPreview() {
583
+ const iframe = document.getElementById('previewFrame');
584
+
585
+ // Inject CSS into HTML for preview
586
+ const css = state.files['style.css'] || '';
587
+ const html = state.files['index.html'] || '';
588
+
589
+ // Basic injection logic to ensure style.css applies even in blob/data URI scenarios if needed
590
+ // For iframe srcdoc, we can just put them together
591
+ const combinedHTML = `
592
+ <!DOCTYPE html>
593
+ <html>
594
+ <head>
595
+ <style>${css}</style>
596
+ </head>
597
+ <body>
598
+ ${html}
599
+ <script>${state.files['script.js'] || ''}<\/script>
600
+ </body>
601
+ </html>
602
+ `;
603
+
604
+ iframe.srcdoc = combinedHTML;
605
+ }
606
+
607
+ function setDevice(type) {
608
+ const iframe = document.getElementById('previewFrame');
609
+ if(type === 'mobile') {
610
+ iframe.style.width = '375px';
611
+ iframe.style.margin = '0 auto';
612
+ iframe.style.border = '1px solid #ccc';
613
+ } else {
614
+ iframe.style.width = '100%';
615
+ iframe.style.border = 'none';
616
+ iframe.style.margin = '0';
617
+ }
618
+ }
619
+
620
+ // --- AI Logic ---
621
+ function enhancePrompt(action, prefix) {
622
+ const input = document.getElementById('aiInput');
623
+ input.value = `${prefix} \n\nCurrent File (${state.activeFile}): \n${state.files[state.activeFile].substring(0, 100)}...`;
624
+
625
+ const output = document.getElementById('aiOutput');
626
+ output.innerHTML += `<div class="ai-message"><strong>System:</strong> Prompt enhanced for "${action}". Review input and press Generate.</div>`;
627
+ output.scrollTop = output.scrollHeight;
628
+ }
629
+
630
+ async function runAI() {
631
+ const input = document.getElementById('aiInput').value;
632
+ if(!input.trim()) return;
633
+
634
+ const loader = document.getElementById('aiLoader');
635
+ const output = document.getElementById('aiOutput');
636
+
637
+ loader.style.display = 'block';
638
+ output.innerHTML += `<div class="ai-message"><strong>User:</strong> ${input}</div>`;
639
+
640
+ try {
641
+ let aiResponse = "";
642
+
643
+ if (state.config.provider === 'mock') {
644
+ // Mock AI for Demo purposes
645
+ await new Promise(r => setTimeout(r, 1500)); // Fake delay
646
+ aiResponse = generateMockResponse(input);
647
+ } else {
648
+ // Real API Call (Conceptual Implementation)
649
+ aiResponse = await callRealAPI(input);
650
+ }
651
+
652
+ output.innerHTML += `<div class="ai-message"><strong>AI:</strong> ${aiResponse}</div>`;
653
+ processAIResult(aiResponse);
654
+
655
+ } catch (error) {
656
+ output.innerHTML += `<div class="ai-message" style="color:red"><strong>Error:</strong> ${error.message}</div>`;
657
+ } finally {
658
+ loader.style.display = 'none';
659
+ output.scrollTop = output.scrollHeight;
660
+ }
661
+ }
662
+
663
+ function generateMockResponse(prompt) {
664
+ // Heuristic responses for demo
665
+ if (prompt.toLowerCase().includes('html')) {
666
+ return "I've updated the HTML structure with a modern layout.";
667
+ }
668
+ if (prompt.toLowerCase().includes('css') || prompt.toLowerCase().includes('style')) {
669
+ return "I've refined the CSS. Added a gradient background and hover effects.";
670
+ }
671
+ if (prompt.toLowerCase().includes('fix') || prompt.toLowerCase().includes('error')) {
672
+ return "I detected a syntax error in the script tag. Fixed.";
673
+ }
674
+
675
+ return "Generated code structure based on your request. I've updated the 'index.html' file.";
676
+ }
677
+
678
+ async function callRealAPI(prompt) {
679
+ // Placeholder for fetch to Qwen/DeepSeek/HuggingFace
680
+ // In a real app, you'd construct the JSON body here based on state.config
681
+ const response = await fetch(state.config.endpoint || 'https://api.example.com/generate', {
682
+ method: 'POST',
683
+ headers: {
684
+ 'Authorization': `Bearer ${state.config.key}`,
685
+ 'Content-Type': 'application/json'
686
+ },
687
+ body: JSON.stringify({ prompt: prompt })
688
+ });
689
+
690
+ if(!response.ok) throw new Error('API Request Failed');
691
+ const data = await response.json();
692
+ return data.choices[0].message.content;
693
+ }
694
+
695
+ function processAIResult(responseText) {
696
+ // This is a very basic parser. In production, you'd want structured JSON from the AI.
697
+ // For this demo, we will detect keywords or just append to index.html for simple commands.
698
+
699
+ if (responseText.includes('```html')) {
700
+ const htmlMatch = responseText.match(/```html([\s\S]*?)```/);
701
+ if(htmlMatch) {
702
+ state.files['index.html'] = htmlMatch[1].trim();
703
+ switchTab('index.html');
704
+ }
705
+ } else if (responseText.includes('```css')) {
706
+ const cssMatch = responseText.match(/```css([\s\S]*?)```/);
707
+ if(cssMatch) {
708
+ state.files['style.css'] = cssMatch[1].trim();
709
+ switchTab('style.css');
710
+ }
711
+ } else {
712
+ // Default: append to current file for memory/chat context
713
+ const currentContent = state.files[state.activeFile];
714
+ state.files[state.activeFile] = currentContent + "\n<!-- AI Generated -->\n" + responseText;
715
+ }
716
+
717
+ loadEditor();
718
+ renderFileList();
719
+ renderPreview();
720
+ document.getElementById('aiInput').value = '';
721
+ }
722
+
723
+ // --- History & Saving ---
724
+ function saveToHistory() {
725
+ const snapshot = {
726
+ timestamp: new Date().toLocaleString(),
727
+ files: JSON.parse(JSON.stringify(state.files)),
728
+ prompt: document.getElementById('aiInput').value || "Manual Save"
729
+ };
730
+ state.history.unshift(snapshot);
731
+ if(state.history.length > 10) state.history.pop();
732
+ localStorage.setItem('ai_code_history', JSON.stringify(state.history));
733
+ renderHistory();
734
+ alert("Snapshot saved to History!");
735
+ }
736
+
737
+ function loadHistory() {
738
+ const stored = localStorage.getItem('ai_code_history');
739
+ if(stored) {
740
+ state.history = JSON.parse(stored);
741
+ renderHistory();
742
+ }
743
+ }
744
+
745
+ function renderHistory() {
746
+ const list = document.getElementById('historyList');
747
+ list.innerHTML = '';
748
+ state.history.forEach((item, index) => {
749
+ const div = document.createElement('div');
750
+ div.className = 'file-item';
751
+ div.innerHTML = `<i class="fas fa-history"></i> ${item.timestamp}`;
752
+ div.title = item.prompt;
753
+ div.onclick = () => restoreHistory(index);
754
+ list.appendChild(div);
755
+ });
756
+ }
757
+
758
+ function restoreHistory(index) {
759
+ if(confirm("Restore this snapshot? Current unsaved changes will be lost.")) {
760
+ state.files = JSON.parse(JSON.stringify(state.history[index].files));
761
+ loadEditor();
762
+ renderFileList();
763
+ renderPreview();
764
+ }
765
+ }
766
+
767
+ function exportProject() {
768
+ const zip = new JSZip();
769
+ for (const [filename, content] of Object.entries(state.files)) {
770
+ zip.file(filename, content);
771
+ }
772
+
773
+ zip.generateAsync({type:"blob"})
774
+ .then(function(content) {
775
+ saveAs(content, "ai-project.zip");
776
+ });
777
+ }
778
+
779
+ // --- Theme Tool ---
780
+ function openThemeTool() {
781
+ document.getElementById('themeModal').style.display = 'flex';
782
+ }
783
+
784
+ function applyTheme() {
785
+ const primary = document.getElementById('themePrimary').value;
786
+ const bg = document.getElementById('themeBg').value;
787
+ const text = document.getElementById('themeText').value;
788
+
789
+ const r = document.querySelector(':root');
790
+ r.style.setProperty('--primary', primary);
791
+ r.style.setProperty('--bg-dark', bg);
792
+ r.style.setProperty('--text-main', text);
793
+
794
+ closeModal('themeModal');
795
+ }
796
+
797
+ function resetTheme() {
798
+ document.getElementById('themePrimary').value = '#FFD700';
799
+ document.getElementById('themeBg').value = '#0f0f0f';
800
+ document.getElementById('themeText').value = '#ffffff';
801
+ applyTheme();
802
+ }
803
+
804
+ // --- Settings ---
805
+ function openSettings() {
806
+ document.getElementById('settingsModal').style.display = 'flex';
807
+ }
808
+
809
+ function saveSettings() {
810
+ state.config.provider = document.getElementById('aiProvider').value;
811
+ state.config.endpoint = document.getElementById('apiEndpoint').value;
812
+ state.config.key = document.getElementById('apiKey').value;
813
+
814
+ const status = document.getElementById('modelStatus');
815
+ status.innerText = `Model: ${state.config.provider.toUpperCase()} (Active)`;
816
+
817
+ closeModal('settingsModal');
818
+ }
819
+
820
+ function closeModal(id) {
821
+ document.getElementById(id).style.display = 'none';
822
+ }
823
+
824
+ // Close modals on outside click
825
+ window.onclick = function(event) {
826
+ if (event.target.classList.contains('modal')) {
827
+ event.target.style.display = "none";
828
+ }
829
+ }
830
+ </script>
831
+ </body>
832
+ </html>