Timeline scroll fix
This commit is contained in:
parent
f1279f55ee
commit
66e21f7cc5
@ -450,6 +450,7 @@
|
||||
|
||||
const scene = payload.scenes[points[0].index];
|
||||
if (scene?.timelineUrl) {
|
||||
window.PlotLineTimelineScroll?.save();
|
||||
window.location.href = scene.timelineUrl;
|
||||
}
|
||||
});
|
||||
@ -534,6 +535,15 @@
|
||||
const collapsedKey = "plotline.timeline.collapsed";
|
||||
const densityKey = "plotline.timeline.density";
|
||||
const zoomKey = "plotline.timeline.zoom";
|
||||
const scrollKey = "plotline.timeline.pending-scroll";
|
||||
const scrollContainerSelector = [
|
||||
".timeline-shell",
|
||||
".plot-lane-board",
|
||||
".asset-lane-board",
|
||||
".character-lane-board",
|
||||
".metric-graph-stack",
|
||||
"[data-timeline-minimap]"
|
||||
].join(",");
|
||||
const densityValues = ["compact", "comfortable", "expanded"];
|
||||
const zoomValues = ["book", "chapter", "scene-detail"];
|
||||
|
||||
@ -548,6 +558,62 @@
|
||||
const hasCollapsedPreference = localStorage.getItem(collapsedKey) !== null;
|
||||
const collapsed = readSet(collapsedKey);
|
||||
|
||||
const getScrollContainers = () => [...root.querySelectorAll(scrollContainerSelector)];
|
||||
|
||||
const saveScrollPosition = () => {
|
||||
try {
|
||||
sessionStorage.setItem(scrollKey, JSON.stringify({
|
||||
path: window.location.pathname,
|
||||
top: window.scrollY,
|
||||
left: window.scrollX,
|
||||
workspaceLeft: workspace.scrollLeft,
|
||||
workspaceTop: workspace.scrollTop,
|
||||
containers: getScrollContainers().map((container, index) => ({
|
||||
index,
|
||||
left: container.scrollLeft,
|
||||
top: container.scrollTop
|
||||
}))
|
||||
}));
|
||||
} catch {
|
||||
// Storage can be unavailable in private or restricted browser modes.
|
||||
}
|
||||
};
|
||||
|
||||
const restoreScrollPosition = () => {
|
||||
let scrollPosition = null;
|
||||
try {
|
||||
scrollPosition = JSON.parse(sessionStorage.getItem(scrollKey) || "null");
|
||||
sessionStorage.removeItem(scrollKey);
|
||||
} catch {
|
||||
try {
|
||||
sessionStorage.removeItem(scrollKey);
|
||||
} catch {
|
||||
// Ignore storage failures; normal navigation should continue.
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!scrollPosition || scrollPosition.path !== window.location.pathname) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.requestAnimationFrame(() => {
|
||||
workspace.scrollLeft = Number(scrollPosition.workspaceLeft) || 0;
|
||||
workspace.scrollTop = Number(scrollPosition.workspaceTop) || 0;
|
||||
const containers = getScrollContainers();
|
||||
(scrollPosition.containers || []).forEach((saved) => {
|
||||
const container = containers[saved.index];
|
||||
if (container) {
|
||||
container.scrollLeft = Number(saved.left) || 0;
|
||||
container.scrollTop = Number(saved.top) || 0;
|
||||
}
|
||||
});
|
||||
window.scrollTo(Number(scrollPosition.left) || 0, Number(scrollPosition.top) || 0);
|
||||
});
|
||||
};
|
||||
|
||||
window.PlotLineTimelineScroll = { save: saveScrollPosition };
|
||||
|
||||
const applyMode = (kind, value, values) => {
|
||||
values.forEach((item) => root.classList.remove(`${kind}-${item}`));
|
||||
root.classList.add(`${kind}-${value}`);
|
||||
@ -638,7 +704,38 @@
|
||||
zoomSelect?.addEventListener("change", () => applyZoom(zoomSelect.value));
|
||||
applyDensity(localStorage.getItem(densityKey) || "comfortable");
|
||||
applyZoom(localStorage.getItem(zoomKey) || "chapter");
|
||||
window.requestAnimationFrame(() => scrollActiveChapterIntoView("auto"));
|
||||
const hadPendingScrollRestore = (() => {
|
||||
try {
|
||||
return sessionStorage.getItem(scrollKey) !== null;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
})();
|
||||
window.requestAnimationFrame(() => {
|
||||
scrollActiveChapterIntoView("auto");
|
||||
if (hadPendingScrollRestore) {
|
||||
restoreScrollPosition();
|
||||
}
|
||||
});
|
||||
|
||||
const saveScrollForSceneSelection = (event) => {
|
||||
if (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
const target = event.target instanceof Element ? event.target : null;
|
||||
const link = target?.closest("a[href]");
|
||||
if (!link || !root.contains(link)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const url = new URL(link.href, window.location.href);
|
||||
if ([...url.searchParams.keys()].some((key) => key.toLowerCase() === "selectedsceneid")) {
|
||||
saveScrollPosition();
|
||||
}
|
||||
};
|
||||
|
||||
root.addEventListener("click", saveScrollForSceneSelection, { capture: true });
|
||||
|
||||
const runSearch = () => {
|
||||
const query = searchInput?.value.trim().toLowerCase() || "";
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user