Mahmoudmody777 commited on
Commit
078d61b
1 Parent(s): 6beb1a6

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +554 -19
index.html CHANGED
@@ -1,19 +1,554 @@
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>Image generator</title>
7
+ <style>
8
+ body {
9
+ font-family: Arial, sans-serif;
10
+ margin: 0;
11
+ padding: 0;
12
+ background-color: #f9f9f9;
13
+ display: flex;
14
+ flex-direction: column;
15
+ height: 100vh;
16
+ overflow: hidden;
17
+ }
18
+
19
+ .header {
20
+ background-color: #007bff;
21
+ color: white;
22
+ padding: 15px;
23
+ text-align: center;
24
+ font-size: 24px;
25
+ position: sticky;
26
+ top: 0;
27
+ z-index: 2;
28
+ display: flex;
29
+ align-items: center;
30
+ justify-content: center;
31
+ }
32
+
33
+ .header img {
34
+ max-height: 50px; /* ضبط ارتفاع الشعار */
35
+ margin-right: 10px; /* مسافة بين الشعار والعنوان */
36
+ cursor: pointer; /* تغيير المؤشر عند المرور */
37
+ }
38
+
39
+ .header img:hover + .tooltip {
40
+ display: block; /* إظهار الكلمة عند المرور */
41
+ }
42
+
43
+ .tooltip {
44
+ display: none;
45
+ position: absolute;
46
+ color: white;
47
+ background-color: rgba(0, 0, 0, 0.7);
48
+ padding: 5px;
49
+ border-radius: 5px;
50
+ font-size: 14px;
51
+ margin-left: -30px; /* ضبط الموقع */
52
+ margin-top: -30px; /* ضبط الموقع */
53
+ }
54
+
55
+ .container {
56
+ display: flex;
57
+ flex-direction: column;
58
+ align-items: center;
59
+ flex: 1;
60
+ overflow-y: auto;
61
+ }
62
+
63
+ .api-info {
64
+ margin: 20px;
65
+ text-align: center;
66
+ font-size: 16px;
67
+ color: #333;
68
+ }
69
+
70
+ .api-info a {
71
+ color: #007bff;
72
+ text-decoration: none;
73
+ }
74
+
75
+ .api-info a:hover {
76
+ text-decoration: underline;
77
+ }
78
+
79
+ .controls {
80
+ width: 80%;
81
+ margin: 20px auto;
82
+ display: flex;
83
+ flex-direction: column;
84
+ align-items: stretch;
85
+ }
86
+
87
+ .controls label {
88
+ margin-bottom: 5px;
89
+ font-size: 14px;
90
+ color: #333;
91
+ }
92
+
93
+ .controls input[type="password"],
94
+ .controls input[type="text"],
95
+ .controls textarea {
96
+ width: 100%;
97
+ padding: 10px;
98
+ margin-bottom: 10px;
99
+ border: 1px solid #ccc;
100
+ border-radius: 5px;
101
+ font-size: 14px;
102
+ box-sizing: border-box;
103
+ transition: border-color 0.3s;
104
+ }
105
+
106
+ .controls input[type="password"]:focus,
107
+ .controls input[type="text"]:focus,
108
+ .controls textarea:focus {
109
+ border-color: #007bff;
110
+ }
111
+
112
+ .controls button {
113
+ padding: 10px;
114
+ background-color: #007bff;
115
+ color: white;
116
+ border: none;
117
+ border-radius: 5px;
118
+ cursor: pointer;
119
+ font-size: 16px;
120
+ transition: background-color 0.3s;
121
+ }
122
+
123
+ .controls button:hover {
124
+ background-color: #0056b3;
125
+ }
126
+
127
+ .sliders {
128
+ display: flex;
129
+ flex-direction: column;
130
+ margin: 10px 0;
131
+ }
132
+
133
+ .slider-container {
134
+ display: flex;
135
+ align-items: center;
136
+ margin-bottom: 15px;
137
+ flex-wrap: nowrap;
138
+ }
139
+
140
+ .slider-container label {
141
+ margin-right: 10px;
142
+ font-size: 14px;
143
+ color: #333;
144
+ width: 100px;
145
+ }
146
+
147
+ .slider-value {
148
+ width: 40px; /* تصغير عرض خانة القياس */
149
+ text-align: center;
150
+ font-size: 14px;
151
+ margin-left: 10px;
152
+ }
153
+
154
+ .output {
155
+ width: 80%;
156
+ display: grid;
157
+ grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
158
+ gap: 20px;
159
+ margin: 20px auto;
160
+ }
161
+
162
+ .output img {
163
+ width: 100%;
164
+ height: auto;
165
+ border-radius: 10px;
166
+ cursor: pointer;
167
+ max-height: 620px;
168
+ object-fit: contain;
169
+ transition: transform 0.3s;
170
+ }
171
+
172
+ .output img:hover {
173
+ transform: scale(1.05);
174
+ }
175
+
176
+ .image-container {
177
+ position: relative;
178
+ }
179
+
180
+ .delete-button {
181
+ position: absolute;
182
+ top: 10px;
183
+ right: 10px;
184
+ background-color: red;
185
+ color: white;
186
+ border: none;
187
+ border-radius: 5px;
188
+ cursor: pointer;
189
+ padding: 5px 10px;
190
+ font-size: 12px;
191
+ display: none;
192
+ }
193
+
194
+ .image-container:hover .delete-button {
195
+ display: block;
196
+ }
197
+
198
+ #status {
199
+ text-align: center;
200
+ color: #333;
201
+ margin-top: 10px;
202
+ font-size: 14px;
203
+ }
204
+
205
+ .modal {
206
+ display: none;
207
+ position: fixed;
208
+ z-index: 1000;
209
+ left: 0;
210
+ top: 0;
211
+ width: 100%;
212
+ height: 100%;
213
+ overflow: auto;
214
+ background-color: rgba(0, 0, 0, 0.8);
215
+ justify-content: center;
216
+ align-items: center;
217
+ padding: 20px;
218
+ }
219
+
220
+ .modal-content {
221
+ background-color: white;
222
+ padding: 50px;
223
+ border-radius: 10px;
224
+ max-width: 800px;
225
+ width: 100%;
226
+ display: flex;
227
+ flex-direction: row;
228
+ align-items: center;
229
+ }
230
+
231
+ .modal img {
232
+ max-width: 50%;
233
+ height: auto;
234
+ border-radius: 10px;
235
+ margin-right: 20px;
236
+ object-fit: contain;
237
+ }
238
+
239
+ .prompt-info {
240
+ margin-top: 0px;
241
+ font-size: 14px;
242
+ max-width: 300px;
243
+ }
244
+
245
+ .copy-prompt {
246
+ background-color: #007bff;
247
+ color: white;
248
+ border: none;
249
+ border-radius: 5px;
250
+ cursor: pointer;
251
+ padding: 5px 10px;
252
+ margin-top: 10px;
253
+ }
254
+
255
+ .copy-prompt:hover {
256
+ background-color: #0056b3;
257
+ }
258
+
259
+ @media (max-width: 600px) {
260
+ .slider-container label {
261
+ width: auto;
262
+ }
263
+
264
+ .slider-container {
265
+ flex-direction: column;
266
+ align-items: stretch;
267
+ }
268
+
269
+ .slider-value {
270
+ margin-left: 0;
271
+ margin-top: 5px;
272
+ }
273
+
274
+ .modal img {
275
+ max-width: 100%;
276
+ }
277
+ }
278
+
279
+ input[type="range"] {
280
+ width: 100%; /* تكبير شريط التمرير */
281
+ }
282
+
283
+ .toggle-button {
284
+ background-color: #007bff;
285
+ color: white;
286
+ border: none;
287
+ border-radius: 5px;
288
+ cursor: pointer;
289
+ padding: 5px 10px;
290
+ margin-left: 10px;
291
+ font-size: 14px;
292
+ }
293
+
294
+ .toggle-button:hover {
295
+ background-color: #0056b3;
296
+ }
297
+ </style>
298
+ </head>
299
+ <body>
300
+
301
+ <div class="header">
302
+ <img src="palestine.png" alt="Logo" id="logo"> <!-- استبدل your-logo-url.png برابط الشعار الخاص بك -->
303
+ <span class="tooltip">Free Palestine</span>
304
+ Pray for Palestine
305
+ </div>
306
+
307
+ <div class="api-info">
308
+ <p>Get the API key and 50 free credits to generate images and purchase from here<a href="https://api.bfl.ml/auth/login#" target="_blank">BFL API Portal</a>.</p> <!-- استبدل your-api-url.com برابط الموقع الخاص بك -->
309
+ </div>
310
+
311
+ <div class="container">
312
+ <div class="controls">
313
+ <label for="api-key">API Key:</label>
314
+ <div style="display: flex; align-items: center;">
315
+ <input type="password" id="api-key" placeholder="Enter your API Key">
316
+ <button class="toggle-button" id="toggle-api-key">Show</button>
317
+ </div>
318
+
319
+ <label for="prompt">Image Description:</label>
320
+ <textarea id="prompt" placeholder="Describe the image you want to generate" rows="4" maxlength="184"></textarea>
321
+
322
+ <div class="sliders">
323
+ <div class="slider-container">
324
+ <label for="width">Width:</label>
325
+ <input type="range" id="width" min="512" max="1440" step="64" value="1024">
326
+ <input class="slider-value" type="text" id="width-value" value="1024" readonly>
327
+ </div>
328
+
329
+ <div class="slider-container">
330
+ <label for="height">Height:</label>
331
+ <input type="range" id="height" min="512" max="1440" step="64" value="768">
332
+ <input class="slider-value" type="text" id="height-value" value="768" readonly>
333
+ </div>
334
+
335
+ <div class="slider-container">
336
+ <label for="steps">Steps:</label>
337
+ <input type="range" id="steps" min="1" max="100" step="1" value="8">
338
+ <input class="slider-value" type="text" id="steps-value" value="8" readonly>
339
+ </div>
340
+ </div>
341
+
342
+ <button id="generate-btn">Generate Image</button>
343
+ <p id="status"></p>
344
+ </div>
345
+
346
+ <div class="output" id="output-container"></div>
347
+ </div>
348
+
349
+ <div class="modal" id="modal">
350
+ <div class="modal-content">
351
+ <img id="modal-image" alt="Enlarged Image">
352
+ <div>
353
+ <div class="prompt-info" id="prompt-info"></div>
354
+ <div class="settings-info" id="settings-info"></div>
355
+ <button id="copy-prompt" class="copy-prompt">Copy Prompt</button>
356
+ </div>
357
+ </div>
358
+ </div>
359
+
360
+ <script>
361
+ const generateBtn = document.getElementById('generate-btn');
362
+ const promptInput = document.getElementById('prompt');
363
+ const apiKeyInput = document.getElementById('api-key');
364
+ const widthSlider = document.getElementById('width');
365
+ const heightSlider = document.getElementById('height');
366
+ const stepsSlider = document.getElementById('steps');
367
+ const widthValue = document.getElementById('width-value');
368
+ const heightValue = document.getElementById('height-value');
369
+ const stepsValue = document.getElementById('steps-value');
370
+ const statusElement = document.getElementById('status');
371
+ const outputContainer = document.getElementById('output-container');
372
+ const modal = document.getElementById('modal');
373
+ const modalImage = document.getElementById('modal-image');
374
+ const promptInfo = document.getElementById('prompt-info');
375
+ const settingsInfo = document.getElementById('settings-info');
376
+ const copyPromptBtn = document.getElementById('copy-prompt');
377
+ const toggleApiKeyBtn = document.getElementById('toggle-api-key');
378
+
379
+ let isApiKeyVisible = false;
380
+
381
+ window.onload = () => {
382
+ const savedPrompt = localStorage.getItem('lastPrompt');
383
+ const savedApiKey = localStorage.getItem('apiKey');
384
+ if (savedPrompt) {
385
+ promptInput.value = savedPrompt;
386
+ }
387
+ if (savedApiKey) {
388
+ apiKeyInput.value = savedApiKey;
389
+ }
390
+
391
+ loadImagesFromStorage();
392
+ };
393
+
394
+ function loadImagesFromStorage() {
395
+ const savedImages = JSON.parse(localStorage.getItem('images')) || [];
396
+ savedImages.forEach(imgObj => addImageToOutput(imgObj.url, imgObj.prompt, imgObj.width, imgObj.height, imgObj.steps));
397
+ }
398
+
399
+ widthSlider.addEventListener('input', () => {
400
+ widthValue.value = widthSlider.value;
401
+ localStorage.setItem('lastWidth', widthSlider.value);
402
+ });
403
+
404
+ heightSlider.addEventListener('input', () => {
405
+ heightValue.value = heightSlider.value;
406
+ localStorage.setItem('lastHeight', heightSlider.value);
407
+ });
408
+
409
+ stepsSlider.addEventListener('input', () => {
410
+ stepsValue.value = stepsSlider.value;
411
+ localStorage.setItem('lastSteps', stepsSlider.value);
412
+ });
413
+
414
+ generateBtn.addEventListener('click', async () => {
415
+ const prompt = promptInput.value;
416
+ const apiKey = apiKeyInput.value;
417
+ const width = widthSlider.value;
418
+ const height = heightSlider.value;
419
+ const steps = stepsSlider.value;
420
+
421
+ // تحقق من عدد الحروف
422
+ if (prompt.length > 184) {
423
+ alert('The prompt cannot exceed 184 characters.');
424
+ return;
425
+ }
426
+
427
+ if (!prompt || !apiKey) {
428
+ alert('Please enter both a prompt and API key!');
429
+ return;
430
+ }
431
+
432
+ localStorage.setItem('lastPrompt', prompt);
433
+ localStorage.setItem('apiKey', apiKey);
434
+
435
+ statusElement.textContent = 'Generating image...';
436
+
437
+ try {
438
+ const requestId = await sendImageGenerationRequest(prompt, width, height, steps, apiKey);
439
+ const imageUrl = await pollResult(requestId, apiKey);
440
+ addImageToOutput(imageUrl, prompt, width, height, steps);
441
+ statusElement.textContent = 'Image generated successfully!';
442
+ } catch (error) {
443
+ statusElement.textContent = `Error: ${error.message}`;
444
+ }
445
+ });
446
+
447
+ toggleApiKeyBtn.addEventListener('click', () => {
448
+ isApiKeyVisible = !isApiKeyVisible;
449
+ apiKeyInput.type = isApiKeyVisible ? 'text' : 'password';
450
+ toggleApiKeyBtn.textContent = isApiKeyVisible ? 'Hide' : 'Show';
451
+ });
452
+
453
+ function addImageToOutput(imageUrl, prompt, width, height, steps) {
454
+ const container = document.createElement('div');
455
+ container.className = 'image-container';
456
+
457
+ const img = document.createElement('img');
458
+ img.src = imageUrl;
459
+ img.alt = "Generated Image";
460
+ img.onclick = () => openModal(imageUrl, prompt, width, height, steps);
461
+
462
+ const deleteButton = document.createElement('button');
463
+ deleteButton.className = 'delete-button';
464
+ deleteButton.innerText = 'Delete';
465
+ deleteButton.onclick = (e) => {
466
+ e.stopPropagation();
467
+ container.remove();
468
+ removeImageFromStorage(imageUrl);
469
+ };
470
+
471
+ container.appendChild(img);
472
+ container.appendChild(deleteButton);
473
+ outputContainer.prepend(container);
474
+
475
+ let savedImages = JSON.parse(localStorage.getItem('images')) || [];
476
+ if (!savedImages.some(imgObj => imgObj.url === imageUrl)) {
477
+ savedImages.push({ url: imageUrl, prompt: prompt, width: width, height: height, steps: steps });
478
+ localStorage.setItem('images', JSON.stringify(savedImages));
479
+ }
480
+ }
481
+
482
+ function removeImageFromStorage(imageUrl) {
483
+ let savedImages = JSON.parse(localStorage.getItem('images')) || [];
484
+ savedImages = savedImages.filter(imgObj => imgObj.url !== imageUrl);
485
+ localStorage.setItem('images', JSON.stringify(savedImages));
486
+ }
487
+
488
+ function openModal(imageUrl, prompt, width, height, steps) {
489
+ modal.style.display = 'flex';
490
+ modalImage.src = imageUrl;
491
+ promptInfo.innerText = `Prompt: ${prompt}`;
492
+ settingsInfo.innerText = `Width: ${width}, Height: ${height}, Steps: ${steps}`;
493
+ }
494
+
495
+ copyPromptBtn.onclick = () => {
496
+ const promptText = promptInfo.innerText.replace('Prompt: ', '');
497
+ navigator.clipboard.writeText(promptText);
498
+ };
499
+
500
+ modal.onclick = (event) => {
501
+ if (event.target === modal) {
502
+ modal.style.display = 'none';
503
+ }
504
+ };
505
+
506
+ async function sendImageGenerationRequest(prompt, width, height, steps, apiKey) {
507
+ const response = await fetch('https://api.bfl.ml/v1/image', {
508
+ method: 'POST',
509
+ headers: {
510
+ 'Content-Type': 'application/json',
511
+ 'x-key': apiKey,
512
+ },
513
+ body: JSON.stringify({
514
+ prompt: prompt,
515
+ width: parseInt(width),
516
+ height: parseInt(height),
517
+ steps: parseInt(steps),
518
+ }),
519
+ });
520
+
521
+ const data = await response.json();
522
+ return data.id;
523
+ }
524
+
525
+ async function pollResult(requestId, apiKey) {
526
+ while (true) {
527
+ const result = await getResult(requestId, apiKey);
528
+ const status = result.status;
529
+
530
+ if (status === 'Ready') {
531
+ return result.result.sample;
532
+ } else if (['Error', 'Content Moderated', 'Request Moderated', 'Task not found'].includes(status)) {
533
+ throw new Error(`Image generation failed. Status: ${status}`);
534
+ }
535
+
536
+ await new Promise(resolve => setTimeout(resolve, 1000));
537
+ }
538
+ }
539
+
540
+ async function getResult(requestId, apiKey) {
541
+ const response = await fetch(`https://api.bfl.ml/v1/get_result?id=${requestId}`, {
542
+ method: 'GET',
543
+ headers: {
544
+ 'x-key': apiKey,
545
+ },
546
+ });
547
+
548
+ const data = await response.json();
549
+ return data;
550
+ }
551
+ </script>
552
+
553
+ </body>
554
+ </html>