|
13 | 13 | M.sharedViewLock = null; // null = no lock, 'ppt' | 'preview' = locked |
14 | 14 | var readonlyClickHandlerInstalled = false; |
15 | 15 |
|
| 16 | + // --- Share-link loading overlay dismissal --- |
| 17 | + function hideShareLoader() { |
| 18 | + var overlay = document.getElementById('share-loading-overlay'); |
| 19 | + if (!overlay || !overlay.classList.contains('slo-active')) return; |
| 20 | + overlay.classList.add('slo-fade-out'); |
| 21 | + setTimeout(function () { |
| 22 | + overlay.classList.remove('slo-active', 'slo-fade-out'); |
| 23 | + }, 380); |
| 24 | + } |
| 25 | + |
16 | 26 | // --- Firebase Config --- |
17 | 27 | var firebaseConfig = { |
18 | 28 | apiKey: 'AIzaSyC_5pgtZ-mZvHmIUH9X7MkObPwDLw8nyfw', |
|
553 | 563 | // --- Space hub: #space=<slug> --- |
554 | 564 | if (spaceSlug && !compactId) { |
555 | 565 | try { |
556 | | - M.markdownPreview.innerHTML = '<div style="padding: 40px; text-align: center; opacity: 0.6;"><i class="bi bi-collection"></i> Loading Space...</div>'; |
557 | 566 | M.setViewMode('preview'); |
558 | 567 | var spaceData = await M.loadSpace(spaceSlug); |
559 | 568 | if (!spaceData) { |
| 569 | + hideShareLoader(); |
560 | 570 | M.markdownPreview.innerHTML = '<div style="padding: 60px; text-align: center;"><h2>Space Not Found</h2><p>This space may have been removed or the URL is incorrect.</p></div>'; |
561 | 571 | return; |
562 | 572 | } |
| 573 | + hideShareLoader(); |
563 | 574 | M.renderSpaceHub(spaceData, spaceSlug); |
564 | 575 | } catch (e) { |
565 | 576 | console.error('Error loading Space:', e); |
| 577 | + hideShareLoader(); |
566 | 578 | M.markdownPreview.innerHTML = '<div style="padding: 60px; text-align: center;"><h2>Error</h2><p>' + e.message + '</p></div>'; |
567 | 579 | } |
568 | 580 | return; |
|
640 | 652 |
|
641 | 653 | // Form access gate: block if form doc but no rk or m=fill (unless editor) |
642 | 654 | if (!isEditMode && /\{\{@?(?:Form|Quiz):/i.test(markdownContent) && !M.formResponseKey && !M.isFormFillMode) { |
| 655 | + hideShareLoader(); |
643 | 656 | M.markdownPreview.innerHTML = '<div style="padding: 40px; text-align: center;"><h3 style="color: var(--color-danger-fg);"><i class="bi bi-shield-lock"></i> Access Denied</h3><p style="opacity: 0.7;">This form requires a valid access link.</p><p style="font-size: 13px; opacity: 0.5;">Please use the link provided by the form creator.</p></div>'; |
644 | 657 | M.setViewMode('preview'); |
645 | 658 | return; |
|
656 | 669 | document.body.classList.remove('editor-readonly'); |
657 | 670 | lastCloudContent = markdownContent; // Prevent immediate re-save |
658 | 671 | scheduleCloudSave(); |
| 672 | + hideShareLoader(); |
659 | 673 | if (M.showToast) M.showToast('🔑 Editor access — changes will sync to this document', 'success'); |
660 | 674 | } else { |
661 | 675 | var sharedMode = M.sharedViewLock || 'preview'; |
662 | 676 | M.setViewMode(sharedMode); |
663 | 677 | M.isViewingSharedDoc = true; |
664 | 678 | showSharedBanner(); |
665 | 679 | if (sharedMode === 'preview' && M.setHeaderLevel) M.setHeaderLevel(2); |
| 680 | + hideShareLoader(); |
666 | 681 | } |
667 | 682 | } catch (error) { |
668 | 683 | console.error('Failed to load compact shared markdown:', error); |
| 684 | + hideShareLoader(); |
669 | 685 | M.markdownPreview.innerHTML = '<div style="padding: 40px; text-align: center;"><h3 style="color: var(--color-danger-fg);"><i class="bi bi-shield-exclamation"></i> Decryption Failed</h3><p style="opacity: 0.7;">The link may be invalid or the document may not exist.</p><p style="font-size: 13px; opacity: 0.5;"></p></div>'; |
670 | 686 | M.markdownPreview.querySelector('p:last-child').textContent = error.message; |
671 | 687 | M.setViewMode('split'); |
|
676 | 692 | // --- Secure share: no key in URL, passphrase needed --- |
677 | 693 | if (isSecure && docId && !keyString) { |
678 | 694 | try { |
679 | | - M.markdownPreview.innerHTML = '<div style="padding: 40px; text-align: center; opacity: 0.6;"><i class="bi bi-shield-lock"></i> Loading protected document...</div>'; |
680 | 695 | M.setViewMode('split'); |
681 | 696 | var doc = await db.collection('shares').doc(docId).get(); |
682 | 697 | if (!doc.exists) throw new Error('Shared document not found.'); |
|
686 | 701 | M.sharedViewLock = data.view; |
687 | 702 | } |
688 | 703 | pendingSecureDoc = { dataString: data.d, saltString: data.salt, docId: docId, ekHash: data.ekHash || '', eWt: data.eWt || '' }; |
| 704 | + hideShareLoader(); |
689 | 705 | showPassphrasePrompt(); |
690 | 706 | } catch (error) { |
691 | 707 | console.error('Failed to load secure shared markdown:', error); |
| 708 | + hideShareLoader(); |
692 | 709 | M.markdownPreview.innerHTML = '<div style="padding: 40px; text-align: center;"><h3 style="color: var(--color-danger-fg);"><i class="bi bi-shield-exclamation"></i> Document Not Found</h3><p style="opacity: 0.7;">The shared document may have been deleted or the link is invalid.</p></div>'; |
693 | 710 | M.setViewMode('split'); |
694 | 711 | } |
|
698 | 715 | // --- Legacy quick share: key in URL (#id=...&k=...) --- |
699 | 716 | if (!keyString || (!docId && !inlineData)) return; |
700 | 717 | try { |
701 | | - M.markdownPreview.innerHTML = '<div style="padding: 40px; text-align: center; opacity: 0.6;"><i class="bi bi-lock"></i> Decrypting shared content...</div>'; |
702 | 718 | M.setViewMode('split'); |
703 | 719 | var dataString; |
704 | 720 | if (docId) { |
|
724 | 740 | var markdownContent = decompressData(compressed); |
725 | 741 | // Form access gate: block if form doc but no rk or m=fill |
726 | 742 | if (/\{\{@?(?:Form|Quiz):/i.test(markdownContent) && !M.formResponseKey && !M.isFormFillMode) { |
| 743 | + hideShareLoader(); |
727 | 744 | M.markdownPreview.innerHTML = '<div style="padding: 40px; text-align: center;"><h3 style="color: var(--color-danger-fg);"><i class="bi bi-shield-lock"></i> Access Denied</h3><p style="opacity: 0.7;">This form requires a valid access link.</p><p style="font-size: 13px; opacity: 0.5;">Please use the link provided by the form creator.</p></div>'; |
728 | 745 | M.setViewMode('preview'); |
729 | 746 | return; |
|
737 | 754 | showSharedBanner(); |
738 | 755 | // Auto-hide full header for preview mode shared links |
739 | 756 | if (sharedMode === 'preview' && M.setHeaderLevel) M.setHeaderLevel(2); |
| 757 | + hideShareLoader(); |
740 | 758 | } catch (error) { |
741 | 759 | console.error('Failed to load shared markdown:', error); |
| 760 | + hideShareLoader(); |
742 | 761 | M.markdownPreview.innerHTML = '<div style="padding: 40px; text-align: center;"><h3 style="color: var(--color-danger-fg);"><i class="bi bi-shield-exclamation"></i> Decryption Failed</h3><p style="opacity: 0.7;">The link may be invalid or the document may not exist.</p><p style="font-size: 13px; opacity: 0.5;"></p></div>'; |
743 | 762 | M.markdownPreview.querySelector('p:last-child').textContent = error.message; |
744 | 763 | M.setViewMode('split'); |
|
0 commit comments