Skip to content

Commit d1878ef

Browse files
committed
fix(mdviewer): scroll position lost on panel reopen, theme reflow guard
- Fix scroll position destroyed when panel is hidden then reopened: saveActiveScrollPos now skips saving when viewer is hidden (scrollTop=0 from hidden element would overwrite the correct cached value) - Stricter theme skip: check both data-theme attr and colorScheme style - Increase panel reopen scroll test timeout for CI stability
1 parent 3f5ae14 commit d1878ef

3 files changed

Lines changed: 14 additions & 5 deletions

File tree

src-mdviewer/src/bridge.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -808,10 +808,14 @@ function handleReloadFile(data) {
808808

809809
function handleSetTheme(data) {
810810
const { theme } = data;
811+
const newScheme = theme === "dark" ? "dark" : "light";
811812
// Skip if already applied to avoid reflows that can reset scroll position
812-
if (document.documentElement.getAttribute("data-theme") === theme) return;
813+
if (document.documentElement.getAttribute("data-theme") === theme &&
814+
document.documentElement.style.colorScheme === newScheme) {
815+
return;
816+
}
813817
document.documentElement.setAttribute("data-theme", theme);
814-
document.documentElement.style.colorScheme = theme === "dark" ? "dark" : "light";
818+
document.documentElement.style.colorScheme = newScheme;
815819
setState({ theme });
816820
}
817821

src-mdviewer/src/core/doc-cache.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,10 @@ export function saveActiveScrollPos() {
176176
const entry = cache.get(activeFilePath);
177177
if (!entry) return;
178178

179+
// Don't overwrite scroll position if viewer is hidden (e.g. panel closed)
180+
// — hidden elements report scrollTop = 0 which would destroy the saved value.
181+
if (!viewerContainer.offsetParent && viewerContainer.scrollTop === 0) return;
182+
179183
entry.scrollPos = viewerContainer.scrollTop;
180184

181185
// Also save source line for reload scenarios (DOM rebuilt, pixel pos unreliable)

test/spec/md-editor-integ-test.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -774,12 +774,13 @@ define(function (require, exports, module) {
774774
// Verify edit mode preserved
775775
await _assertMdEditMode(true);
776776

777-
// Verify scroll position preserved (wider tolerance for CI)
777+
// Verify scroll position preserved (wider tolerance for CI).
778+
// Wait longer as theme/content sync after reopen can cause transient reflows.
778779
await awaitsFor(() => {
779780
const scroll = _getViewerScrollTop();
780781
return scroll > 10 && Math.abs(scroll - scrollBefore) < 150;
781-
}, "scroll position to be preserved after panel reopen", 5000);
782-
}, 15000);
782+
}, "scroll position to be preserved after panel reopen", 8000);
783+
}, 20000);
783784

784785
it("should reload button re-render current file with fresh DOM preserving scroll and edit mode", async function () {
785786
await _openMdFileAndWaitForPreview("long.md");

0 commit comments

Comments
 (0)