Elias207 commited on
Commit
4c1e5cb
·
verified ·
1 Parent(s): 7a42222

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +594 -172
index.html CHANGED
@@ -1,172 +1,594 @@
1
- body {
2
- font-family: 'Vazirmatn', sans-serif;
3
- background: linear-gradient(135deg, var(--background-end), var(--background-start));
4
- color: var(--text-color);
5
- display: flex;
6
- justify-content: center;
7
- align-items: center;
8
- min-height: 100vh;
9
- padding: 20px;
10
- gap: 40px;
11
- flex-wrap: wrap;
12
- }
13
-
14
- .main-title {
15
- width: 100%;
16
- text-align: center;
17
- font-size: 2.5rem;
18
- font-weight: 300;
19
- margin-bottom: 20px;
20
- text-shadow: 0 2px 4px rgba(0,0,0,0.3);
21
- }
22
- .main-title span {
23
- font-weight: 700;
24
- color: #fff;
25
- }
26
-
27
- .container {
28
- background: var(--container-bg);
29
- padding: 30px;
30
- border-radius: 15px;
31
- box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37);
32
- backdrop-filter: blur(10px);
33
- -webkit-backdrop-filter: blur(10px);
34
- border: 1px solid var(--border-color);
35
- width: 100%;
36
- max-width: 450px;
37
- display: flex;
38
- flex-direction: column;
39
- gap: 20px;
40
- transition: transform 0.3s ease, box-shadow 0.3s ease;
41
- }
42
- .container:hover {
43
- transform: translateY(-5px);
44
- box-shadow: 0 12px 40px 0 rgba(0, 0, 0, 0.45);
45
- }
46
-
47
- h2 {
48
- text-align: center;
49
- color: #fff;
50
- margin-top: 0;
51
- font-weight: 500;
52
- border-bottom: 1px solid var(--secondary-color);
53
- padding-bottom: 15px;
54
- }
55
-
56
- label {
57
- font-size: 0.9rem;
58
- margin-bottom: -10px;
59
- color: #bdc3c7;
60
- }
61
-
62
- textarea, .file-label {
63
- width: 100%;
64
- padding: 12px;
65
- border-radius: 8px;
66
- border: 1px solid var(--border-color);
67
- box-sizing: border-box;
68
- font-size: 1rem;
69
- background: var(--input-bg);
70
- color: var(--text-color);
71
- transition: border-color 0.3s, box-shadow 0.3s;
72
- }
73
- textarea::placeholder {
74
- color: #95a5a6;
75
- }
76
- textarea:focus, .file-label:hover {
77
- outline: none;
78
- border-color: var(--secondary-color);
79
- box-shadow: 0 0 10px rgba(52, 152, 219, 0.5);
80
- }
81
-
82
- /* Custom file input */
83
- .file-wrapper {
84
- position: relative;
85
- cursor: pointer;
86
- }
87
- input[type="file"] {
88
- display: none;
89
- }
90
- .file-label {
91
- display: flex;
92
- justify-content: center;
93
- align-items: center;
94
- gap: 10px;
95
- }
96
- #file-name {
97
- margin-top: 10px;
98
- font-size: 0.85rem;
99
- color: #bdc3c7;
100
- text-align: center;
101
- height: 1.2em;
102
- }
103
-
104
- button {
105
- padding: 14px 20px;
106
- background: linear-gradient(45deg, var(--primary-color), var(--secondary-color));
107
- color: white;
108
- border: none;
109
- border-radius: 8px;
110
- cursor: pointer;
111
- font-size: 1.1rem;
112
- font-weight: 600;
113
- transition: all 0.3s ease;
114
- display: flex;
115
- justify-content: center;
116
- align-items: center;
117
- gap: 10px;
118
- box-shadow: 0 4px 15px rgba(0,0,0,0.2);
119
- }
120
- button:hover:not(:disabled) {
121
- transform: translateY(-3px);
122
- box-shadow: 0 6px 20px rgba(0,0,0,0.3);
123
- }
124
- button:disabled {
125
- background: #555;
126
- cursor: not-allowed;
127
- opacity: 0.7;
128
- }
129
-
130
- .result-box {
131
- margin-top: 15px;
132
- padding: 20px;
133
- background: var(--input-bg);
134
- border: 1px solid var(--border-color);
135
- border-radius: 8px;
136
- min-height: 100px;
137
- display: flex;
138
- justify-content: center;
139
- align-items: center;
140
- text-align: center;
141
- word-wrap: break-word;
142
- color: #ecf0f1;
143
- font-size: 1rem;
144
- }
145
-
146
- #qr-code-display img {
147
- max-width: 100%;
148
- height: auto;
149
- border-radius: 8px;
150
- border: 2px solid white;
151
- animation: fadeIn 0.5s ease-in-out;
152
- }
153
-
154
- .loader {
155
- border: 4px solid #555;
156
- border-top: 4px solid var(--secondary-color);
157
- border-radius: 50%;
158
- width: 30px;
159
- height: 30px;
160
- animation: spin 1s linear infinite;
161
- display: none;
162
- }
163
-
164
- @keyframes spin {
165
- 0% { transform: rotate(0deg); }
166
- 100% { transform: rotate(360deg); }
167
- }
168
- @keyframes fadeIn {
169
- from { opacity: 0; transform: scale(0.9); }
170
- to { opacity: 1; transform: scale(1); }
171
- }
172
- </style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="fa" dir="rtl">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>QR کد | ساخت و خواندن</title>
7
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/rastikerdar/vazirmatn@v33.003/Vazirmatn-font-face.css">
8
+ <style>
9
+ * {
10
+ margin: 0;
11
+ padding: 0;
12
+ box-sizing: border-box;
13
+ }
14
+
15
+ body {
16
+ font-family: 'Vazirmatn', sans-serif;
17
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
18
+ min-height: 100vh;
19
+ color: #fff;
20
+ overflow-x: hidden;
21
+ }
22
+
23
+ .container {
24
+ max-width: 400px;
25
+ margin: 0 auto;
26
+ padding: 15px;
27
+ min-height: 100vh;
28
+ display: flex;
29
+ flex-direction: column;
30
+ }
31
+
32
+ /* هدر */
33
+ .header {
34
+ text-align: center;
35
+ padding: 20px 0 30px;
36
+ }
37
+
38
+ .logo {
39
+ font-size: 3rem;
40
+ margin-bottom: 10px;
41
+ filter: drop-shadow(0 4px 8px rgba(0,0,0,0.3));
42
+ }
43
+
44
+ .title {
45
+ font-size: 1.5rem;
46
+ font-weight: 600;
47
+ margin-bottom: 5px;
48
+ }
49
+
50
+ .subtitle {
51
+ font-size: 0.9rem;
52
+ opacity: 0.8;
53
+ }
54
+
55
+ /* تب‌ها */
56
+ .tabs {
57
+ display: flex;
58
+ background: rgba(255,255,255,0.15);
59
+ border-radius: 15px;
60
+ padding: 5px;
61
+ margin-bottom: 20px;
62
+ backdrop-filter: blur(10px);
63
+ }
64
+
65
+ .tab {
66
+ flex: 1;
67
+ padding: 12px;
68
+ text-align: center;
69
+ border-radius: 10px;
70
+ cursor: pointer;
71
+ transition: all 0.3s ease;
72
+ font-weight: 500;
73
+ font-size: 0.9rem;
74
+ }
75
+
76
+ .tab.active {
77
+ background: rgba(255,255,255,0.3);
78
+ transform: translateY(-2px);
79
+ box-shadow: 0 4px 12px rgba(0,0,0,0.2);
80
+ }
81
+
82
+ /* کارت اصلی */
83
+ .card {
84
+ background: rgba(255,255,255,0.2);
85
+ border-radius: 20px;
86
+ padding: 25px;
87
+ backdrop-filter: blur(15px);
88
+ border: 1px solid rgba(255,255,255,0.3);
89
+ box-shadow: 0 8px 32px rgba(0,0,0,0.1);
90
+ flex: 1;
91
+ display: flex;
92
+ flex-direction: column;
93
+ }
94
+
95
+ /* محتوای تب‌ها */
96
+ .tab-content {
97
+ display: none;
98
+ flex: 1;
99
+ display: flex;
100
+ flex-direction: column;
101
+ }
102
+
103
+ .tab-content.active {
104
+ display: flex;
105
+ }
106
+
107
+ /* فرم */
108
+ .form-group {
109
+ margin-bottom: 20px;
110
+ }
111
+
112
+ .label {
113
+ display: block;
114
+ margin-bottom: 8px;
115
+ font-size: 0.9rem;
116
+ opacity: 0.9;
117
+ font-weight: 500;
118
+ }
119
+
120
+ .input {
121
+ width: 100%;
122
+ padding: 15px;
123
+ border: none;
124
+ border-radius: 12px;
125
+ background: rgba(255,255,255,0.9);
126
+ color: #333;
127
+ font-size: 1rem;
128
+ min-height: 100px;
129
+ resize: vertical;
130
+ outline: none;
131
+ transition: all 0.3s ease;
132
+ }
133
+
134
+ .input:focus {
135
+ background: white;
136
+ transform: translateY(-2px);
137
+ box-shadow: 0 6px 20px rgba(0,0,0,0.15);
138
+ }
139
+
140
+ .input::placeholder {
141
+ color: #666;
142
+ }
143
+
144
+ /* فایل آپلود */
145
+ .file-upload {
146
+ position: relative;
147
+ background: rgba(255,255,255,0.9);
148
+ border: 2px dashed #667eea;
149
+ border-radius: 12px;
150
+ padding: 30px 20px;
151
+ text-align: center;
152
+ cursor: pointer;
153
+ transition: all 0.3s ease;
154
+ }
155
+
156
+ .file-upload:hover {
157
+ background: white;
158
+ transform: translateY(-2px);
159
+ }
160
+
161
+ .file-upload input {
162
+ position: absolute;
163
+ left: -9999px;
164
+ }
165
+
166
+ .upload-icon {
167
+ font-size: 2.5rem;
168
+ margin-bottom: 10px;
169
+ color: #667eea;
170
+ }
171
+
172
+ .upload-text {
173
+ color: #333;
174
+ font-size: 0.9rem;
175
+ font-weight: 500;
176
+ }
177
+
178
+ .file-info {
179
+ margin-top: 10px;
180
+ padding: 8px 12px;
181
+ background: rgba(102, 126, 234, 0.1);
182
+ border-radius: 8px;
183
+ font-size: 0.8rem;
184
+ color: #333;
185
+ display: none;
186
+ }
187
+
188
+ /* دکمه */
189
+ .btn {
190
+ width: 100%;
191
+ padding: 16px;
192
+ border: none;
193
+ border-radius: 12px;
194
+ font-size: 1.1rem;
195
+ font-weight: 600;
196
+ cursor: pointer;
197
+ margin-top: auto;
198
+ margin-bottom: 20px;
199
+ transition: all 0.3s ease;
200
+ position: relative;
201
+ overflow: hidden;
202
+ }
203
+
204
+ .btn-generate {
205
+ background: linear-gradient(45deg, #ff6b6b, #ee5a24);
206
+ color: white;
207
+ box-shadow: 0 6px 20px rgba(255, 107, 107, 0.4);
208
+ }
209
+
210
+ .btn-read {
211
+ background: linear-gradient(45deg, #00d2d3, #54a0ff);
212
+ color: white;
213
+ box-shadow: 0 6px 20px rgba(84, 160, 255, 0.4);
214
+ }
215
+
216
+ .btn:hover:not(:disabled) {
217
+ transform: translateY(-3px);
218
+ box-shadow: 0 8px 25px rgba(0,0,0,0.3);
219
+ }
220
+
221
+ .btn:disabled {
222
+ opacity: 0.6;
223
+ cursor: not-allowed;
224
+ transform: none;
225
+ }
226
+
227
+ .btn:active {
228
+ transform: translateY(0);
229
+ }
230
+
231
+ /* نتایج */
232
+ .result {
233
+ flex: 1;
234
+ background: rgba(255,255,255,0.15);
235
+ border-radius: 12px;
236
+ padding: 20px;
237
+ min-height: 150px;
238
+ display: flex;
239
+ align-items: center;
240
+ justify-content: center;
241
+ text-align: center;
242
+ backdrop-filter: blur(5px);
243
+ margin-bottom: 20px;
244
+ }
245
+
246
+ .result-empty {
247
+ opacity: 0.7;
248
+ font-style: italic;
249
+ }
250
+
251
+ .result img {
252
+ max-width: 100%;
253
+ height: auto;
254
+ border-radius: 8px;
255
+ background: white;
256
+ padding: 10px;
257
+ box-shadow: 0 4px 15px rgba(0,0,0,0.2);
258
+ animation: zoomIn 0.4s ease;
259
+ }
260
+
261
+ .result-text {
262
+ background: rgba(255,255,255,0.2);
263
+ border-radius: 8px;
264
+ padding: 15px;
265
+ word-break: break-all;
266
+ line-height: 1.5;
267
+ animation: slideUp 0.4s ease;
268
+ }
269
+
270
+ /* لودر */
271
+ .loader {
272
+ width: 40px;
273
+ height: 40px;
274
+ border: 3px solid rgba(255,255,255,0.3);
275
+ border-top: 3px solid white;
276
+ border-radius: 50%;
277
+ animation: spin 1s linear infinite;
278
+ }
279
+
280
+ /* انیمیشن‌ها */
281
+ @keyframes spin {
282
+ 0% { transform: rotate(0deg); }
283
+ 100% { transform: rotate(360deg); }
284
+ }
285
+
286
+ @keyframes zoomIn {
287
+ from { opacity: 0; transform: scale(0.8); }
288
+ to { opacity: 1; transform: scale(1); }
289
+ }
290
+
291
+ @keyframes slideUp {
292
+ from { opacity: 0; transform: translateY(20px); }
293
+ to { opacity: 1; transform: translateY(0); }
294
+ }
295
+
296
+ /* آیکون‌ها */
297
+ .icon {
298
+ display: inline-block;
299
+ margin-left: 8px;
300
+ }
301
+
302
+ /* ریسپانسیو برای موبایل‌های کوچک */
303
+ @media (max-width: 360px) {
304
+ .container {
305
+ padding: 10px;
306
+ }
307
+
308
+ .card {
309
+ padding: 20px;
310
+ }
311
+
312
+ .title {
313
+ font-size: 1.3rem;
314
+ }
315
+ }
316
+ </style>
317
+ </head>
318
+ <body>
319
+ <div class="container">
320
+ <!-- هدر -->
321
+ <div class="header">
322
+ <div class="logo">📱</div>
323
+ <h1 class="title">QR کد ساز</h1>
324
+ <p class="subtitle">ساخت و خواندن آسان کیوآر کد</p>
325
+ </div>
326
+
327
+ <!-- تب‌ها -->
328
+ <div class="tabs">
329
+ <div class="tab active" data-tab="generate">
330
+ <span class="icon">➕</span>
331
+ ساخت
332
+ </div>
333
+ <div class="tab" data-tab="read">
334
+ <span class="icon">👁</span>
335
+ خواندن
336
+ </div>
337
+ </div>
338
+
339
+ <!-- کارت اصلی -->
340
+ <div class="card">
341
+ <!-- تب ساخت -->
342
+ <div class="tab-content active" id="generate-content">
343
+ <div class="form-group">
344
+ <label class="label">متن یا لینک خود را بنویسید:</label>
345
+ <textarea id="text-input" class="input" placeholder="مثال: https://google.com یا سلام دنیا">سلام دنیا</textarea>
346
+ </div>
347
+
348
+ <div class="result" id="qr-result">
349
+ <div id="generate-loader" class="loader" style="display: none;"></div>
350
+ <div id="qr-display">
351
+ <span class="result-empty">QR کد شما اینجا ظاهر می‌شود</span>
352
+ </div>
353
+ </div>
354
+
355
+ <button id="generate-btn" class="btn btn-generate">
356
+ <span class="icon">✨</span>
357
+ ساخت QR کد
358
+ </button>
359
+ </div>
360
+
361
+ <!-- تب خواندن -->
362
+ <div class="tab-content" id="read-content">
363
+ <div class="form-group">
364
+ <label class="label">تصویر QR کد را انتخاب کنید:</label>
365
+ <div class="file-upload" onclick="document.getElementById('file-input').click()">
366
+ <input type="file" id="file-input" accept="image/*">
367
+ <div class="upload-icon">📷</div>
368
+ <div class="upload-text">انتخاب تصویر</div>
369
+ <div id="file-info" class="file-info"></div>
370
+ </div>
371
+ </div>
372
+
373
+ <div class="result" id="read-result">
374
+ <div id="read-loader" class="loader" style="display: none;"></div>
375
+ <div id="decoded-text">
376
+ <span class="result-empty">نتیجه اینجا نمایش داده می‌شود</span>
377
+ </div>
378
+ </div>
379
+
380
+ <button id="read-btn" class="btn btn-read">
381
+ <span class="icon">🔍</span>
382
+ خواندن QR کد
383
+ </button>
384
+ </div>
385
+ </div>
386
+ </div>
387
+
388
+ <script>
389
+ const SPACE_URL = "https://cultrix-qrcode-read-generate.hf.space";
390
+
391
+ // عناصر DOM
392
+ const tabs = document.querySelectorAll('.tab');
393
+ const tabContents = document.querySelectorAll('.tab-content');
394
+ const generateBtn = document.getElementById('generate-btn');
395
+ const readBtn = document.getElementById('read-btn');
396
+ const textInput = document.getElementById('text-input');
397
+ const fileInput = document.getElementById('file-input');
398
+ const qrDisplay = document.getElementById('qr-display');
399
+ const decodedText = document.getElementById('decoded-text');
400
+ const generateLoader = document.getElementById('generate-loader');
401
+ const readLoader = document.getElementById('read-loader');
402
+ const fileInfo = document.getElementById('file-info');
403
+
404
+ // تعویض تب‌ها
405
+ tabs.forEach(tab => {
406
+ tab.addEventListener('click', () => {
407
+ // حذف کلاس active از همه
408
+ tabs.forEach(t => t.classList.remove('active'));
409
+ tabContents.forEach(tc => tc.classList.remove('active'));
410
+
411
+ // اضافه کردن کلاس active
412
+ tab.classList.add('active');
413
+ const targetTab = tab.getAttribute('data-tab');
414
+ document.getElementById(targetTab + '-content').classList.add('active');
415
+ });
416
+ });
417
+
418
+ // نمایش اطلاعات فایل
419
+ fileInput.addEventListener('change', () => {
420
+ if (fileInput.files.length > 0) {
421
+ fileInfo.textContent = `📎 ${fileInput.files[0].name}`;
422
+ fileInfo.style.display = 'block';
423
+ } else {
424
+ fileInfo.style.display = 'none';
425
+ }
426
+ });
427
+
428
+ // توابع کمکی
429
+ const generateSessionHash = () => Math.random().toString(36).substring(2, 15);
430
+
431
+ const listenForData = (sessionHash, onResult, onError) => {
432
+ const eventSource = new EventSource(`${SPACE_URL}/gradio_api/queue/data?session_hash=${sessionHash}`);
433
+
434
+ eventSource.onmessage = (event) => {
435
+ const data = JSON.parse(event.data);
436
+ if (data.msg === "process_completed") {
437
+ eventSource.close();
438
+ if (data.output.error) {
439
+ onError(data.output.error);
440
+ } else {
441
+ onResult(data.output.data);
442
+ }
443
+ } else if (data.msg === "process_failed") {
444
+ eventSource.close();
445
+ onError("پردازش با خطا مواجه شد.");
446
+ }
447
+ };
448
+
449
+ eventSource.onerror = (err) => {
450
+ eventSource.close();
451
+ onError("خطا در ارتباط با سرور.");
452
+ };
453
+ };
454
+
455
+ // ساخت QR کد
456
+ generateBtn.addEventListener('click', async () => {
457
+ const text = textInput.value.trim();
458
+ if (!text) {
459
+ alert("لطفاً متنی را وارد کنید.");
460
+ return;
461
+ }
462
+
463
+ generateLoader.style.display = 'block';
464
+ qrDisplay.innerHTML = '';
465
+ generateBtn.disabled = true;
466
+
467
+ const sessionHash = generateSessionHash();
468
+
469
+ try {
470
+ const joinResponse = await fetch(`${SPACE_URL}/gradio_api/queue/join`, {
471
+ method: 'POST',
472
+ headers: { 'Content-Type': 'application/json' },
473
+ body: JSON.stringify({ fn_index: 0, data: [text], session_hash: sessionHash })
474
+ });
475
+
476
+ if (!joinResponse.ok) throw new Error('خطا در ارسال درخواست');
477
+
478
+ listenForData(
479
+ sessionHash,
480
+ (result) => {
481
+ if (result && result[0]) {
482
+ qrDisplay.innerHTML = result[0];
483
+ } else {
484
+ qrDisplay.innerHTML = '<span class="result-empty">خطا در ساخت QR کد</span>';
485
+ }
486
+ },
487
+ (error) => {
488
+ alert(`خطا: ${error}`);
489
+ qrDisplay.innerHTML = '<span class="result-empty">خطا در ساخت</span>';
490
+ }
491
+ );
492
+ } catch (error) {
493
+ alert(`خطا: ${error.message}`);
494
+ qrDisplay.innerHTML = '<span class="result-empty">خطا در ساخت</span>';
495
+ } finally {
496
+ generateLoader.style.display = 'none';
497
+ generateBtn.disabled = false;
498
+ }
499
+ });
500
+
501
+ // خواندن QR کد
502
+ readBtn.addEventListener('click', async () => {
503
+ const file = fileInput.files[0];
504
+ if (!file) {
505
+ alert("لطفاً یک تصویر انتخاب کنید.");
506
+ return;
507
+ }
508
+
509
+ readLoader.style.display = 'block';
510
+ decodedText.innerHTML = '';
511
+ readBtn.disabled = true;
512
+
513
+ try {
514
+ const formData = new FormData();
515
+ formData.append('files', file);
516
+
517
+ const uploadResponse = await fetch(`${SPACE_URL}/gradio_api/upload`, {
518
+ method: 'POST',
519
+ body: formData
520
+ });
521
+
522
+ if (!uploadResponse.ok) throw new Error('خطا در آپلود فایل');
523
+
524
+ const uploadResult = await uploadResponse.json();
525
+ const serverFilePath = uploadResult[0];
526
+
527
+ const fileDataObject = {
528
+ path: serverFilePath,
529
+ url: `${SPACE_URL}/gradio_api/file=${serverFilePath}`,
530
+ orig_name: file.name,
531
+ };
532
+
533
+ const sessionHash = generateSessionHash();
534
+ const joinResponse = await fetch(`${SPACE_URL}/gradio_api/queue/join`, {
535
+ method: 'POST',
536
+ headers: { 'Content-Type': 'application/json' },
537
+ body: JSON.stringify({ fn_index: 1, data: [fileDataObject], session_hash: sessionHash })
538
+ });
539
+
540
+ if (!joinResponse.ok) throw new Error('خطا در پردازش');
541
+
542
+ listenForData(
543
+ sessionHash,
544
+ (result) => {
545
+ decodedText.innerHTML = `<div class="result-text">📝 ${result[0]}</div>`;
546
+ },
547
+ (error) => {
548
+ alert(`خطا: ${error}`);
549
+ decodedText.innerHTML = '<span class="result-empty">خطا در خواندن</span>';
550
+ }
551
+ );
552
+ } catch (error) {
553
+ alert(`خطا: ${error.message}`);
554
+ decodedText.innerHTML = '<span class="result-empty">خطا در پردازش</span>';
555
+ } finally {
556
+ readLoader.style.display = 'none';
557
+ readBtn.disabled = false;
558
+ }
559
+ });
560
+
561
+ // Drag & Drop برای فایل
562
+ const fileUpload = document.querySelector('.file-upload');
563
+
564
+ ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
565
+ fileUpload.addEventListener(eventName, (e) => {
566
+ e.preventDefault();
567
+ e.stopPropagation();
568
+ });
569
+ });
570
+
571
+ ['dragenter', 'dragover'].forEach(eventName => {
572
+ fileUpload.addEventListener(eventName, () => {
573
+ fileUpload.style.background = 'white';
574
+ fileUpload.style.transform = 'translateY(-2px)';
575
+ });
576
+ });
577
+
578
+ ['dragleave', 'drop'].forEach(eventName => {
579
+ fileUpload.addEventListener(eventName, () => {
580
+ fileUpload.style.background = 'rgba(255,255,255,0.9)';
581
+ fileUpload.style.transform = 'translateY(0)';
582
+ });
583
+ });
584
+
585
+ fileUpload.addEventListener('drop', (e) => {
586
+ const files = e.dataTransfer.files;
587
+ if (files.length > 0) {
588
+ fileInput.files = files;
589
+ fileInput.dispatchEvent(new Event('change'));
590
+ }
591
+ });
592
+ </script>
593
+ </body>
594
+ </html>