fix(web): render full document content in viewer

The memories list endpoint caps content at 2000 chars; the document
modal rendered straight from that list cache, so long Claude Code
sessions (and any doc over the cap) were truncated mid-transcript.
Fetch the full document by id when the modal opens and use it for
parsing, the editor, and content rendering.

Also closes a latent data-loss path where the editor initialized from
truncated content, so a save could overwrite the stored document.
This commit is contained in:
Mahesh Sanikommu 2026-06-05 17:33:08 -07:00
parent ad5734cdfc
commit a5ff55c99f
2 changed files with 44 additions and 5 deletions

View file

@ -27,6 +27,7 @@ import type { UseMutationResult } from "@tanstack/react-query"
import { toast } from "sonner"
import { useIsMobile } from "@hooks/use-mobile"
import { parsePluginDocument } from "@/lib/plugin-document"
import { useFullDocumentContent } from "@/hooks/use-full-document"
type DocumentsResponse = z.infer<typeof DocumentsWithMemoriesResponseSchema>
type DocumentWithMemories = DocumentsResponse["documents"][0]
@ -198,16 +199,25 @@ export function DocumentModal({
const isMobile = useIsMobile()
const { updateMutation, deleteMutation } = useDocumentMutations({ onClose })
const fullContent = useFullDocumentContent(_document?.id, isOpen)
const effectiveDocument = useMemo(
() =>
_document && fullContent !== null
? { ..._document, content: fullContent }
: _document,
[_document, fullContent],
)
const { initialEditorContent, initialEditorString } = useMemo(() => {
const content = _document?.content as string | null | undefined
const content = effectiveDocument?.content as string | null | undefined
return {
initialEditorContent: content ?? undefined,
initialEditorString: content ?? "",
}
}, [_document?.content])
}, [effectiveDocument?.content])
const pluginDocument = useMemo(
() => parsePluginDocument(_document),
[_document],
() => parsePluginDocument(effectiveDocument),
[effectiveDocument],
)
const [draftContentString, setDraftContentString] =
@ -281,7 +291,7 @@ export function DocumentModal({
className="bg-[#14161A] rounded-[14px] overflow-hidden flex min-h-0 flex-1 flex-col shadow-[inset_0_2px_4px_rgba(0,0,0,0.3),inset_0_1px_2px_rgba(0,0,0,0.1)] relative"
>
<DocumentContent
document={_document}
document={effectiveDocument}
textEditorProps={textEditorProps}
pluginDocument={pluginDocument}
/>

View file

@ -0,0 +1,29 @@
import { useQuery } from "@tanstack/react-query"
import { $fetch } from "@lib/api"
// List endpoint truncates `content` to ~2000 chars; fetch the full doc by id for the viewer.
export function useFullDocumentContent(
documentId: string | null | undefined,
enabled: boolean,
): string | null {
const isReal = !!documentId && !documentId.startsWith("temp-")
const { data } = useQuery({
queryKey: ["document-full", documentId],
enabled: enabled && isReal,
staleTime: 5 * 60 * 1000,
queryFn: async () => {
const res = await $fetch("@get/documents/:id", {
params: { id: documentId as string },
disableValidation: true,
})
if (res.error) {
throw new Error(res.error?.message || "Failed to fetch document")
}
const doc = res.data as { content?: string | null } | null
return typeof doc?.content === "string" ? doc.content : null
},
})
return data ?? null
}