From 1aa4c5e6ae214d7f99294dda0327d738e70efe0a Mon Sep 17 00:00:00 2001 From: chark1es Date: Mon, 3 Feb 2025 04:20:31 -0800 Subject: [PATCH] new file previewer modal old one is reusing the component, making lots of bugs appear --- src/components/modals/FileViewerModal.tsx | 379 ++++++++++++++++++ .../profile/DefaultProfileView.astro | 222 ++++------ 2 files changed, 446 insertions(+), 155 deletions(-) create mode 100644 src/components/modals/FileViewerModal.tsx diff --git a/src/components/modals/FileViewerModal.tsx b/src/components/modals/FileViewerModal.tsx new file mode 100644 index 0000000..b5c0fa2 --- /dev/null +++ b/src/components/modals/FileViewerModal.tsx @@ -0,0 +1,379 @@ +import React, { useState, useEffect } from 'react'; + +interface FileType { + url: string; + type: string; + name: string; +} + +interface FileViewerModalProps { + isOpen: boolean; + onClose: () => void; + files: FileType | FileType[]; + modalId?: string; +} + +// Create a wrapper component that listens to custom events +export const FileViewerModalWrapper: React.FC = () => { + const [isOpen, setIsOpen] = useState(false); + const [files, setFiles] = useState([]); + + useEffect(() => { + // Listen for custom events to open/close modal and set files + const handleShowFiles = (event: CustomEvent) => { + const { files } = event.detail; + setFiles(Array.isArray(files) ? files : [files]); + setIsOpen(true); + }; + + // Add event listeners + window.addEventListener('showFileViewer' as any, handleShowFiles); + + // Cleanup + return () => { + window.removeEventListener('showFileViewer' as any, handleShowFiles); + }; + }, []); + + const handleClose = () => { + setIsOpen(false); + }; + + return ( + + ); +}; + +const FileViewerModal: React.FC = ({ isOpen, onClose, files, modalId = 'file-viewer' }) => { + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + const [selectedFile, setSelectedFile] = useState(null); + const [showPreview, setShowPreview] = useState(false); + + const fileArray = Array.isArray(files) ? files : [files]; + + // Helper function to check if file type is previewable + const isPreviewableType = (fileType: string): boolean => { + return ( + fileType.startsWith('image/') || + fileType.startsWith('video/') || + fileType.startsWith('audio/') || + fileType === 'application/pdf' || + fileType.startsWith('text/') || + fileType === 'application/json' + ); + }; + + useEffect(() => { + if (isOpen) { + // Only set loading if the file is previewable + if (selectedFile && isPreviewableType(selectedFile.type)) { + setLoading(true); + } else { + setLoading(false); + } + setError(null); + // If single file, show preview directly + if (!Array.isArray(files)) { + setSelectedFile(files); + setShowPreview(true); + } else { + setShowPreview(false); + setSelectedFile(null); + } + } + }, [isOpen, files]); + + const handleLoadSuccess = () => { + setLoading(false); + }; + + const handleLoadError = () => { + setLoading(false); + setError('Failed to load file'); + }; + + const handleFileSelect = (file: FileType) => { + setSelectedFile(file); + setShowPreview(true); + // Only set loading if the file is previewable + setLoading(isPreviewableType(file.type)); + setError(null); + }; + + const handleBackToList = () => { + setShowPreview(false); + setSelectedFile(null); + }; + + const renderFileContent = (file: FileType) => { + const fileType = file.type.toLowerCase(); + + // If not a previewable type, don't show loading state + if (!isPreviewableType(fileType)) { + return ( +
+
📄
+

+ This file type ({file.type}) cannot be previewed. +
+ + Open in New Tab + +

+
+ ); + } + + if (fileType.startsWith('image/')) { + return ( + {file.name} + ); + } + + if (fileType.startsWith('video/')) { + return ( + + ); + } + + if (fileType === 'application/pdf') { + return ( +