diff --git a/shared/editor/nodes/CodeFence.ts b/shared/editor/nodes/CodeFence.ts index bca0828da6..a736e68fad 100644 --- a/shared/editor/nodes/CodeFence.ts +++ b/shared/editor/nodes/CodeFence.ts @@ -42,6 +42,7 @@ import { setRecentlyUsedCodeLanguage, } from "../lib/code"; import { isCode, isMermaid } from "../lib/isCode"; +import { isRemoteTransaction } from "../lib/multiplayer"; import { findBlockNodes } from "../queries/findChildren"; import type { MarkdownSerializerState } from "../lib/markdown/serializer"; import { findNextNewline, findPreviousNewline } from "../queries/findNewlines"; @@ -447,17 +448,20 @@ export default class CodeFence extends Node { return prev; } - // Recompute tall blocks on doc changes, preserving - // user collapse/expand choices where possible. + // Recompute tall blocks on doc changes. Newly tall blocks are only + // auto-collapsed when content arrives via load/remote sync — never + // while the user is typing, which would collapse the block under + // the cursor. if (tr.docChanged) { const tallBlocks = findTallBlocks(newState.doc); const collapsedBlocks = new Set(); + const isRemote = isRemoteTransaction(tr); const inverse = tr.mapping.invert(); for (const pos of tallBlocks) { const oldPos = inverse.map(pos); - if (!prev.tallBlocks.has(oldPos)) { - // Newly tall blocks start collapsed + if (isRemote && !prev.tallBlocks.has(oldPos)) { + // Newly tall blocks start collapsed on load collapsedBlocks.add(pos); } else if (prev.collapsedBlocks.has(oldPos)) { // Preserve previous collapsed state