Feat: Live thumbnails for office files
All checks were successful
Automated Container Build / build-and-push (push) Successful in 1m26s
All checks were successful
Automated Container Build / build-and-push (push) Successful in 1m26s
This commit is contained in:
parent
b80abdbefb
commit
80d60d540a
10 changed files with 244 additions and 106 deletions
|
|
@ -1,6 +1,7 @@
|
|||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { Plus, Pencil, Trash2, Pin, FileText, LayoutTemplate, FileSpreadsheet } from 'lucide-react';
|
||||
import api from '@/lib/api';
|
||||
import ThumbnailImage from './ThumbnailImage';
|
||||
|
||||
interface FileItem {
|
||||
name: string;
|
||||
|
|
@ -11,6 +12,7 @@ interface FileItem {
|
|||
is_pinned: boolean;
|
||||
is_trashed: boolean;
|
||||
mod_time: string;
|
||||
checksum?: string;
|
||||
}
|
||||
|
||||
interface OfficeHomeProps {
|
||||
|
|
@ -63,6 +65,7 @@ export default function OfficeHome({ type, onFileSelect, onCreateBlank, onPinCha
|
|||
const [renaming, setRenaming] = useState<string | null>(null); // path of file being renamed
|
||||
const [renameValue, setRenameValue] = useState('');
|
||||
const renameInputRef = useRef<HTMLInputElement>(null);
|
||||
const [downloadToken, setDownloadToken] = useState('');
|
||||
|
||||
const ext = type === 'docs' ? '.docx' : type === 'slides' ? '.pptx' : '.xlsx';
|
||||
const fileTypeParam = type === 'docs' ? 'docx' : type === 'slides' ? 'pptx' : 'xlsx';
|
||||
|
|
@ -118,6 +121,7 @@ export default function OfficeHome({ type, onFileSelect, onCreateBlank, onPinCha
|
|||
|
||||
useEffect(() => {
|
||||
fetchFiles();
|
||||
api.createDownloadToken().then(setDownloadToken).catch(console.error);
|
||||
}, [type]);
|
||||
|
||||
// Close context menu on click elsewhere
|
||||
|
|
@ -232,7 +236,13 @@ export default function OfficeHome({ type, onFileSelect, onCreateBlank, onPinCha
|
|||
className={`w-full ${type === 'docs' ? 'aspect-[1/1.4]' : 'aspect-[1.4/1]'} rounded-lg border hover:border-blue-500 transition-colors flex items-center justify-center shadow-sm overflow-hidden relative`}
|
||||
style={{ backgroundColor: 'var(--color-bg-elevated)', borderColor: 'var(--color-border)' }}
|
||||
>
|
||||
<Icon className="w-16 h-16 text-3xl opacity-30 group-hover:opacity-60 transition-opacity" />
|
||||
{file.checksum ? (
|
||||
<div className="absolute inset-0 w-full h-full flex items-center justify-center z-0">
|
||||
<ThumbnailImage checksum={file.checksum} fallbackIcon={<Icon className="w-16 h-16 text-3xl opacity-30 group-hover:opacity-60 transition-opacity" />} downloadToken={downloadToken} />
|
||||
</div>
|
||||
) : (
|
||||
<Icon className="w-16 h-16 text-3xl opacity-30 group-hover:opacity-60 transition-opacity" />
|
||||
)}
|
||||
</button>
|
||||
<div className="flex items-start gap-2 min-w-0">
|
||||
<Icon className="w-4 h-4 flex-shrink-0 mt-0.5 text-[10px]" />
|
||||
|
|
|
|||
Reference in a new issue