Minor appearance changes, sharing live preview
All checks were successful
Automated Container Build / build-and-push (push) Successful in 1m16s
All checks were successful
Automated Container Build / build-and-push (push) Successful in 1m16s
This commit is contained in:
parent
2bcfca983c
commit
27fd6fa4f5
3 changed files with 25 additions and 2 deletions
|
|
@ -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,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)' }} />
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
))
|
))
|
||||||
|
|
|
||||||
Reference in a new issue