fix: preserve board scroll position when navigating back from a card (#431)
This commit is contained in:
44
apps/web/src/hooks/useScrollRestore.ts
Normal file
44
apps/web/src/hooks/useScrollRestore.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import type { RefObject } from "react";
|
||||||
|
import type { NextRouter } from "next/router";
|
||||||
|
import { useEffect, useRef } from "react";
|
||||||
|
|
||||||
|
const scrollPositions = new Map<string, number>();
|
||||||
|
|
||||||
|
export function useScrollRestore(
|
||||||
|
boardId: string | null | undefined,
|
||||||
|
scrollRef: RefObject<HTMLElement | null>,
|
||||||
|
router: NextRouter,
|
||||||
|
isReady: boolean,
|
||||||
|
) {
|
||||||
|
const restored = useRef(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!boardId) return;
|
||||||
|
|
||||||
|
restored.current = false;
|
||||||
|
|
||||||
|
const saveScrollPosition = () => {
|
||||||
|
if (scrollRef.current) {
|
||||||
|
scrollPositions.set(boardId, scrollRef.current.scrollLeft);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
router.events.on("routeChangeStart", saveScrollPosition);
|
||||||
|
return () => router.events.off("routeChangeStart", saveScrollPosition);
|
||||||
|
}, [boardId, router.events, scrollRef]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (restored.current || !isReady || !boardId) return;
|
||||||
|
restored.current = true;
|
||||||
|
|
||||||
|
const saved = scrollPositions.get(boardId);
|
||||||
|
if (saved === undefined) return;
|
||||||
|
|
||||||
|
// StrictModeDroppable delays rendering by one requestAnimationFrame
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
if (scrollRef.current) scrollRef.current.scrollLeft = saved;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, [isReady, scrollRef, boardId]);
|
||||||
|
}
|
||||||
@@ -26,6 +26,7 @@ import { StrictModeDroppable as Droppable } from "~/components/StrictModeDroppab
|
|||||||
import { Tooltip } from "~/components/Tooltip";
|
import { Tooltip } from "~/components/Tooltip";
|
||||||
import { EditYouTubeModal } from "~/components/YouTubeEmbed/EditYouTubeModal";
|
import { EditYouTubeModal } from "~/components/YouTubeEmbed/EditYouTubeModal";
|
||||||
import { useDragToScroll } from "~/hooks/useDragToScroll";
|
import { useDragToScroll } from "~/hooks/useDragToScroll";
|
||||||
|
import { useScrollRestore } from "~/hooks/useScrollRestore";
|
||||||
import { usePermissions } from "~/hooks/usePermissions";
|
import { usePermissions } from "~/hooks/usePermissions";
|
||||||
import { useKeyboardShortcut } from "~/providers/keyboard-shortcuts";
|
import { useKeyboardShortcut } from "~/providers/keyboard-shortcuts";
|
||||||
import { useModal } from "~/providers/modal";
|
import { useModal } from "~/providers/modal";
|
||||||
@@ -141,6 +142,8 @@ export default function BoardPage({ isTemplate }: { isTemplate?: boolean }) {
|
|||||||
|
|
||||||
const isLoading = isInitialLoading || isQueryLoading;
|
const isLoading = isInitialLoading || isQueryLoading;
|
||||||
|
|
||||||
|
useScrollRestore(boardId, scrollRef, router, !isLoading && (boardData?.lists.length ?? 0) > 0);
|
||||||
|
|
||||||
const updateListMutation = api.list.update.useMutation({
|
const updateListMutation = api.list.update.useMutation({
|
||||||
onMutate: async (args) => {
|
onMutate: async (args) => {
|
||||||
await utils.board.byId.cancel();
|
await utils.board.byId.cancel();
|
||||||
|
|||||||
Reference in New Issue
Block a user