Skip to content

Commit

Permalink
Merge pull request #119 from autonomys/add-file-preview
Browse files Browse the repository at this point in the history
Add file preview
  • Loading branch information
clostao authored Dec 19, 2024
2 parents 2c3be2c + 2e4d41f commit e8eff9f
Show file tree
Hide file tree
Showing 8 changed files with 681 additions and 27 deletions.
Binary file modified frontend/.yarn/install-state.gz
Binary file not shown.
3 changes: 2 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
},
"dependencies": {
"@apollo/client": "^3.11.10",
"@autonomys/auto-drive": "^1.0.8",
"@autonomys/auto-drive": "^1.1.4",
"@cyntler/react-doc-viewer": "^1.17.0",
"@graphql-codegen/cli": "^5.0.3",
"@graphql-codegen/introspection": "^4.0.3",
"@graphql-codegen/typescript": "^4.1.2",
Expand Down
102 changes: 102 additions & 0 deletions frontend/src/components/FilePreview/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { useEffect, useMemo, useState } from 'react';
import { ApiService } from '../../services/api';
import { OffchainMetadata } from '@autonomys/auto-dag-data';
import DocViewer, { DocViewerRenderers } from '@cyntler/react-doc-viewer';
import '@cyntler/react-doc-viewer/dist/index.css';
import { simpleMimeType } from '../../utils/misc';

const MAX_FILE_SIZE = BigInt(100 * 1024 * 1024); // 100 MB

export const FilePreview = ({ metadata }: { metadata: OffchainMetadata }) => {
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [isFilePreviewable, setIsFilePreviewable] = useState(false);
const [file, setFile] = useState<Blob | null>(null);

useEffect(() => {
const fetchFile = async () => {
if (
metadata.uploadOptions?.encryption ||
metadata.totalSize > MAX_FILE_SIZE
) {
setIsFilePreviewable(false);
} else {
setIsFilePreviewable(true);
}
};
fetchFile();
}, [metadata]);

useEffect(() => {
if (isFilePreviewable) {
setLoading(true);
ApiService.downloadObject(metadata.dataCid)
.then(async (file) => {
let buffer = Buffer.alloc(0);
for await (const chunk of file) {
buffer = Buffer.concat([buffer, chunk]);
}
const blob = new Blob([buffer], {
type:
metadata.type === 'file' && metadata.mimeType
? simpleMimeType(metadata.mimeType)
: undefined,
});
setFile(blob);
setLoading(false);
})
.catch((error) => {
setError(error.message);
setLoading(false);
});
} else {
setLoading(false);
}
}, [metadata, isFilePreviewable]);

const documents = useMemo(() => {
return (
file && [
{
uri: URL.createObjectURL(file),
fileName: metadata.name,
fileType: metadata.type === 'file' ? metadata.mimeType : undefined,
},
]
);
}, [file, metadata]);

if (loading) {
return <div>Loading...</div>;
}

if (error) {
return <div>Error: {error}</div>;
}

const noRenderer = () => (
<div className='flex h-full items-center justify-center'>
<div className='text-center text-gray-500'>File is not previewable</div>
</div>
);

if (!isFilePreviewable) {
return noRenderer();
}

return (
<DocViewer
documents={documents ?? []}
pluginRenderers={DocViewerRenderers}
initialActiveDocument={documents?.[0]}
config={{
noRenderer: {
overrideComponent: noRenderer,
},
header: {
disableHeader: true,
},
}}
/>
);
};
3 changes: 2 additions & 1 deletion frontend/src/components/Files/UploadingFileModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Dialog, Transition } from '@headlessui/react';
import { Button } from '../common/Button';
import { useEncryptionStore } from '../../states/encryption';
import { UploadService } from '../../services/upload';
import { UploadFileStatus } from '@autonomys/auto-drive';

export const UploadingFileModal = ({
file,
Expand All @@ -24,7 +25,7 @@ export const UploadingFileModal = ({
await UploadService.uploadFile(file, {
password,
}).then((observer) =>
observer.forEach((status) => {
observer.forEach((status: UploadFileStatus) => {
setProgress(status.progress);
}),
);
Expand Down
25 changes: 19 additions & 6 deletions frontend/src/components/UploadedObjectInformation/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ObjectShareModal } from '../Files/ObjectShareModal';
import { ObjectDeleteModal } from '../Files/ObjectDeleteModal';
import { Loader } from 'lucide-react';
import { ObjectDownloadModal } from '../Files/ObjectDownloadModal';
import { FilePreview } from '../FilePreview';

export const UploadedObjectInformation = ({
object,
Expand Down Expand Up @@ -174,13 +175,25 @@ export const UploadedObjectInformation = ({
<span className='ml-[4px]'>0</span>
</div>
</div>
<span className='ml-2 text-xl font-semibold'>Owners</span>
<span className='ml-2 text-xl font-semibold'>Upload Options</span>
<div className='grid grid-cols-2 gap-x-4 gap-y-2 rounded-lg bg-gray-50 p-4 font-medium text-primary'>
{owners?.map((o) => (
<div className='flex' key={o.publicId}>
<span className='ml-[4px]'>{o.publicId}</span>
</div>
))}
<div className='flex'>
<span>Encryption: </span>
<span className='ml-[4px] font-bold'>
{object.metadata.uploadOptions?.encryption?.algorithm || 'Disabled'}
</span>
</div>
<div className='flex'>
<span>Compression: </span>
<span className='ml-[4px] font-bold'>
{object.metadata.uploadOptions?.compression?.algorithm ||
'Disabled'}
</span>
</div>
</div>
<span className='ml-2 text-xl font-semibold'>Preview</span>
<div className='flex w-full flex-col items-center'>
<FilePreview metadata={object.metadata} />
</div>
</div>
);
Expand Down
11 changes: 10 additions & 1 deletion frontend/src/components/common/FileTable/FileTableRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import { FileActionButtons } from '../FileTable';
import bytes from 'bytes';
import { Button } from '../Button';
import { handleEnterOrSpace } from '../../../utils/eventHandler';
import { SquareArrowOutUpRight } from 'lucide-react';
import { InternalLink } from '../InternalLink';

export const FileTableRow = ({
file,
Expand Down Expand Up @@ -169,12 +171,19 @@ export const FileTableRow = ({
onMouseEnter={() => popoverButtonRef.current?.click()}
onMouseLeave={() => popoverButtonRef.current?.click()}
>
<PopoverButton ref={popoverButtonRef} as='span'>
<PopoverButton
ref={popoverButtonRef}
as='div'
className='flex items-center'
>
<span className='font-semibold text-accent hover:cursor-pointer'>
{file.name
? shortenString(file.name, 30)
: `No name (${file.headCid.slice(0, 12)})`}
</span>
<InternalLink href={`/drive/metadata/${file.headCid}`}>
<SquareArrowOutUpRight className='ml-2 h-4 w-4 transition-all duration-200 hover:scale-105' />
</InternalLink>
</PopoverButton>
<Transition
as={Fragment}
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/utils/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,7 @@ export const isValidUUID = (uuid: string | null) => {
/^[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/i;
return uuid ? uuidRegex.test(uuid) : false;
};

export const simpleMimeType = (mimeType: string) => {
return mimeType.split('/')[0];
};
Loading

0 comments on commit e8eff9f

Please sign in to comment.