Simonc-44 commited on
Commit
3ad6837
·
verified ·
1 Parent(s): ea96bdc

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +340 -17
index.html CHANGED
@@ -3,28 +3,338 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Cygnis Image Gen</title>
 
 
 
 
7
  <style>
8
- body { font-family: sans-serif; background: #111; color: white; display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; margin: 0; }
9
- input { padding: 10px; width: 300px; border-radius: 5px; border: none; }
10
- button { padding: 10px 20px; background: #8b5cf6; color: white; border: none; border-radius: 5px; cursor: pointer; margin-left: 10px; }
11
- button:disabled { background: #555; }
12
- #result { margin-top: 20px; max-width: 512px; }
13
- img { width: 100%; border-radius: 10px; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  </style>
15
  </head>
16
  <body>
17
- <h1>Cygnis Image Generator (DALL-E Mini)</h1>
18
- <div>
19
- <input type="text" id="prompt" placeholder="Un chat dans l'espace...">
20
- <button id="btn">Générer</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  </div>
22
- <div id="result"></div>
23
 
24
  <script>
25
- const btn = document.getElementById('btn');
 
 
26
  const prompt = document.getElementById('prompt');
27
- const result = document.getElementById('result');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
  btn.addEventListener('click', async () => {
30
  const text = prompt.value;
@@ -32,7 +342,9 @@
32
 
33
  btn.disabled = true;
34
  btn.textContent = "Génération...";
35
- result.innerHTML = '<p>Calcul en cours (peut prendre 1-2 min sur CPU)...</p>';
 
 
36
 
37
  try {
38
  const res = await fetch('/generate', {
@@ -44,9 +356,20 @@
44
  if (!res.ok) throw new Error("Erreur serveur");
45
  const data = await res.json();
46
 
47
- result.innerHTML = `<img src="${data.image_url}" alt="Image générée">`;
 
 
 
 
 
 
 
 
 
 
48
  } catch (e) {
49
- result.innerHTML = `<p style="color:red">Erreur: ${e.message}</p>`;
 
50
  } finally {
51
  btn.disabled = false;
52
  btn.textContent = "Générer";
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Cygnis Image Studio</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com">
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
10
+ <script src="https://unpkg.com/lucide@latest"></script>
11
  <style>
12
+ :root {
13
+ --bg-app: #1e1e1e;
14
+ --bg-panel: #252526;
15
+ --bg-canvas: #111111;
16
+ --border: #3e3e42;
17
+ --accent: #0f64d2;
18
+ --text: #cccccc;
19
+ --text-light: #ffffff;
20
+ --toolbar-width: 50px;
21
+ --panel-width: 300px;
22
+ }
23
+
24
+ * { margin: 0; padding: 0; box-sizing: border-box; }
25
+
26
+ body {
27
+ background-color: var(--bg-app);
28
+ color: var(--text);
29
+ font-family: 'Inter', sans-serif;
30
+ height: 100vh;
31
+ display: flex;
32
+ flex-direction: column;
33
+ overflow: hidden;
34
+ font-size: 12px;
35
+ user-select: none;
36
+ }
37
+
38
+ /* --- MENU BAR --- */
39
+ .menubar {
40
+ height: 30px;
41
+ background-color: #2d2d2d;
42
+ display: flex;
43
+ align-items: center;
44
+ padding: 0 10px;
45
+ border-bottom: 1px solid #000;
46
+ }
47
+
48
+ .menu-item { padding: 0 10px; cursor: pointer; }
49
+ .menu-item:hover { background: #3e3e42; color: white; }
50
+
51
+ /* --- MAIN LAYOUT --- */
52
+ .workspace {
53
+ display: flex;
54
+ flex: 1;
55
+ overflow: hidden;
56
+ }
57
+
58
+ /* --- TOOLBAR (LEFT) --- */
59
+ .toolbar {
60
+ width: var(--toolbar-width);
61
+ background-color: var(--bg-panel);
62
+ border-right: 1px solid #000;
63
+ display: flex;
64
+ flex-direction: column;
65
+ align-items: center;
66
+ padding-top: 10px;
67
+ gap: 5px;
68
+ }
69
+
70
+ .tool-btn {
71
+ width: 36px; height: 36px;
72
+ display: flex; align-items: center; justify-content: center;
73
+ border-radius: 3px;
74
+ cursor: pointer;
75
+ color: #a0a0a0;
76
+ transition: all 0.1s;
77
+ }
78
+
79
+ .tool-btn:hover { background: #3e3e42; color: white; }
80
+ .tool-btn.active { background: #3e3e42; color: var(--accent); border-left: 2px solid var(--accent); }
81
+
82
+ /* --- CENTER AREA (CANVAS + GALLERY) --- */
83
+ .center-area {
84
+ flex: 1;
85
+ display: flex;
86
+ flex-direction: column;
87
+ background-color: var(--bg-canvas);
88
+ }
89
+
90
+ .canvas-area {
91
+ flex: 1;
92
+ display: flex;
93
+ align-items: center;
94
+ justify-content: center;
95
+ position: relative;
96
+ overflow: hidden;
97
+ border-bottom: 1px solid #000;
98
+ }
99
+
100
+ .canvas-wrapper {
101
+ width: 512px; height: 512px;
102
+ background-color: white;
103
+ box-shadow: 0 0 20px rgba(0,0,0,0.5);
104
+ background-image:
105
+ linear-gradient(45deg, #ccc 25%, transparent 25%),
106
+ linear-gradient(-45deg, #ccc 25%, transparent 25%),
107
+ linear-gradient(45deg, transparent 75%, #ccc 75%),
108
+ linear-gradient(-45deg, transparent 75%, #ccc 75%);
109
+ background-size: 20px 20px;
110
+ background-position: 0 0, 0 10px, 10px -10px, -10px 0px;
111
+ display: flex; align-items: center; justify-content: center;
112
+ }
113
+
114
+ .generated-image {
115
+ width: 100%; height: 100%;
116
+ object-fit: contain;
117
+ display: none;
118
+ }
119
+
120
+ /* --- GALLERY PANEL (BOTTOM) --- */
121
+ .gallery-panel {
122
+ height: 150px;
123
+ background-color: var(--bg-panel);
124
+ display: flex;
125
+ flex-direction: column;
126
+ }
127
+
128
+ .gallery-content {
129
+ flex: 1;
130
+ padding: 10px;
131
+ display: flex;
132
+ gap: 10px;
133
+ overflow-x: auto;
134
+ }
135
+
136
+ .gallery-item {
137
+ width: 100px; height: 100px;
138
+ background: #333;
139
+ border: 1px solid #444;
140
+ cursor: pointer;
141
+ position: relative;
142
+ }
143
+ .gallery-item:hover { border-color: var(--accent); }
144
+ .gallery-item img { width: 100%; height: 100%; object-fit: cover; }
145
+
146
+ /* --- PROPERTIES PANEL (RIGHT) --- */
147
+ .properties {
148
+ width: var(--panel-width);
149
+ background-color: var(--bg-panel);
150
+ border-left: 1px solid #000;
151
+ display: flex;
152
+ flex-direction: column;
153
+ }
154
+
155
+ .panel-header {
156
+ padding: 8px 12px;
157
+ background: #333;
158
+ font-weight: 600;
159
+ border-bottom: 1px solid #000;
160
+ border-top: 1px solid #444;
161
+ color: #eee;
162
+ font-size: 11px;
163
+ text-transform: uppercase;
164
+ letter-spacing: 0.5px;
165
+ }
166
+
167
+ .panel-content {
168
+ padding: 15px;
169
+ display: flex;
170
+ flex-direction: column;
171
+ gap: 15px;
172
+ }
173
+
174
+ .control-group {
175
+ display: flex; flex-direction: column; gap: 6px;
176
+ }
177
+
178
+ label { color: #ccc; font-size: 11px; font-weight: 600; }
179
+
180
+ textarea {
181
+ background: #181818;
182
+ border: 1px solid #444;
183
+ color: white;
184
+ padding: 8px;
185
+ border-radius: 2px;
186
+ resize: none;
187
+ height: 100px;
188
+ font-family: inherit;
189
+ font-size: 12px;
190
+ }
191
+ textarea:focus { border-color: var(--accent); outline: none; }
192
+
193
+ .btn-primary {
194
+ background: var(--accent);
195
+ color: white;
196
+ border: none;
197
+ padding: 8px;
198
+ border-radius: 2px;
199
+ font-weight: 600;
200
+ cursor: pointer;
201
+ transition: background 0.2s;
202
+ }
203
+ .btn-primary:hover { background: #1473e6; }
204
+ .btn-primary:disabled { background: #444; color: #888; cursor: not-allowed; }
205
+
206
+ /* --- LOADER --- */
207
+ .loader {
208
+ width: 40px; height: 40px;
209
+ border: 3px solid rgba(255,255,255,0.1);
210
+ border-top-color: var(--accent);
211
+ border-radius: 50%;
212
+ animation: spin 1s linear infinite;
213
+ display: none;
214
+ }
215
+ @keyframes spin { to { transform: rotate(360deg); } }
216
+
217
+ .status-bar {
218
+ height: 24px;
219
+ background: #2d2d2d;
220
+ border-top: 1px solid #000;
221
+ display: flex; align-items: center;
222
+ padding: 0 10px;
223
+ font-size: 11px;
224
+ color: #aaa;
225
+ justify-content: space-between;
226
+ }
227
+
228
  </style>
229
  </head>
230
  <body>
231
+
232
+ <!-- MENU BAR -->
233
+ <div class="menubar">
234
+ <div class="menu-item" style="font-weight:700; color:#0f64d2;">Ps</div>
235
+ <div class="menu-item">Fichier</div>
236
+ <div class="menu-item">Édition</div>
237
+ <div class="menu-item">Image</div>
238
+ <div class="menu-item">Calque</div>
239
+ <div class="menu-item">Sélection</div>
240
+ <div class="menu-item">Filtre</div>
241
+ <div class="menu-item">Affichage</div>
242
+ <div class="menu-item">Fenêtre</div>
243
+ <div class="menu-item">Aide</div>
244
+ </div>
245
+
246
+ <div class="workspace">
247
+ <!-- TOOLBAR -->
248
+ <div class="toolbar">
249
+ <div class="tool-btn active"><i data-lucide="move"></i></div>
250
+ <div class="tool-btn"><i data-lucide="crop"></i></div>
251
+ <div class="tool-btn"><i data-lucide="lasso"></i></div>
252
+ <div class="tool-btn"><i data-lucide="brush"></i></div>
253
+ <div class="tool-btn"><i data-lucide="eraser"></i></div>
254
+ <div class="tool-btn"><i data-lucide="type"></i></div>
255
+ <div class="tool-btn"><i data-lucide="paint-bucket"></i></div>
256
+ <div class="tool-btn"><i data-lucide="zoom-in"></i></div>
257
+ <div style="flex:1"></div>
258
+ <div class="tool-btn"><i data-lucide="palette"></i></div>
259
+ </div>
260
+
261
+ <!-- CENTER AREA -->
262
+ <div class="center-area">
263
+ <div class="canvas-area">
264
+ <div class="canvas-wrapper">
265
+ <div class="loader" id="loader"></div>
266
+ <img id="result-img" class="generated-image" alt="Résultat">
267
+ </div>
268
+ </div>
269
+
270
+ <div class="gallery-panel">
271
+ <div class="panel-header">Bibliothèque / Historique</div>
272
+ <div class="gallery-content" id="gallery">
273
+ <!-- Images will be added here -->
274
+ </div>
275
+ </div>
276
+ </div>
277
+
278
+ <!-- PROPERTIES -->
279
+ <div class="properties">
280
+ <div class="panel-header">Propriétés</div>
281
+ <div class="panel-content">
282
+ <div class="control-group">
283
+ <label>PROMPT (DESCRIPTION)</label>
284
+ <textarea id="prompt" placeholder="Décrivez l'image à générer..."></textarea>
285
+ </div>
286
+
287
+ <div class="control-group">
288
+ <label>MODÈLE</label>
289
+ <select style="background:#181818; border:1px solid #444; color:white; padding:5px;">
290
+ <option>Stable Diffusion XL (Cloud)</option>
291
+ </select>
292
+ </div>
293
+
294
+ <button id="generate-btn" class="btn-primary">Générer</button>
295
+ </div>
296
+
297
+ <div class="panel-header" style="margin-top:auto;">Calques</div>
298
+ <div class="layers-panel" style="flex:1; padding:10px;">
299
+ <div style="display:flex; align-items:center; gap:10px; padding:5px; background:#3e3e42;">
300
+ <div style="width:30px; height:30px; background:white; border:1px solid #000;"></div>
301
+ <div style="color:white; font-weight:500;">Arrière-plan</div>
302
+ <i data-lucide="eye" size="14" style="margin-left:auto; color:#ccc;"></i>
303
+ </div>
304
+ </div>
305
+ </div>
306
+ </div>
307
+
308
+ <div class="status-bar">
309
+ <span id="status-text">Prêt</span>
310
+ <span>100%</span>
311
  </div>
 
312
 
313
  <script>
314
+ lucide.createIcons();
315
+
316
+ const btn = document.getElementById('generate-btn');
317
  const prompt = document.getElementById('prompt');
318
+ const img = document.getElementById('result-img');
319
+ const loader = document.getElementById('loader');
320
+ const status = document.getElementById('status-text');
321
+ const gallery = document.getElementById('gallery');
322
+
323
+ // Load gallery from local storage
324
+ const savedImages = JSON.parse(localStorage.getItem('cygnis_images') || '[]');
325
+ savedImages.forEach(url => addToGallery(url));
326
+
327
+ function addToGallery(url) {
328
+ const div = document.createElement('div');
329
+ div.className = 'gallery-item';
330
+ div.innerHTML = `<img src="${url}" onclick="showImage('${url}')">`;
331
+ gallery.prepend(div);
332
+ }
333
+
334
+ window.showImage = (url) => {
335
+ img.src = url;
336
+ img.style.display = 'block';
337
+ };
338
 
339
  btn.addEventListener('click', async () => {
340
  const text = prompt.value;
 
342
 
343
  btn.disabled = true;
344
  btn.textContent = "Génération...";
345
+ loader.style.display = 'block';
346
+ img.style.display = 'none';
347
+ status.textContent = "Calcul en cours (SDXL)...";
348
 
349
  try {
350
  const res = await fetch('/generate', {
 
356
  if (!res.ok) throw new Error("Erreur serveur");
357
  const data = await res.json();
358
 
359
+ img.src = data.image_url;
360
+ img.onload = () => {
361
+ loader.style.display = 'none';
362
+ img.style.display = 'block';
363
+ status.textContent = "Terminé.";
364
+
365
+ // Save to gallery
366
+ addToGallery(data.image_url);
367
+ savedImages.unshift(data.image_url);
368
+ localStorage.setItem('cygnis_images', JSON.stringify(savedImages));
369
+ };
370
  } catch (e) {
371
+ status.textContent = "Erreur : " + e.message;
372
+ loader.style.display = 'none';
373
  } finally {
374
  btn.disabled = false;
375
  btn.textContent = "Générer";