Skip to content

Commit

Permalink
cache document thumbnails
Browse files Browse the repository at this point in the history
  • Loading branch information
ibastawisi committed Jan 13, 2025
1 parent 9752c15 commit 8137b6a
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 27 deletions.
4 changes: 2 additions & 2 deletions src/components/DocumentCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { LocalDocumentRevision, User, UserDocument } from '@/types';
import { memo } from 'react';
import { SxProps, Theme } from '@mui/material/styles';
import { Card, CardActionArea, CardHeader, Skeleton, Typography, Avatar, CardActions, Chip, Badge, NoSsr, IconButton } from '@mui/material';
import { Article, MobileFriendly, Cloud, Public, Workspaces, Security, CloudDone, CloudSync, MoreVert, Share } from '@mui/icons-material';
import { MobileFriendly, Cloud, Public, Workspaces, Security, CloudDone, CloudSync, MoreVert, Share } from '@mui/icons-material';
import dynamic from "next/dynamic";
import DocumentCardThumbnail from './DocumentCardThumbnail';

Expand Down Expand Up @@ -81,7 +81,7 @@ const DocumentCard: React.FC<{ userDocument?: UserDocument, user?: User, sx?: Sx
}
avatar={
<Badge badgeContent={revisionsBadgeContent} color="secondary">
<DocumentCardThumbnail documetId={document?.id} />
<DocumentCardThumbnail documentId={document?.id} head={document?.head} />
</Badge>
}
/>
Expand Down
48 changes: 25 additions & 23 deletions src/components/DocumentCardThumbnail.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,37 @@
"use client"
import * as React from 'react';
import { memo, useEffect } from 'react';
import { memo, useEffect, useState } from 'react';
import { Box, Skeleton } from '@mui/material';
import { actions, useDispatch } from '@/store';
import { generateHtml } from '@/editor';
import documentDB from '@/indexeddb';
import { GetDocumentThumbnailResponse } from '@/types';

const DocumentCardThumbnail: React.FC<{ documetId?: string }> = memo(({ documetId }) => {
const dispatch = useDispatch();
const [thumbnail, setThumbnail] = React.useState<string | null>(null);
const thumbnailCache = new Map<string, string>();

const getDocumentThumbnail = async () => {
if (!documetId) return null;
const localResponse = await dispatch(actions.getLocalDocument(documetId));
if (localResponse.type === actions.getLocalDocument.fulfilled.type) {
const editorDocument = localResponse.payload as ReturnType<typeof actions.getLocalDocument.fulfilled>['payload'];
const data = editorDocument.data;
const thumbnail = await generateHtml({ ...data, root: { ...data.root, children: data.root.children.slice(0, 5) } });
return thumbnail;
} else {
const cloudResponse = await dispatch(actions.getCloudDocumentThumbnail(documetId));
if (cloudResponse.type === actions.getCloudDocumentThumbnail.fulfilled.type) {
const thumbnail = cloudResponse.payload as ReturnType<typeof actions.getCloudDocumentThumbnail.fulfilled>['payload'];
return thumbnail;
}
}
return null;
const getDocumentThumbnail = async (id: string, head: string) => {
const cachedThumbnail = thumbnailCache.get(id);
if (cachedThumbnail) return cachedThumbnail;
const document = await documentDB.getByID(id);
if (document) {
const data = document.data;
const thumbnail = await generateHtml({ ...data, root: { ...data.root, children: data.root.children.slice(0, 5) } });
thumbnailCache.set(head, thumbnail);
return thumbnail;
} else {
const response = await fetch(`/api/thumbnails/${id}`);
const { data } = await response.json() as GetDocumentThumbnailResponse;
if (data) thumbnailCache.set(head, data);
return data;
}
}

const DocumentCardThumbnail: React.FC<{ documentId?: string, head?: string }> = memo(({ documentId, head }) => {
const [thumbnail, setThumbnail] = useState(head ? thumbnailCache.get(head) : null);

useEffect(() => {
getDocumentThumbnail().then(setThumbnail);
}, []);
if (!documentId || !head || thumbnail) return;
getDocumentThumbnail(documentId, head).then(setThumbnail);
}, [thumbnail]);

if (thumbnail) return <Box className='document-thumbnail' dangerouslySetInnerHTML={{ __html: thumbnail.replaceAll('<a', '<span').replaceAll('</a', '</span') }} />;
return (
Expand Down
2 changes: 0 additions & 2 deletions src/store/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ import {
} from '../types';
import { GetDocumentsResponse, PostDocumentsResponse, DeleteDocumentResponse, GetDocumentResponse, PatchDocumentResponse } from '@/types';
import { validate } from 'uuid';
import { generateHtml } from '@/editor';
import exp from 'constants';

const initialState: AppState = {
documents: [],
Expand Down

0 comments on commit 8137b6a

Please sign in to comment.