mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-09-13 23:11:10 +00:00
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:
parent
ad5734cdfc
commit
a5ff55c99f
2 changed files with 44 additions and 5 deletions
|
|
@ -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}
|
||||
/>
|
||||
|
|
|
|||
29
apps/web/hooks/use-full-document.ts
Normal file
29
apps/web/hooks/use-full-document.ts
Normal 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
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue