Elias207 commited on
Commit
bf863df
·
verified ·
1 Parent(s): eba0b23

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +412 -159
index.html CHANGED
@@ -7,236 +7,483 @@
7
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/rastikerdar/vazirmatn@v33.003/Vazirmatn-font-face.css">
8
  <style>
9
  :root {
10
- --primary-color: #8e44ad;
11
- --secondary-color: #3498db;
12
- --background-start: #141e30;
13
- --background-end: #243b55;
14
- --text-color: #ecf0f1;
15
- --input-bg: rgba(255, 255, 255, 0.1);
16
- --container-bg: rgba(255, 255, 255, 0.15);
17
- --border-color: rgba(255, 255, 255, 0.2);
 
 
 
 
 
 
 
 
 
18
  }
19
 
20
  body {
21
  font-family: 'Vazirmatn', sans-serif;
22
- background: linear-gradient(135deg, var(--background-end), var(--background-start));
23
- color: var(--text-color);
24
- display: flex;
25
- justify-content: center;
26
- align-items: center;
27
  min-height: 100vh;
28
- padding: 20px;
29
- gap: 40px;
30
- flex-wrap: wrap;
31
  }
32
 
33
- .main-title {
 
 
 
 
 
34
  width: 100%;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  text-align: center;
36
- font-size: 2.5rem;
 
 
 
 
 
 
 
37
  font-weight: 300;
38
- margin-bottom: 20px;
39
- text-shadow: 0 2px 4px rgba(0,0,0,0.3);
 
 
 
 
40
  }
 
41
  .main-title span {
42
  font-weight: 700;
43
- color: #fff;
 
 
 
44
  }
45
 
46
- .container {
47
- background: var(--container-bg);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  padding: 30px;
49
- border-radius: 15px;
50
- box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37);
51
- backdrop-filter: blur(10px);
52
- -webkit-backdrop-filter: blur(10px);
53
- border: 1px solid var(--border-color);
54
- width: 100%;
55
- max-width: 450px;
56
- display: flex;
57
- flex-direction: column;
58
- gap: 20px;
59
- transition: transform 0.3s ease, box-shadow 0.3s ease;
 
 
 
 
 
60
  }
61
- .container:hover {
62
- transform: translateY(-5px);
63
- box-shadow: 0 12px 40px 0 rgba(0, 0, 0, 0.45);
 
64
  }
65
 
66
- h2 {
67
- text-align: center;
68
- color: #fff;
69
- margin-top: 0;
70
- font-weight: 500;
71
- border-bottom: 1px solid var(--secondary-color);
 
 
 
72
  padding-bottom: 15px;
 
73
  }
74
 
75
- label {
76
- font-size: 0.9rem;
77
- margin-bottom: -10px;
78
- color: #bdc3c7;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  }
80
 
81
- textarea, .file-label {
82
  width: 100%;
83
- padding: 12px;
84
- border-radius: 8px;
85
- border: 1px solid var(--border-color);
86
- box-sizing: border-box;
87
- font-size: 1rem;
88
  background: var(--input-bg);
89
- color: var(--text-color);
90
- transition: border-color 0.3s, box-shadow 0.3s;
91
- }
92
- textarea::placeholder {
93
- color: #95a5a6;
 
94
  }
95
- textarea:focus, .file-label:hover {
 
96
  outline: none;
97
- border-color: var(--secondary-color);
98
- box-shadow: 0 0 10px rgba(52, 152, 219, 0.5);
 
99
  }
100
 
101
- /* Custom file input */
102
- .file-wrapper {
 
 
 
103
  position: relative;
104
  cursor: pointer;
105
  }
106
- input[type="file"] {
 
107
  display: none;
108
  }
109
- .file-label {
 
110
  display: flex;
111
- justify-content: center;
112
  align-items: center;
113
- gap: 10px;
 
 
 
 
 
 
 
 
 
 
 
 
114
  }
115
- #file-name {
 
116
  margin-top: 10px;
117
- font-size: 0.85rem;
118
- color: #bdc3c7;
 
 
 
119
  text-align: center;
120
- height: 1.2em;
121
  }
122
-
123
- button {
124
- padding: 14px 20px;
125
- background: linear-gradient(45deg, var(--primary-color), var(--secondary-color));
126
- color: white;
127
  border: none;
128
- border-radius: 8px;
129
- cursor: pointer;
130
  font-size: 1.1rem;
131
  font-weight: 600;
 
132
  transition: all 0.3s ease;
133
  display: flex;
134
- justify-content: center;
135
  align-items: center;
 
136
  gap: 10px;
137
  box-shadow: 0 4px 15px rgba(0,0,0,0.2);
 
 
 
 
 
 
 
 
 
 
 
 
 
138
  }
139
- button:hover:not(:disabled) {
140
- transform: translateY(-3px);
 
141
  box-shadow: 0 6px 20px rgba(0,0,0,0.3);
142
  }
143
- button:disabled {
144
- background: #555;
 
 
 
 
 
145
  cursor: not-allowed;
146
- opacity: 0.7;
 
 
 
 
147
  }
148
 
149
- .result-box {
150
- margin-top: 15px;
151
  padding: 20px;
152
  background: var(--input-bg);
153
- border: 1px solid var(--border-color);
154
- border-radius: 8px;
155
- min-height: 100px;
156
  display: flex;
157
- justify-content: center;
158
  align-items: center;
 
159
  text-align: center;
160
- word-wrap: break-word;
161
- color: #ecf0f1;
162
- font-size: 1rem;
163
  }
164
-
165
- #qr-code-display img {
166
  max-width: 100%;
167
  height: auto;
168
  border-radius: 8px;
169
- border: 2px solid white;
170
- animation: fadeIn 0.5s ease-in-out;
 
 
 
 
 
 
171
  }
172
 
173
  .loader {
174
- border: 4px solid #555;
175
- border-top: 4px solid var(--secondary-color);
 
 
176
  border-radius: 50%;
177
- width: 30px;
178
- height: 30px;
179
  animation: spin 1s linear infinite;
180
- display: none;
181
  }
182
 
183
  @keyframes spin {
184
  0% { transform: rotate(0deg); }
185
  100% { transform: rotate(360deg); }
186
  }
187
- @keyframes fadeIn {
188
- from { opacity: 0; transform: scale(0.9); }
189
- to { opacity: 1; transform: scale(1); }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
  }
191
  </style>
192
  </head>
193
  <body>
194
-
195
- <h1 class="main-title">ابزار مدرن <span>QR Code</span></h1>
196
-
197
- <!-- بخش ساخت QR Code -->
198
- <div class="container">
199
- <h2>ساخت QR Code از متن</h2>
200
- <label for="text-input">متن خود را وارد کنید:</label>
201
- <textarea id="text-input" rows="4" placeholder="مثلا: https://google.com">سلام دنیا</textarea>
202
- <button id="generate-btn">
203
- <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2a10 10 0 1 0 10 10A10 10 0 0 0 12 2v0z"/><path d="M12 8l4 4-4 4"/><path d="M8 12h7"/></svg>
204
- <span>ساخت QR Code</span>
205
- </button>
206
- <div class="result-box">
207
- <div id="generate-loader" class="loader"></div>
208
- <div id="qr-code-display"></div>
209
- </div>
210
  </div>
211
 
212
- <!-- بخش خواندن QR Code -->
213
- <div class="container">
214
- <h2>خواندن متن از QR Code</h2>
215
- <label for="file-input">فایل تصویر QR Code را انتخاب کنید:</label>
216
- <div class="file-wrapper">
217
- <input type="file" id="file-input" accept="image/*">
218
- <label for="file-input" class="file-label">
219
- <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
220
- <span>انتخاب فایل تصویر</span>
221
- </label>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
222
  </div>
223
- <p id="file-name"></p>
224
- <button id="read-btn">
225
- <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
226
- <span>خواندن QR Code</span>
227
- </button>
228
- <div class="result-box">
229
- <div id="read-loader" class="loader"></div>
230
- <p id="decoded-text">نتیجه در اینجا نمایش داده می‌شود.</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231
  </div>
232
  </div>
233
 
234
  <script>
235
- // --- کد جاوااسکریپت بدون هیچ تغییری باقی مانده است ---
236
-
237
  const SPACE_URL = "https://cultrix-qrcode-read-generate.hf.space";
238
 
239
- // --- دریافت عناصر DOM ---
240
  const generateBtn = document.getElementById('generate-btn');
241
  const readBtn = document.getElementById('read-btn');
242
  const textInput = document.getElementById('text-input');
@@ -250,13 +497,14 @@
250
  // نمایش نام فایل انتخاب شده
251
  fileInput.addEventListener('change', () => {
252
  if (fileInput.files.length > 0) {
253
- fileNameDisplay.textContent = `فایل انتخاب شده: ${fileInput.files[0].name}`;
 
254
  } else {
255
  fileNameDisplay.textContent = '';
256
  }
257
  });
258
 
259
- // --- توابع کمکی ---
260
  const generateSessionHash = () => Math.random().toString(36).substring(2, 15);
261
 
262
  const listenForData = (sessionHash, onResult, onError) => {
@@ -286,10 +534,15 @@
286
  };
287
  };
288
 
289
- // --- منطق ساخت QR Code ---
290
  generateBtn.addEventListener('click', async () => {
291
  const text = textInput.value.trim();
292
- if (!text) return alert("لطفاً متنی را وارد کنید.");
 
 
 
 
 
293
 
294
  generateLoader.style.display = 'block';
295
  qrCodeDisplay.innerHTML = '';
@@ -312,29 +565,32 @@
312
  if (result && result[0]) {
313
  qrCodeDisplay.innerHTML = result[0];
314
  } else {
315
- qrCodeDisplay.innerText = "خطا: خروجی معتبر دریافت نشد.";
316
  }
317
  },
318
  (error) => {
319
- alert(`خطا در پردازش: ${error}`);
320
- qrCodeDisplay.innerText = "خطا در ساخت تصویر.";
321
  }
322
  );
323
  } catch (error) {
324
- alert(`یک خطا رخ داد: ${error.message}`);
325
  } finally {
326
  generateLoader.style.display = 'none';
327
  generateBtn.disabled = false;
328
  }
329
  });
330
 
331
- // --- منطق خواندن QR Code ---
332
  readBtn.addEventListener('click', async () => {
333
  const file = fileInput.files[0];
334
- if (!file) return alert("لطفاً یک فایل تصویر انتخاب کنید.");
 
 
 
 
335
 
336
  readLoader.style.display = 'block';
337
- decodedText.innerText = '';
338
  readBtn.disabled = true;
339
 
340
  try {
@@ -367,20 +623,17 @@
367
  listenForData(
368
  sessionHash,
369
  (result) => {
370
- decodedText.innerText = `متن خوانده شده: \n ${result[0]}`;
371
  },
372
  (error) => {
373
- alert(`خطا در پردازش: ${error}`);
374
- decodedText.innerText = "خطا در خواندن کد.";
375
  }
376
  );
377
  } catch (error) {
378
- alert(`یک خطا رخ داد: ${error.message}`);
379
- decodedText.innerText = "نتیجه در اینجا نمایش داده می‌شود.";
380
  } finally {
381
  readLoader.style.display = 'none';
382
  readBtn.disabled = false;
383
- // fileInput.value = ''; // ریست کردن اینپوت فایل باعث حذف نام فایل از نمایش می‌شود
384
  }
385
  });
386
  </script>
 
7
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/rastikerdar/vazirmatn@v33.003/Vazirmatn-font-face.css">
8
  <style>
9
  :root {
10
+ --primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
11
+ --secondary-gradient: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
12
+ --success-gradient: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
13
+ --bg-pattern: linear-gradient(45deg, #1e3c72 0%, #2a5298 50%, #1e3c72 100%);
14
+ --text-primary: #ffffff;
15
+ --text-secondary: #e2e8f0;
16
+ --card-bg: rgba(255, 255, 255, 0.1);
17
+ --card-border: rgba(255, 255, 255, 0.2);
18
+ --input-bg: rgba(255, 255, 255, 0.15);
19
+ --shadow-light: 0 8px 32px rgba(31, 38, 135, 0.37);
20
+ --shadow-heavy: 0 15px 35px rgba(31, 38, 135, 0.5);
21
+ }
22
+
23
+ * {
24
+ margin: 0;
25
+ padding: 0;
26
+ box-sizing: border-box;
27
  }
28
 
29
  body {
30
  font-family: 'Vazirmatn', sans-serif;
31
+ background: var(--bg-pattern);
32
+ background-attachment: fixed;
 
 
 
33
  min-height: 100vh;
34
+ color: var(--text-primary);
35
+ overflow-x: hidden;
 
36
  }
37
 
38
+ /* QR Pattern Background */
39
+ body::before {
40
+ content: '';
41
+ position: fixed;
42
+ top: 0;
43
+ left: 0;
44
  width: 100%;
45
+ height: 100%;
46
+ background-image:
47
+ radial-gradient(circle at 25% 25%, rgba(255,255,255,0.05) 2px, transparent 2px),
48
+ radial-gradient(circle at 75% 75%, rgba(255,255,255,0.05) 2px, transparent 2px);
49
+ background-size: 50px 50px;
50
+ z-index: -1;
51
+ animation: float 20s ease-in-out infinite;
52
+ }
53
+
54
+ @keyframes float {
55
+ 0%, 100% { transform: translateY(0px) rotate(0deg); }
56
+ 50% { transform: translateY(-20px) rotate(1deg); }
57
+ }
58
+
59
+ .header {
60
  text-align: center;
61
+ padding: 40px 20px;
62
+ background: rgba(255, 255, 255, 0.05);
63
+ backdrop-filter: blur(20px);
64
+ margin-bottom: 40px;
65
+ }
66
+
67
+ .main-title {
68
+ font-size: clamp(2rem, 5vw, 3.5rem);
69
  font-weight: 300;
70
+ margin-bottom: 10px;
71
+ background: linear-gradient(135deg, #ffffff, #a8edea);
72
+ -webkit-background-clip: text;
73
+ -webkit-text-fill-color: transparent;
74
+ background-clip: text;
75
+ text-shadow: 0 2px 10px rgba(0,0,0,0.3);
76
  }
77
+
78
  .main-title span {
79
  font-weight: 700;
80
+ background: var(--secondary-gradient);
81
+ -webkit-background-clip: text;
82
+ -webkit-text-fill-color: transparent;
83
+ background-clip: text;
84
  }
85
 
86
+ .subtitle {
87
+ font-size: 1.1rem;
88
+ color: var(--text-secondary);
89
+ opacity: 0.9;
90
+ }
91
+
92
+ .main-container {
93
+ display: grid;
94
+ grid-template-columns: 1fr 1fr;
95
+ gap: 30px;
96
+ max-width: 1200px;
97
+ margin: 0 auto;
98
+ padding: 0 20px;
99
+ }
100
+
101
+ @media (max-width: 768px) {
102
+ .main-container {
103
+ grid-template-columns: 1fr;
104
+ gap: 25px;
105
+ }
106
+ }
107
+
108
+ .card {
109
+ background: var(--card-bg);
110
+ backdrop-filter: blur(20px);
111
+ border: 1px solid var(--card-border);
112
+ border-radius: 20px;
113
  padding: 30px;
114
+ box-shadow: var(--shadow-light);
115
+ transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
116
+ position: relative;
117
+ overflow: hidden;
118
+ }
119
+
120
+ .card::before {
121
+ content: '';
122
+ position: absolute;
123
+ top: 0;
124
+ left: 0;
125
+ right: 0;
126
+ height: 4px;
127
+ background: var(--primary-gradient);
128
+ transform: scaleX(0);
129
+ transition: transform 0.3s ease;
130
  }
131
+
132
+ .card:hover {
133
+ transform: translateY(-10px);
134
+ box-shadow: var(--shadow-heavy);
135
  }
136
 
137
+ .card:hover::before {
138
+ transform: scaleX(1);
139
+ }
140
+
141
+ .card-header {
142
+ display: flex;
143
+ align-items: center;
144
+ gap: 15px;
145
+ margin-bottom: 25px;
146
  padding-bottom: 15px;
147
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
148
  }
149
 
150
+ .card-icon {
151
+ width: 50px;
152
+ height: 50px;
153
+ background: var(--primary-gradient);
154
+ border-radius: 12px;
155
+ display: flex;
156
+ align-items: center;
157
+ justify-content: center;
158
+ box-shadow: 0 4px 15px rgba(0,0,0,0.2);
159
+ }
160
+
161
+ .card-title {
162
+ font-size: 1.4rem;
163
+ font-weight: 600;
164
+ color: var(--text-primary);
165
+ }
166
+
167
+ .form-group {
168
+ margin-bottom: 20px;
169
+ }
170
+
171
+ .form-label {
172
+ display: block;
173
+ margin-bottom: 8px;
174
+ font-size: 0.95rem;
175
+ color: var(--text-secondary);
176
+ font-weight: 500;
177
  }
178
 
179
+ .form-input {
180
  width: 100%;
181
+ padding: 15px;
 
 
 
 
182
  background: var(--input-bg);
183
+ border: 2px solid transparent;
184
+ border-radius: 12px;
185
+ color: var(--text-primary);
186
+ font-size: 1rem;
187
+ transition: all 0.3s ease;
188
+ backdrop-filter: blur(10px);
189
  }
190
+
191
+ .form-input:focus {
192
  outline: none;
193
+ border-color: #667eea;
194
+ background: rgba(255, 255, 255, 0.2);
195
+ box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
196
  }
197
 
198
+ .form-input::placeholder {
199
+ color: rgba(255, 255, 255, 0.6);
200
+ }
201
+
202
+ .file-input-wrapper {
203
  position: relative;
204
  cursor: pointer;
205
  }
206
+
207
+ .file-input {
208
  display: none;
209
  }
210
+
211
+ .file-input-label {
212
  display: flex;
 
213
  align-items: center;
214
+ justify-content: center;
215
+ gap: 12px;
216
+ padding: 15px;
217
+ background: var(--input-bg);
218
+ border: 2px dashed rgba(255, 255, 255, 0.3);
219
+ border-radius: 12px;
220
+ transition: all 0.3s ease;
221
+ min-height: 60px;
222
+ }
223
+
224
+ .file-input-label:hover {
225
+ border-color: #667eea;
226
+ background: rgba(255, 255, 255, 0.2);
227
  }
228
+
229
+ .file-name {
230
  margin-top: 10px;
231
+ padding: 8px 12px;
232
+ background: rgba(255, 255, 255, 0.1);
233
+ border-radius: 8px;
234
+ font-size: 0.9rem;
235
+ color: var(--text-secondary);
236
  text-align: center;
237
+ min-height: 1.5em;
238
  }
239
+
240
+ .btn {
241
+ width: 100%;
242
+ padding: 16px;
243
+ background: var(--primary-gradient);
244
  border: none;
245
+ border-radius: 12px;
246
+ color: white;
247
  font-size: 1.1rem;
248
  font-weight: 600;
249
+ cursor: pointer;
250
  transition: all 0.3s ease;
251
  display: flex;
 
252
  align-items: center;
253
+ justify-content: center;
254
  gap: 10px;
255
  box-shadow: 0 4px 15px rgba(0,0,0,0.2);
256
+ position: relative;
257
+ overflow: hidden;
258
+ }
259
+
260
+ .btn::before {
261
+ content: '';
262
+ position: absolute;
263
+ top: 0;
264
+ left: -100%;
265
+ width: 100%;
266
+ height: 100%;
267
+ background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
268
+ transition: left 0.5s;
269
  }
270
+
271
+ .btn:hover:not(:disabled) {
272
+ transform: translateY(-2px);
273
  box-shadow: 0 6px 20px rgba(0,0,0,0.3);
274
  }
275
+
276
+ .btn:hover:not(:disabled)::before {
277
+ left: 100%;
278
+ }
279
+
280
+ .btn:disabled {
281
+ background: rgba(255, 255, 255, 0.1);
282
  cursor: not-allowed;
283
+ transform: none;
284
+ }
285
+
286
+ .btn-secondary {
287
+ background: var(--success-gradient);
288
  }
289
 
290
+ .result-container {
291
+ margin-top: 20px;
292
  padding: 20px;
293
  background: var(--input-bg);
294
+ border-radius: 12px;
295
+ min-height: 120px;
 
296
  display: flex;
 
297
  align-items: center;
298
+ justify-content: center;
299
  text-align: center;
300
+ position: relative;
301
+ backdrop-filter: blur(10px);
 
302
  }
303
+
304
+ .result-container img {
305
  max-width: 100%;
306
  height: auto;
307
  border-radius: 8px;
308
+ box-shadow: 0 4px 15px rgba(0,0,0,0.3);
309
+ animation: zoomIn 0.5s ease-out;
310
+ }
311
+
312
+ .result-text {
313
+ word-wrap: break-word;
314
+ line-height: 1.6;
315
+ color: var(--text-primary);
316
  }
317
 
318
  .loader {
319
+ width: 40px;
320
+ height: 40px;
321
+ border: 4px solid rgba(255, 255, 255, 0.1);
322
+ border-top: 4px solid #667eea;
323
  border-radius: 50%;
 
 
324
  animation: spin 1s linear infinite;
 
325
  }
326
 
327
  @keyframes spin {
328
  0% { transform: rotate(0deg); }
329
  100% { transform: rotate(360deg); }
330
  }
331
+
332
+ @keyframes zoomIn {
333
+ from {
334
+ opacity: 0;
335
+ transform: scale(0.5);
336
+ }
337
+ to {
338
+ opacity: 1;
339
+ transform: scale(1);
340
+ }
341
+ }
342
+
343
+ .floating-elements {
344
+ position: fixed;
345
+ top: 0;
346
+ left: 0;
347
+ width: 100%;
348
+ height: 100%;
349
+ pointer-events: none;
350
+ z-index: -1;
351
+ }
352
+
353
+ .floating-qr {
354
+ position: absolute;
355
+ width: 20px;
356
+ height: 20px;
357
+ background: rgba(255, 255, 255, 0.05);
358
+ animation: float-qr 15s infinite linear;
359
+ }
360
+
361
+ .floating-qr:nth-child(1) { top: 20%; left: 10%; animation-delay: 0s; }
362
+ .floating-qr:nth-child(2) { top: 80%; left: 90%; animation-delay: 5s; }
363
+ .floating-qr:nth-child(3) { top: 40%; left: 80%; animation-delay: 10s; }
364
+
365
+ @keyframes float-qr {
366
+ 0% { transform: translateY(0) rotate(0deg); opacity: 0; }
367
+ 50% { opacity: 1; }
368
+ 100% { transform: translateY(-100vh) rotate(360deg); opacity: 0; }
369
+ }
370
+
371
+ /* Mobile optimizations */
372
+ @media (max-width: 480px) {
373
+ .header {
374
+ padding: 30px 15px;
375
+ }
376
+
377
+ .card {
378
+ padding: 20px;
379
+ border-radius: 15px;
380
+ }
381
+
382
+ .main-container {
383
+ padding: 0 15px;
384
+ }
385
  }
386
  </style>
387
  </head>
388
  <body>
389
+ <div class="floating-elements">
390
+ <div class="floating-qr"></div>
391
+ <div class="floating-qr"></div>
392
+ <div class="floating-qr"></div>
 
 
 
 
 
 
 
 
 
 
 
 
393
  </div>
394
 
395
+ <header class="header">
396
+ <h1 class="main-title">ابزار مدرن <span>QR Code</span></h1>
397
+ <p class="subtitle">ساخت و خواندن کیوآر کد به سادگی</p>
398
+ </header>
399
+
400
+ <div class="main-container">
401
+ <!-- کارت ساخت QR Code -->
402
+ <div class="card">
403
+ <div class="card-header">
404
+ <div class="card-icon">
405
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
406
+ <rect x="3" y="3" width="7" height="7"/>
407
+ <rect x="14" y="3" width="7" height="7"/>
408
+ <rect x="14" y="14" width="7" height="7"/>
409
+ <rect x="3" y="14" width="7" height="7"/>
410
+ <rect x="5" y="5" width="3" height="3"/>
411
+ <rect x="16" y="5" width="3" height="3"/>
412
+ <rect x="16" y="16" width="3" height="3"/>
413
+ <rect x="5" y="16" width="3" height="3"/>
414
+ </svg>
415
+ </div>
416
+ <h2 class="card-title">ساخت QR Code</h2>
417
+ </div>
418
+
419
+ <div class="form-group">
420
+ <label for="text-input" class="form-label">متن یا لینک خود را وارد کنید:</label>
421
+ <textarea id="text-input" class="form-input" rows="4" placeholder="مثال: https://google.com یا متن دلخواه">سلام دنیا</textarea>
422
+ </div>
423
+
424
+ <button id="generate-btn" class="btn">
425
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
426
+ <polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/>
427
+ </svg>
428
+ <span>ساخت QR Code</span>
429
+ </button>
430
+
431
+ <div class="result-container">
432
+ <div id="generate-loader" class="loader" style="display: none;"></div>
433
+ <div id="qr-code-display"></div>
434
+ </div>
435
  </div>
436
+
437
+ <!-- کارت خواندن QR Code -->
438
+ <div class="card">
439
+ <div class="card-header">
440
+ <div class="card-icon">
441
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
442
+ <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/>
443
+ <circle cx="12" cy="12" r="3"/>
444
+ </svg>
445
+ </div>
446
+ <h2 class="card-title">خواندن QR Code</h2>
447
+ </div>
448
+
449
+ <div class="form-group">
450
+ <label for="file-input" class="form-label">تصویر QR Code را انتخاب کنید:</label>
451
+ <div class="file-input-wrapper">
452
+ <input type="file" id="file-input" class="file-input" accept="image/*">
453
+ <label for="file-input" class="file-input-label">
454
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
455
+ <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
456
+ <polyline points="17 8 12 3 7 8"/>
457
+ <line x1="12" y1="3" x2="12" y2="15"/>
458
+ </svg>
459
+ <span>انتخاب فایل تصویر</span>
460
+ </label>
461
+ </div>
462
+ <div id="file-name" class="file-name"></div>
463
+ </div>
464
+
465
+ <button id="read-btn" class="btn btn-secondary">
466
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
467
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
468
+ <polyline points="14,2 14,8 20,8"/>
469
+ <line x1="16" y1="13" x2="8" y2="13"/>
470
+ <line x1="16" y1="17" x2="8" y2="17"/>
471
+ <polyline points="10,9 9,9 8,9"/>
472
+ </svg>
473
+ <span>خواندن QR Code</span>
474
+ </button>
475
+
476
+ <div class="result-container">
477
+ <div id="read-loader" class="loader" style="display: none;"></div>
478
+ <div id="decoded-text" class="result-text">نتیجه در اینجا نمایش داده می‌شود</div>
479
+ </div>
480
  </div>
481
  </div>
482
 
483
  <script>
 
 
484
  const SPACE_URL = "https://cultrix-qrcode-read-generate.hf.space";
485
 
486
+ // دریافت عناصر DOM
487
  const generateBtn = document.getElementById('generate-btn');
488
  const readBtn = document.getElementById('read-btn');
489
  const textInput = document.getElementById('text-input');
 
497
  // نمایش نام فایل انتخاب شده
498
  fileInput.addEventListener('change', () => {
499
  if (fileInput.files.length > 0) {
500
+ fileNameDisplay.textContent = `✓ ${fileInput.files[0].name}`;
501
+ fileNameDisplay.style.color = '#4facfe';
502
  } else {
503
  fileNameDisplay.textContent = '';
504
  }
505
  });
506
 
507
+ // توابع کمکی
508
  const generateSessionHash = () => Math.random().toString(36).substring(2, 15);
509
 
510
  const listenForData = (sessionHash, onResult, onError) => {
 
534
  };
535
  };
536
 
537
+ // منطق ساخت QR Code
538
  generateBtn.addEventListener('click', async () => {
539
  const text = textInput.value.trim();
540
+ if (!text) {
541
+ textInput.focus();
542
+ textInput.style.borderColor = '#f5576c';
543
+ setTimeout(() => textInput.style.borderColor = 'transparent', 2000);
544
+ return;
545
+ }
546
 
547
  generateLoader.style.display = 'block';
548
  qrCodeDisplay.innerHTML = '';
 
565
  if (result && result[0]) {
566
  qrCodeDisplay.innerHTML = result[0];
567
  } else {
568
+ qrCodeDisplay.innerHTML = '<p class="result-text">خطا: خروجی معتبر دریافت نشد.</p>';
569
  }
570
  },
571
  (error) => {
572
+ qrCodeDisplay.innerHTML = `<p class="result-text">خطا در ساخت: ${error}</p>`;
 
573
  }
574
  );
575
  } catch (error) {
576
+ qrCodeDisplay.innerHTML = `<p class="result-text">خطا: ${error.message}</p>`;
577
  } finally {
578
  generateLoader.style.display = 'none';
579
  generateBtn.disabled = false;
580
  }
581
  });
582
 
583
+ // منطق خواندن QR Code
584
  readBtn.addEventListener('click', async () => {
585
  const file = fileInput.files[0];
586
+ if (!file) {
587
+ fileNameDisplay.textContent = '⚠️ لطفاً ی�� فایل انتخاب کنید';
588
+ fileNameDisplay.style.color = '#f5576c';
589
+ return;
590
+ }
591
 
592
  readLoader.style.display = 'block';
593
+ decodedText.textContent = '';
594
  readBtn.disabled = true;
595
 
596
  try {
 
623
  listenForData(
624
  sessionHash,
625
  (result) => {
626
+ decodedText.textContent = `📄 متن خوانده شده:\n\n${result[0]}`;
627
  },
628
  (error) => {
629
+ decodedText.textContent = `❌ خطا در خواندن: ${error}`;
 
630
  }
631
  );
632
  } catch (error) {
633
+ decodedText.textContent = `❌ خطا: ${error.message}`;
 
634
  } finally {
635
  readLoader.style.display = 'none';
636
  readBtn.disabled = false;
 
637
  }
638
  });
639
  </script>