Eluza133 commited on
Commit
eeb63d0
·
verified ·
1 Parent(s): 81949e3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +89 -109
app.py CHANGED
@@ -317,15 +317,57 @@ USER_TEMPLATE = """
317
  background-color: var(--card-bg);
318
  padding: 12px var(--padding);
319
  border-radius: var(--border-radius);
320
- display: flex; align-items: center; justify-content: space-between;
 
321
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
322
  transition: background-color 0.2s ease;
323
  word-break: break-word;
324
  }
325
  .file-item:hover { background-color: rgba(255, 255, 255, 0.08); }
326
- .file-info { flex-grow: 1; margin-right: 10px; overflow: hidden; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
327
  .file-name { font-weight: 500; display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
328
  .file-meta { font-size: 0.8em; color: var(--tg-theme-hint-color); }
 
329
  .file-actions a, .file-actions button {
330
  display: inline-block;
331
  padding: 6px 10px;
@@ -344,33 +386,6 @@ USER_TEMPLATE = """
344
  .loading, .no-files { text-align: center; padding: 20px; color: var(--tg-theme-hint-color); }
345
  .progress-bar { width: 100%; background-color: #ddd; border-radius: 4px; height: 8px; margin-top: 5px; display: none; }
346
  .progress-bar-inner { height: 100%; width: 0%; background-color: var(--tg-theme-button-color); border-radius: 4px; transition: width 0.1s linear; }
347
- .modal {
348
- display: none; position: fixed; z-index: 1001;
349
- left: 0; top: 0; width: 100%; height: 100%;
350
- overflow: auto; background-color: rgba(0,0,0,0.8);
351
- backdrop-filter: blur(5px); -webkit-backdrop-filter: blur(5px);
352
- animation: fadeIn 0.3s ease-out;
353
- }
354
- @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
355
- .modal-content {
356
- margin: auto; display: block; max-width: 90%; max-height: 85%;
357
- position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
358
- }
359
- .modal-content img, .modal-content video, .modal-content audio {
360
- display: block; width: auto; height: auto; max-width: 100%; max-height: 100%; margin: auto;
361
- background-color: var(--tg-theme-bg-color);
362
- }
363
- .modal-close {
364
- position: absolute; top: 15px; right: 35px; color: #f1f1f1; font-size: 40px;
365
- font-weight: bold; transition: 0.3s; cursor: pointer; z-index: 1002;
366
- text-shadow: 0 1px 3px rgba(0,0,0,0.5);
367
- }
368
- .modal-close:hover, .modal-close:focus { color: #bbb; text-decoration: none; }
369
- .modal-caption {
370
- margin: auto; display: block; width: 80%; max-width: 700px; text-align: center;
371
- color: #ccc; padding: 10px 0; height: 50px; position: absolute; bottom: 15px; left: 50%; transform: translateX(-50%);
372
- background: rgba(0,0,0,0.5); border-radius: 8px;
373
- }
374
  .spinner {
375
  border: 4px solid rgba(255, 255, 255, 0.3);
376
  border-radius: 50%;
@@ -407,12 +422,6 @@ USER_TEMPLATE = """
407
  </ul>
408
  </section>
409
  </div>
410
- <div id="viewerModal" class="modal">
411
- <span class="modal-close" id="modalCloseBtn">×</span>
412
- <div id="modalContent" class="modal-content">
413
- </div>
414
- <div id="modalCaption" class="modal-caption"></div>
415
- </div>
416
  <script>
417
  const tg = window.Telegram.WebApp;
418
  const MAX_FILES = {{ max_files }};
@@ -428,10 +437,6 @@ USER_TEMPLATE = """
428
  const loadingSpinner = document.getElementById('loading-spinner');
429
  const progressBar = document.getElementById('progress-bar');
430
  const progressBarInner = document.getElementById('progress-bar-inner');
431
- const modal = document.getElementById('viewerModal');
432
- const modalContent = document.getElementById('modalContent');
433
- const modalCaption = document.getElementById('modalCaption');
434
- const modalCloseBtn = document.getElementById('modalCloseBtn');
435
 
436
  function applyTheme(themeParams) {
437
  const root = document.documentElement;
@@ -470,9 +475,45 @@ USER_TEMPLATE = """
470
  }
471
  noFilesMessage.style.display = 'none';
472
  files.sort((a, b) => b.uploaded_at_ts - a.uploaded_at_ts);
 
473
  files.forEach(file => {
474
  const li = document.createElement('li');
475
  li.classList.add('file-item');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
476
  const fileInfoDiv = document.createElement('div');
477
  fileInfoDiv.classList.add('file-info');
478
  const fileNameSpan = document.createElement('span');
@@ -485,31 +526,18 @@ USER_TEMPLATE = """
485
  const size = file.size ? formatBytes(file.size) : '';
486
  fileMetaSpan.textContent = `${date}${size ? ' - ' + size : ''}`;
487
  fileInfoDiv.appendChild(fileMetaSpan);
 
 
488
  const fileActionsDiv = document.createElement('div');
489
  fileActionsDiv.classList.add('file-actions');
490
- const mimeType = file.content_type || '';
491
- if (mimeType.startsWith('image/') || mimeType.startsWith('video/') || mimeType.startsWith('audio/')) {
492
- const viewButton = document.createElement('button');
493
- viewButton.textContent = '👁️';
494
- viewButton.classList.add('view-btn');
495
- viewButton.style.backgroundColor = '#6f42c1';
496
- viewButton.style.color = 'white';
497
- viewButton.title = 'Просмотр';
498
- viewButton.onclick = (e) => {
499
- e.stopPropagation();
500
- openViewer(file);
501
- };
502
- fileActionsDiv.appendChild(viewButton);
503
- }
504
  const downloadLink = document.createElement('a');
505
  downloadLink.classList.add('download-btn');
506
  downloadLink.textContent = 'Скачать';
507
- downloadLink.href = `/download/${encodeURIComponent(file.filename)}?initData=${encodeURIComponent(userInitData)}`;
508
- downloadLink.target = '_blank';
509
  downloadLink.title = 'Скачать файл';
510
  downloadLink.onclick = (e) => e.stopPropagation();
511
  fileActionsDiv.appendChild(downloadLink);
512
- li.appendChild(fileInfoDiv);
513
  li.appendChild(fileActionsDiv);
514
  fileListUl.appendChild(li);
515
  });
@@ -620,67 +648,19 @@ USER_TEMPLATE = """
620
  uploadStatusDiv.style.color = 'red';
621
  } finally {
622
  progressBar.style.display = 'none';
623
- if (currentFiles.length > 0) {
624
  uploadButton.classList.add('enabled');
625
  uploadButton.disabled = false;
626
- } else {
627
  uploadButton.classList.remove('enabled');
628
  uploadButton.disabled = true;
629
- selectedFilesDiv.textContent = 'Файлы не выбраны';
 
 
630
  }
631
  }
632
  }
633
 
634
- function openViewer(file) {
635
- modal.style.display = 'block';
636
- modalContent.innerHTML = '';
637
- modalCaption.textContent = file.filename;
638
- const mimeType = file.content_type || '';
639
- const downloadUrl = `/download/${encodeURIComponent(file.filename)}?initData=${encodeURIComponent(userInitData)}`;
640
- let element;
641
- if (mimeType.startsWith('image/')) {
642
- element = document.createElement('img');
643
- element.src = downloadUrl;
644
- element.alt = file.filename;
645
- } else if (mimeType.startsWith('video/')) {
646
- element = document.createElement('video');
647
- element.src = downloadUrl;
648
- element.controls = true;
649
- element.autoplay = true;
650
- } else if (mimeType.startsWith('audio/')) {
651
- element = document.createElement('audio');
652
- element.src = downloadUrl;
653
- element.controls = true;
654
- element.autoplay = true;
655
- element.style.padding = '20px';
656
- }
657
- if (element) {
658
- modalContent.appendChild(element);
659
- if (tg.HapticFeedback) {
660
- tg.HapticFeedback.impactOccurred('light');
661
- }
662
- } else {
663
- modalCaption.textContent = 'Предпросмотр недоступен для этого типа файла.';
664
- }
665
- }
666
-
667
- function closeViewer() {
668
- modal.style.display = 'none';
669
- const mediaElement = modalContent.querySelector('video, audio');
670
- if (mediaElement) {
671
- mediaElement.pause();
672
- mediaElement.src = '';
673
- }
674
- modalContent.innerHTML = '';
675
- }
676
-
677
- modalCloseBtn.onclick = closeViewer;
678
- modal.onclick = function(event) {
679
- if (event.target === modal) {
680
- closeViewer();
681
- }
682
- };
683
-
684
  function setupTelegram() {
685
  if (!tg || !tg.initData) {
686
  console.error("Telegram WebApp script not loaded or initData is missing.");
 
317
  background-color: var(--card-bg);
318
  padding: 12px var(--padding);
319
  border-radius: var(--border-radius);
320
+ display: flex;
321
+ align-items: center;
322
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
323
  transition: background-color 0.2s ease;
324
  word-break: break-word;
325
  }
326
  .file-item:hover { background-color: rgba(255, 255, 255, 0.08); }
327
+
328
+ .file-preview-area {
329
+ flex-shrink: 0;
330
+ width: 80px;
331
+ height: 80px;
332
+ margin-right: var(--padding);
333
+ display: flex;
334
+ align-items: center;
335
+ justify-content: center;
336
+ background-color: rgba(0,0,0,0.05);
337
+ border-radius: 8px;
338
+ overflow: hidden;
339
+ }
340
+ .file-preview-image,
341
+ .file-preview-video {
342
+ max-width: 100%;
343
+ max-height: 100%;
344
+ object-fit: cover;
345
+ display: block;
346
+ }
347
+ .file-preview-video {
348
+ width: 100%;
349
+ height: 100%;
350
+ }
351
+ .file-preview-audio {
352
+ width: 100%;
353
+ transform: scale(0.85);
354
+ transform-origin: center;
355
+ }
356
+ .file-preview-icon {
357
+ font-size: 0.8em;
358
+ font-weight: bold;
359
+ color: var(--tg-theme-hint-color);
360
+ padding: 5px;
361
+ text-align: center;
362
+ text-transform: uppercase;
363
+ word-break: break-all;
364
+ line-height: 1.2;
365
+ }
366
+
367
+ .file-info { flex-grow: 1; margin-right: 10px; overflow: hidden; min-width: 0;}
368
  .file-name { font-weight: 500; display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
369
  .file-meta { font-size: 0.8em; color: var(--tg-theme-hint-color); }
370
+ .file-actions { flex-shrink: 0; }
371
  .file-actions a, .file-actions button {
372
  display: inline-block;
373
  padding: 6px 10px;
 
386
  .loading, .no-files { text-align: center; padding: 20px; color: var(--tg-theme-hint-color); }
387
  .progress-bar { width: 100%; background-color: #ddd; border-radius: 4px; height: 8px; margin-top: 5px; display: none; }
388
  .progress-bar-inner { height: 100%; width: 0%; background-color: var(--tg-theme-button-color); border-radius: 4px; transition: width 0.1s linear; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
389
  .spinner {
390
  border: 4px solid rgba(255, 255, 255, 0.3);
391
  border-radius: 50%;
 
422
  </ul>
423
  </section>
424
  </div>
 
 
 
 
 
 
425
  <script>
426
  const tg = window.Telegram.WebApp;
427
  const MAX_FILES = {{ max_files }};
 
437
  const loadingSpinner = document.getElementById('loading-spinner');
438
  const progressBar = document.getElementById('progress-bar');
439
  const progressBarInner = document.getElementById('progress-bar-inner');
 
 
 
 
440
 
441
  function applyTheme(themeParams) {
442
  const root = document.documentElement;
 
475
  }
476
  noFilesMessage.style.display = 'none';
477
  files.sort((a, b) => b.uploaded_at_ts - a.uploaded_at_ts);
478
+
479
  files.forEach(file => {
480
  const li = document.createElement('li');
481
  li.classList.add('file-item');
482
+
483
+ const previewDiv = document.createElement('div');
484
+ previewDiv.classList.add('file-preview-area');
485
+ const downloadUrl = `/download/${encodeURIComponent(file.filename)}?initData=${encodeURIComponent(userInitData)}`;
486
+ const mimeType = file.content_type || '';
487
+
488
+ if (mimeType.startsWith('image/')) {
489
+ const img = document.createElement('img');
490
+ img.src = downloadUrl;
491
+ img.alt = file.filename;
492
+ img.classList.add('file-preview-image');
493
+ previewDiv.appendChild(img);
494
+ } else if (mimeType.startsWith('video/')) {
495
+ const video = document.createElement('video');
496
+ video.src = downloadUrl;
497
+ video.controls = true;
498
+ video.classList.add('file-preview-video');
499
+ video.preload = "metadata";
500
+ previewDiv.appendChild(video);
501
+ } else if (mimeType.startsWith('audio/')) {
502
+ const audio = document.createElement('audio');
503
+ audio.src = downloadUrl;
504
+ audio.controls = true;
505
+ audio.classList.add('file-preview-audio');
506
+ audio.preload = "metadata";
507
+ previewDiv.appendChild(audio);
508
+ } else {
509
+ const iconPlaceholder = document.createElement('div');
510
+ iconPlaceholder.classList.add('file-preview-icon');
511
+ const ext = file.filename.split('.').pop().toLowerCase() || 'file';
512
+ iconPlaceholder.textContent = ext.substring(0,4);
513
+ previewDiv.appendChild(iconPlaceholder);
514
+ }
515
+ li.appendChild(previewDiv);
516
+
517
  const fileInfoDiv = document.createElement('div');
518
  fileInfoDiv.classList.add('file-info');
519
  const fileNameSpan = document.createElement('span');
 
526
  const size = file.size ? formatBytes(file.size) : '';
527
  fileMetaSpan.textContent = `${date}${size ? ' - ' + size : ''}`;
528
  fileInfoDiv.appendChild(fileMetaSpan);
529
+ li.appendChild(fileInfoDiv);
530
+
531
  const fileActionsDiv = document.createElement('div');
532
  fileActionsDiv.classList.add('file-actions');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
533
  const downloadLink = document.createElement('a');
534
  downloadLink.classList.add('download-btn');
535
  downloadLink.textContent = 'Скачать';
536
+ downloadLink.href = downloadUrl;
537
+ downloadLink.setAttribute('download', file.filename);
538
  downloadLink.title = 'Скачать файл';
539
  downloadLink.onclick = (e) => e.stopPropagation();
540
  fileActionsDiv.appendChild(downloadLink);
 
541
  li.appendChild(fileActionsDiv);
542
  fileListUl.appendChild(li);
543
  });
 
648
  uploadStatusDiv.style.color = 'red';
649
  } finally {
650
  progressBar.style.display = 'none';
651
+ if (currentFiles.length > 0 && fileInput.files.length > 0) { // Check also fileInput as currentFiles might not be reset on some errors
652
  uploadButton.classList.add('enabled');
653
  uploadButton.disabled = false;
654
+ } else { // Default to disabled if no files or error
655
  uploadButton.classList.remove('enabled');
656
  uploadButton.disabled = true;
657
+ selectedFilesDiv.textContent = 'Файлы не выбраны'; // Ensure this is accurate
658
+ fileInput.value = ''; // Clear file input on final step
659
+ currentFiles = [];
660
  }
661
  }
662
  }
663
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
664
  function setupTelegram() {
665
  if (!tg || !tg.initData) {
666
  console.error("Telegram WebApp script not loaded or initData is missing.");