Minor appearance changes, sharing live preview
All checks were successful
Automated Container Build / build-and-push (push) Successful in 1m16s

This commit is contained in:
Elijah 2026-05-22 19:06:21 -07:00
parent 2bcfca983c
commit 27fd6fa4f5
3 changed files with 25 additions and 2 deletions

View file

@ -2,6 +2,7 @@ package handlers
import ( import (
"fmt" "fmt"
"mime"
"os" "os"
"path/filepath" "path/filepath"
"time" "time"
@ -203,10 +204,16 @@ func (h *ShareHandler) GetPublicShare(c *fiber.Ctx) error {
// For simplicity, we'll return a short-lived download token JWT. // For simplicity, we'll return a short-lived download token JWT.
// Actually, easier: the frontend calls GET /api/public/download/:id?pwd=xxx // Actually, easier: the frontend calls GET /api/public/download/:id?pwd=xxx
mimeType := mime.TypeByExtension(filepath.Ext(info.Name()))
if mimeType == "" {
mimeType = "application/octet-stream"
}
return c.JSON(fiber.Map{ return c.JSON(fiber.Map{
"name": filepath.Base(path), "name": filepath.Base(path),
"size": info.Size(), "size": info.Size(),
"is_dir": info.IsDir(), "is_dir": info.IsDir(),
"mime_type": mimeType,
}) })
} }

View file

@ -11,7 +11,7 @@ export default function PublicSharePage({ params }: { params: Promise<{ id: stri
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
const [requirePassword, setRequirePassword] = useState(false); const [requirePassword, setRequirePassword] = useState(false);
const [password, setPassword] = useState(''); const [password, setPassword] = useState('');
const [fileInfo, setFileInfo] = useState<{ name: string; size: number; is_dir: boolean } | null>(null); const [fileInfo, setFileInfo] = useState<{ name: string; size: number; is_dir: boolean; mime_type?: string } | null>(null);
useEffect(() => { useEffect(() => {
fetchShareInfo(); fetchShareInfo();
@ -112,6 +112,11 @@ export default function PublicSharePage({ params }: { params: Promise<{ id: stri
</div> </div>
); );
} }
const isImage = fileInfo?.mime_type?.startsWith('image/');
const isVideo = fileInfo?.mime_type?.startsWith('video/');
const isAudio = fileInfo?.mime_type?.startsWith('audio/');
const isPdf = fileInfo?.mime_type === 'application/pdf';
const downloadUrl = fileInfo ? api.getPublicDownloadUrl(id, password) : '';
return ( return (
<div className="min-h-screen flex items-center justify-center p-4" style={{ backgroundColor: 'var(--color-bg-primary)' }}> <div className="min-h-screen flex items-center justify-center p-4" style={{ backgroundColor: 'var(--color-bg-primary)' }}>
@ -121,6 +126,14 @@ export default function PublicSharePage({ params }: { params: Promise<{ id: stri
<div className="w-24 h-24 rounded-2xl flex items-center justify-center" style={{ backgroundColor: 'var(--color-accent-subtle)' }}> <div className="w-24 h-24 rounded-2xl flex items-center justify-center" style={{ backgroundColor: 'var(--color-accent-subtle)' }}>
<Folder className="w-12 h-12" style={{ color: 'var(--color-accent)' }} /> <Folder className="w-12 h-12" style={{ color: 'var(--color-accent)' }} />
</div> </div>
) : isImage ? (
<img src={downloadUrl} alt={fileInfo?.name} className="w-full max-h-48 object-contain rounded-xl" />
) : isVideo ? (
<video src={downloadUrl} controls className="w-full max-h-48 rounded-xl" />
) : isAudio ? (
<audio src={downloadUrl} controls className="w-full mt-4" />
) : isPdf ? (
<iframe src={downloadUrl} className="w-full h-64 rounded-xl border-none" />
) : ( ) : (
<div className="w-24 h-24 rounded-2xl flex items-center justify-center" style={{ backgroundColor: 'var(--color-accent-subtle)' }}> <div className="w-24 h-24 rounded-2xl flex items-center justify-center" style={{ backgroundColor: 'var(--color-accent-subtle)' }}>
<File className="w-12 h-12" style={{ color: 'var(--color-accent)' }} /> <File className="w-12 h-12" style={{ color: 'var(--color-accent)' }} />

View file

@ -762,10 +762,13 @@ export default function FileExplorer({ onLogout }: FileExplorerProps) {
handlePinnedDragEnd(source, file.path); handlePinnedDragEnd(source, file.path);
} }
}} }}
className="group flex items-center justify-between px-10 py-2 text-sm font-medium cursor-pointer rounded-lg transition-colors hover:bg-white/5" className="group flex items-center justify-between px-10 py-2 text-sm font-medium cursor-pointer rounded-lg transition-colors hover:bg-white/5 gap-3"
style={{ color: 'var(--color-text-secondary)' }} style={{ color: 'var(--color-text-secondary)' }}
onClick={() => navigateTo(file.path)} onClick={() => navigateTo(file.path)}
> >
<div className="w-4 h-4 flex items-center justify-center flex-shrink-0 [&>svg]:w-4 [&>svg]:h-4">
{getFileIcon(file)}
</div>
<span className="truncate flex-1">{file.name}</span> <span className="truncate flex-1">{file.name}</span>
</div> </div>
)) ))