From 1ac6b42ae33088ff9e4ea6971759d365168d5e77 Mon Sep 17 00:00:00 2001 From: Anthony LC Date: Tue, 24 Feb 2026 11:14:12 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=EF=B8=8F(frontend)=20fetch=20document?= =?UTF-8?q?=20without=20content=20when=20not=20needed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To improve performance, especially for documents with large content, an optional query parameter `without_content` has been added to the document fetching API endpoint. When this parameter is set to true, the API will return the document metadata without the content, allowing the frontend to load faster and reduce unnecessary data transfer. --- .../Interlinking/InterlinkingLinkInlineContent.tsx | 2 +- .../src/features/docs/doc-management/api/useDoc.tsx | 9 +++++++-- .../impress/src/features/docs/doc-management/types.tsx | 2 +- .../y-provider/__tests__/collaborationBackend.test.ts | 7 +++++-- .../servers/y-provider/__tests__/hocuspocusWS.test.ts | 8 ++++---- .../servers/y-provider/src/api/collaborationBackend.ts | 7 ++++--- .../servers/y-provider/src/servers/hocuspocusServer.ts | 5 ++++- 7 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-inline-content/Interlinking/InterlinkingLinkInlineContent.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-inline-content/Interlinking/InterlinkingLinkInlineContent.tsx index be5145dd..f07ac5fa 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-inline-content/Interlinking/InterlinkingLinkInlineContent.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/custom-inline-content/Interlinking/InterlinkingLinkInlineContent.tsx @@ -95,7 +95,7 @@ export const LinkSelected = ({ isEditable, updateInlineContent, }: LinkSelectedProps) => { - const { data: doc } = useDoc({ id: docId }); + const { data: doc } = useDoc({ id: docId, withoutContent: true }); /** * Update the content title if the referenced doc title changes diff --git a/src/frontend/apps/impress/src/features/docs/doc-management/api/useDoc.tsx b/src/frontend/apps/impress/src/features/docs/doc-management/api/useDoc.tsx index 4fd6e07f..5441634c 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-management/api/useDoc.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-management/api/useDoc.tsx @@ -6,10 +6,15 @@ import { Doc } from '../types'; export type DocParams = { id: string; + withoutContent?: boolean; }; -export const getDoc = async ({ id }: DocParams): Promise => { - const response = await fetchAPI(`documents/${id}/`); +export const getDoc = async ({ + id, + withoutContent, +}: DocParams): Promise => { + const params = withoutContent ? '?without_content=true' : ''; + const response = await fetchAPI(`documents/${id}/${params}`); if (!response.ok) { throw new APIError('Failed to get the doc', await errorCauses(response)); diff --git a/src/frontend/apps/impress/src/features/docs/doc-management/types.tsx b/src/frontend/apps/impress/src/features/docs/doc-management/types.tsx index 64640f9e..75f1981c 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-management/types.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-management/types.tsx @@ -53,7 +53,7 @@ export interface Doc { title?: string; children?: Doc[]; childrenCount?: number; - content: Base64; + content?: Base64; created_at: string; creator: string; deleted_at: string | null; diff --git a/src/frontend/servers/y-provider/__tests__/collaborationBackend.test.ts b/src/frontend/servers/y-provider/__tests__/collaborationBackend.test.ts index d5b7678f..561ece87 100644 --- a/src/frontend/servers/y-provider/__tests__/collaborationBackend.test.ts +++ b/src/frontend/servers/y-provider/__tests__/collaborationBackend.test.ts @@ -19,10 +19,13 @@ describe('CollaborationBackend', () => { const { fetchDocument } = await import('@/api/collaborationBackend'); const documentId = 'test-document-123'; - await fetchDocument(documentId, { cookie: 'test-cookie' }); + await fetchDocument( + { name: documentId, withoutContent: true }, + { cookie: 'test-cookie' }, + ); expect(axiosGetSpy).toHaveBeenCalledWith( - `http://app-dev:8000/api/v1.0/documents/${documentId}/`, + `http://app-dev:8000/api/v1.0/documents/${documentId}/?without_content=true`, expect.objectContaining({ headers: expect.objectContaining({ 'X-Y-Provider-Key': 'test-yprovider-key', diff --git a/src/frontend/servers/y-provider/__tests__/hocuspocusWS.test.ts b/src/frontend/servers/y-provider/__tests__/hocuspocusWS.test.ts index eaaa785e..3a23f90b 100644 --- a/src/frontend/servers/y-provider/__tests__/hocuspocusWS.test.ts +++ b/src/frontend/servers/y-provider/__tests__/hocuspocusWS.test.ts @@ -228,7 +228,7 @@ describe('Server Tests', () => { wsHocus.stopConnectionAttempt(); expect(data.reason).toBe('permission-denied'); expect(fetchDocumentMock).toHaveBeenCalledExactlyOnceWith( - room, + { name: room, withoutContent: true }, expect.any(Object), ); wsHocus.webSocket?.close(); @@ -273,7 +273,7 @@ describe('Server Tests', () => { wsHocus.stopConnectionAttempt(); expect(data.reason).toBe('permission-denied'); expect(fetchDocumentMock).toHaveBeenCalledExactlyOnceWith( - room, + { name: room, withoutContent: true }, expect.any(Object), ); wsHocus.webSocket?.close(); @@ -322,7 +322,7 @@ describe('Server Tests', () => { wsHocus.destroy(); expect(fetchDocumentMock).toHaveBeenCalledWith( - room, + { name: room, withoutContent: true }, expect.any(Object), ); @@ -371,7 +371,7 @@ describe('Server Tests', () => { wsHocus.destroy(); expect(fetchDocumentMock).toHaveBeenCalledWith( - room, + { name: room, withoutContent: true }, expect.any(Object), ); diff --git a/src/frontend/servers/y-provider/src/api/collaborationBackend.ts b/src/frontend/servers/y-provider/src/api/collaborationBackend.ts index 6fca2b84..f0ec850a 100644 --- a/src/frontend/servers/y-provider/src/api/collaborationBackend.ts +++ b/src/frontend/servers/y-provider/src/api/collaborationBackend.ts @@ -17,7 +17,7 @@ type Base64 = string; interface Doc { id: string; title?: string; - content: Base64; + content?: Base64; creator: string; is_favorite: boolean; link_reach: 'restricted' | 'public' | 'authenticated'; @@ -74,10 +74,11 @@ async function fetch( } export function fetchDocument( - name: string, + { name, withoutContent }: { name: string; withoutContent?: boolean }, requestHeaders: IncomingHttpHeaders, ): Promise { - return fetch(`/api/v1.0/documents/${name}/`, requestHeaders); + const params = withoutContent ? '?without_content=true' : ''; + return fetch(`/api/v1.0/documents/${name}/${params}`, requestHeaders); } export function fetchCurrentUser( diff --git a/src/frontend/servers/y-provider/src/servers/hocuspocusServer.ts b/src/frontend/servers/y-provider/src/servers/hocuspocusServer.ts index 5b2fde0c..1686960b 100644 --- a/src/frontend/servers/y-provider/src/servers/hocuspocusServer.ts +++ b/src/frontend/servers/y-provider/src/servers/hocuspocusServer.ts @@ -39,7 +39,10 @@ export const hocuspocusServer = new Server({ let canEdit; try { - const document = await fetchDocument(documentName, requestHeaders); + const document = await fetchDocument( + { name: documentName, withoutContent: true }, + requestHeaders, + ); if (!document.abilities.retrieve) { logger(