Opera8 commited on
Commit
4c89546
·
verified ·
1 Parent(s): fa788e6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +173 -50
app.py CHANGED
@@ -146,7 +146,6 @@ def update_dimensions_on_upload(image):
146
  new_height = (new_height // 8) * 8
147
  return new_width, new_height
148
 
149
- # تابع به‌روزرسانی وضعیت نمایش اسلایدرها
150
  def update_sliders_visibility(choice):
151
  if choice == "شخصی‌سازی (Custom)":
152
  return gr.update(visible=True), gr.update(visible=True)
@@ -236,6 +235,8 @@ def infer(
236
  return result, seed, get_success_html("تصویر با موفقیت ویرایش شد.")
237
 
238
  except Exception as e:
 
 
239
  return None, seed, get_error_html(f"خطا در پردازش: {str(e)}")
240
 
241
  @spaces.GPU(duration=30)
@@ -243,27 +244,78 @@ def infer_example(input_image, prompt, lora_adapter):
243
  res, s, status = infer(input_image, prompt, lora_adapter, 0, True, 1.0, 4, "خودکار (پیش‌فرض)", 1024, 1024)
244
  return res, s, status
245
 
246
- # --- جاوااسکریپت ---
247
- js_post_message = """
248
- async (image) => {
249
- if (!image) {
250
- alert("لطفاً ابتدا تصویر را تولید کنید.");
251
- return;
 
 
 
 
252
  }
253
- let fileUrl = image.url;
254
- if (fileUrl && !fileUrl.startsWith('http')) {
255
- fileUrl = window.location.origin + fileUrl;
256
- } else if (!fileUrl && image.path) {
257
- fileUrl = window.location.origin + "/file=" + image.path;
 
 
 
 
 
258
  }
259
- console.log("Sending download request for:", fileUrl);
260
- window.parent.postMessage({
261
- type: 'DOWNLOAD_REQUEST',
262
- url: fileUrl
263
- }, '*');
264
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
265
  """
266
 
 
267
  html_code = """
268
  <style>
269
  @import url('https://fonts.googleapis.com/css2?family=Vazirmatn:wght@300;400;500;700&display=swap');
@@ -288,6 +340,75 @@ body {
288
  padding: 10px;
289
  }
290
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
291
  #col-container {
292
  margin: 0 auto;
293
  max-width: 980px;
@@ -366,10 +487,6 @@ textarea:focus, input[type="text"]:focus {
366
  box-shadow: 0 8px 25px rgba(16, 185, 129, 0.45) !important;
367
  }
368
 
369
- .primary-btn:active, button.primary:active {
370
- transform: translateY(1px);
371
- }
372
-
373
  #download-btn {
374
  background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%) !important;
375
  box-shadow: 0 4px 15px rgba(59, 130, 246, 0.3) !important;
@@ -413,11 +530,6 @@ textarea:focus, input[type="text"]:focus {
413
  padding: 10px !important;
414
  }
415
 
416
- .gradio-container tbody td span,
417
- .gradio-container tbody td p {
418
- color: #374151 !important;
419
- }
420
-
421
  footer { display: none !important; }
422
  .flagging { display: none !important; }
423
 
@@ -428,27 +540,27 @@ footer { display: none !important; }
428
  }
429
  }
430
  </style>
 
431
 
432
- <script>
433
- function forceLightMode() {
434
- const body = document.querySelector('body');
435
- if (body) {
436
- body.classList.remove('dark');
437
- body.style.backgroundColor = '#f5f7fa';
438
- body.style.color = '#333333';
439
- }
440
- document.querySelectorAll('.dark').forEach(el => {
441
- el.classList.remove('dark');
442
- });
443
- }
444
- forceLightMode();
445
- setInterval(forceLightMode, 1000);
446
- document.addEventListener('DOMContentLoaded', forceLightMode);
447
- </script>
448
  """
449
 
450
  with gr.Blocks() as demo:
451
- gr.HTML(html_code)
 
452
 
453
  with gr.Column(elem_id="col-container"):
454
  gr.Markdown("# **ویرایشگر هوشمند آلفا**", elem_id="main-title")
@@ -471,7 +583,6 @@ with gr.Blocks() as demo:
471
 
472
  status_box = gr.HTML(label="وضعیت")
473
 
474
- # اضافه کردن api_name="predict" برای فعال کردن حالت API
475
  run_button = gr.Button("✨ شروع پردازش و ساخت تصویر", variant="primary", elem_classes="primary-btn")
476
 
477
  with gr.Column():
@@ -494,7 +605,6 @@ with gr.Blocks() as demo:
494
  interactive=True
495
  )
496
 
497
- # اسلایدرها با visible=False شروع می‌شوند
498
  with gr.Row(visible=False) as custom_dims_row:
499
  custom_width = gr.Slider(
500
  label="عرض دلخواه (Width)",
@@ -510,7 +620,6 @@ with gr.Blocks() as demo:
510
  guidance_scale = gr.Slider(label="میزان وفاداری به متن (Guidance Scale)", minimum=1.0, maximum=10.0, step=0.1, value=1.0)
511
  steps = gr.Slider(label="تعداد مراحل پردازش (Steps)", minimum=1, maximum=50, step=1, value=4)
512
 
513
- # اصلاح منطق نمایش/مخفی کردن ردیف اسلایدرها
514
  def toggle_row(choice):
515
  if choice == "شخصی‌سازی (Custom)":
516
  return gr.update(visible=True)
@@ -519,7 +628,7 @@ with gr.Blocks() as demo:
519
  aspect_ratio_selection.change(
520
  fn=toggle_row,
521
  inputs=aspect_ratio_selection,
522
- outputs=custom_dims_row # کنترل کل ردیف به جای تک تک اسلایدرها
523
  )
524
 
525
  gr.Examples(
@@ -543,19 +652,33 @@ with gr.Blocks() as demo:
543
  label="نمونه‌ها (برای تست کلیک کنید)"
544
  )
545
 
546
- # اتصال دکمه اجرا با قابلیت API
 
 
 
 
 
 
 
 
 
 
 
 
 
 
547
  run_button.click(
548
  fn=infer,
549
  inputs=[input_image, prompt, lora_adapter, seed, randomize_seed, guidance_scale, steps, aspect_ratio_selection, custom_width, custom_height],
550
  outputs=[output_image, seed, status_box],
551
- api_name="predict" # فعال‌سازی API
552
  )
553
 
554
  download_button.click(
555
  fn=None,
556
  inputs=[output_image],
557
  outputs=None,
558
- js=js_post_message
559
  )
560
 
561
  if __name__ == "__main__":
 
146
  new_height = (new_height // 8) * 8
147
  return new_width, new_height
148
 
 
149
  def update_sliders_visibility(choice):
150
  if choice == "شخصی‌سازی (Custom)":
151
  return gr.update(visible=True), gr.update(visible=True)
 
235
  return result, seed, get_success_html("تصویر با موفقیت ویرایش شد.")
236
 
237
  except Exception as e:
238
+ # اگر خطا مربوط به Quota باشد، اینجا هندل نمی‌شود چون از سمت سرور می‌آید.
239
+ # اما خطاهای پایتونی را هندل می‌کند.
240
  return None, seed, get_error_html(f"خطا در پردازش: {str(e)}")
241
 
242
  @spaces.GPU(duration=30)
 
244
  res, s, status = infer(input_image, prompt, lora_adapter, 0, True, 1.0, 4, "خودکار (پیش‌فرض)", 1024, 1024)
245
  return res, s, status
246
 
247
+ # --- جاوااسکریپت (PostMessage + Quota Handler) ---
248
+ js_code = """
249
+ <script>
250
+ // 1. تابع فورس کردن لایت مود
251
+ function forceLightMode() {
252
+ const body = document.querySelector('body');
253
+ if (body) {
254
+ body.classList.remove('dark');
255
+ body.style.backgroundColor = '#f5f7fa';
256
+ body.style.color = '#333333';
257
  }
258
+ document.querySelectorAll('.dark').forEach(el => {
259
+ el.classList.remove('dark');
260
+ });
261
+ }
262
+
263
+ // 2. تابع بستن مودال خطای Quota
264
+ function closeQuotaModal() {
265
+ const modal = document.getElementById('custom-quota-modal');
266
+ if (modal) {
267
+ modal.style.display = 'none';
268
  }
 
 
 
 
 
269
  }
270
+
271
+ // 3. آبزرور برای شکار خطای GPU Quota
272
+ const observer = new MutationObserver((mutations) => {
273
+ mutations.forEach((mutation) => {
274
+ // بررسی متن‌های اضافه شده
275
+ if (mutation.type === 'childList') {
276
+ mutation.addedNodes.forEach((node) => {
277
+ if (node.nodeType === 1) { // Element node
278
+ const text = node.innerText || node.textContent;
279
+ if (text && text.includes('exceeded your GPU quota')) {
280
+ // مخفی کردن پیغام اصلی
281
+ node.style.display = 'none';
282
+ node.style.visibility = 'hidden';
283
+
284
+ // نمایش مودال سفارشی
285
+ const modal = document.getElementById('custom-quota-modal');
286
+ if (modal) modal.style.display = 'flex';
287
+ }
288
+ }
289
+ });
290
+ }
291
+ });
292
+
293
+ // بررسی پیغام‌های موجود در toast-wrap (روش دوم برای اطمینان)
294
+ const toasts = document.querySelectorAll('.toast-wrap');
295
+ toasts.forEach(toast => {
296
+ if (toast.innerText.includes('exceeded your GPU quota') && toast.style.display !== 'none') {
297
+ toast.style.display = 'none';
298
+ const modal = document.getElementById('custom-quota-modal');
299
+ if (modal) modal.style.display = 'flex';
300
+ }
301
+ });
302
+ });
303
+
304
+ document.addEventListener('DOMContentLoaded', () => {
305
+ forceLightMode();
306
+ setInterval(forceLightMode, 1000);
307
+
308
+ // شروع مانیتور کردن بادی برای خطاها
309
+ observer.observe(document.body, {
310
+ childList: true,
311
+ subtree: true,
312
+ characterData: true
313
+ });
314
+ });
315
+ </script>
316
  """
317
 
318
+ # --- تنظیمات HTML و CSS ---
319
  html_code = """
320
  <style>
321
  @import url('https://fonts.googleapis.com/css2?family=Vazirmatn:wght@300;400;500;700&display=swap');
 
340
  padding: 10px;
341
  }
342
 
343
+ /* استایل مودال خطای سفارشی */
344
+ #custom-quota-modal {
345
+ position: fixed;
346
+ top: 0;
347
+ left: 0;
348
+ width: 100%;
349
+ height: 100%;
350
+ background-color: rgba(0, 0, 0, 0.7);
351
+ backdrop-filter: blur(5px);
352
+ z-index: 99999;
353
+ display: none; /* پیش‌فرض مخفی */
354
+ justify-content: center;
355
+ align-items: center;
356
+ direction: rtl;
357
+ }
358
+
359
+ .quota-modal-content {
360
+ background-color: white;
361
+ padding: 30px;
362
+ border-radius: 20px;
363
+ width: 90%;
364
+ max-width: 400px;
365
+ text-align: center;
366
+ box-shadow: 0 10px 25px rgba(0,0,0,0.2);
367
+ animation: fadeIn 0.3s ease-out;
368
+ }
369
+
370
+ .quota-icon {
371
+ font-size: 60px;
372
+ margin-bottom: 20px;
373
+ display: block;
374
+ }
375
+
376
+ .quota-title {
377
+ font-size: 1.4em;
378
+ font-weight: 800;
379
+ color: #e11d48;
380
+ margin-bottom: 15px;
381
+ }
382
+
383
+ .quota-text {
384
+ font-size: 1.1em;
385
+ color: #4b5563;
386
+ line-height: 1.6;
387
+ margin-bottom: 25px;
388
+ }
389
+
390
+ .quota-btn {
391
+ background: linear-gradient(135deg, #e11d48 0%, #be123c 100%);
392
+ color: white;
393
+ border: none;
394
+ padding: 12px 30px;
395
+ border-radius: 12px;
396
+ font-weight: bold;
397
+ font-family: 'Vazirmatn', sans-serif;
398
+ font-size: 1em;
399
+ cursor: pointer;
400
+ transition: transform 0.2s;
401
+ }
402
+
403
+ .quota-btn:hover {
404
+ transform: scale(1.05);
405
+ }
406
+
407
+ @keyframes fadeIn {
408
+ from { opacity: 0; transform: translateY(-20px); }
409
+ to { opacity: 1; transform: translateY(0); }
410
+ }
411
+
412
  #col-container {
413
  margin: 0 auto;
414
  max-width: 980px;
 
487
  box-shadow: 0 8px 25px rgba(16, 185, 129, 0.45) !important;
488
  }
489
 
 
 
 
 
490
  #download-btn {
491
  background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%) !important;
492
  box-shadow: 0 4px 15px rgba(59, 130, 246, 0.3) !important;
 
530
  padding: 10px !important;
531
  }
532
 
 
 
 
 
 
533
  footer { display: none !important; }
534
  .flagging { display: none !important; }
535
 
 
540
  }
541
  }
542
  </style>
543
+ """
544
 
545
+ # ساختار HTML برای مودال سفارشی
546
+ modal_html = """
547
+ <div id="custom-quota-modal">
548
+ <div class="quota-modal-content">
549
+ <span class="quota-icon">✈️</span>
550
+ <div class="quota-title">محدودیت استفاده</div>
551
+ <div class="quota-text">
552
+ سهمیه استفاده از گرافیک پر شده است.
553
+ <br><br>
554
+ لطفاً <b>حالت هواپیما (Airplane Mode)</b> گوشی خود را یکبار روشن و خاموش کنید تا IP تغییر کند و سپس مجدد تلاش کنید.
555
+ </div>
556
+ <button class="quota-btn" onclick="closeQuotaModal()">متوجه شدم</button>
557
+ </div>
558
+ </div>
 
 
559
  """
560
 
561
  with gr.Blocks() as demo:
562
+ # تزریق HTML و JS
563
+ gr.HTML(html_code + js_code + modal_html)
564
 
565
  with gr.Column(elem_id="col-container"):
566
  gr.Markdown("# **ویرایشگر هوشمند آلفا**", elem_id="main-title")
 
583
 
584
  status_box = gr.HTML(label="وضعیت")
585
 
 
586
  run_button = gr.Button("✨ شروع پردازش و ساخت تصویر", variant="primary", elem_classes="primary-btn")
587
 
588
  with gr.Column():
 
605
  interactive=True
606
  )
607
 
 
608
  with gr.Row(visible=False) as custom_dims_row:
609
  custom_width = gr.Slider(
610
  label="عرض دلخواه (Width)",
 
620
  guidance_scale = gr.Slider(label="میزان وفاداری به متن (Guidance Scale)", minimum=1.0, maximum=10.0, step=0.1, value=1.0)
621
  steps = gr.Slider(label="تعداد مراحل پردازش (Steps)", minimum=1, maximum=50, step=1, value=4)
622
 
 
623
  def toggle_row(choice):
624
  if choice == "شخصی‌سازی (Custom)":
625
  return gr.update(visible=True)
 
628
  aspect_ratio_selection.change(
629
  fn=toggle_row,
630
  inputs=aspect_ratio_selection,
631
+ outputs=custom_dims_row
632
  )
633
 
634
  gr.Examples(
 
652
  label="نمونه‌ها (برای تست کلیک کنید)"
653
  )
654
 
655
+ # جاوااسکریپت دانلود
656
+ js_dl = """
657
+ async (image) => {
658
+ if (!image) { alert("لطف��ً ابتدا تصویر را تولید کنید."); return; }
659
+ let fileUrl = image.url;
660
+ if (fileUrl && !fileUrl.startsWith('http')) {
661
+ fileUrl = window.location.origin + fileUrl;
662
+ } else if (!fileUrl && image.path) {
663
+ fileUrl = window.location.origin + "/file=" + image.path;
664
+ }
665
+ console.log("Sending download request for:", fileUrl);
666
+ window.parent.postMessage({ type: 'DOWNLOAD_REQUEST', url: fileUrl }, '*');
667
+ }
668
+ """
669
+
670
  run_button.click(
671
  fn=infer,
672
  inputs=[input_image, prompt, lora_adapter, seed, randomize_seed, guidance_scale, steps, aspect_ratio_selection, custom_width, custom_height],
673
  outputs=[output_image, seed, status_box],
674
+ api_name="predict"
675
  )
676
 
677
  download_button.click(
678
  fn=None,
679
  inputs=[output_image],
680
  outputs=None,
681
+ js=js_dl
682
  )
683
 
684
  if __name__ == "__main__":