fix(reader): apply page margin changes live on all platforms (#4898) (#4900)

Adjusting the top, bottom, left, or right page margin had no visible
effect until an unrelated setting (e.g. Show Header) was toggled.

The BooksGrid perf refactor (#4562) memoized the derived view/content
insets on the ViewSettings object identity. saveViewSettings mutates
ViewSettings in place (same reference), so the memo never recomputed on
a margin edit and the new margin never reached the paginator. Left and
right margins were always stale; top and bottom only refreshed when the
header/footer visibility (an effect dependency) changed, which is why
toggling the header appeared to apply a pending change.

Extract the inset derivation into useContentInsets and memoize by the
resolved numeric values instead of the object reference: identical
numbers across a page turn keep a stable reference (no re-render storm),
while a changed margin yields a new one that propagates to the renderer.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Huang Xin
2026-07-03 03:24:34 +09:00
committed by GitHub
parent 77ea87c344
commit fd8fbb178c
3 changed files with 143 additions and 28 deletions
@@ -10,7 +10,7 @@ import { useSidebarStore } from '@/store/sidebarStore';
import { useBookDataStore } from '@/store/bookDataStore';
import { useTranslation } from '@/hooks/useTranslation';
import { getGridTemplate, getInsetEdges } from '@/utils/grid';
import { getViewInsets } from '@/utils/insets';
import { useContentInsets } from '../hooks/useContentInsets';
import SearchResultsNav from './sidebar/SearchResultsNav';
import BooknotesNav from './sidebar/BooknotesNav';
import FoliateViewer from './FoliateViewer';
@@ -118,33 +118,10 @@ const BookCellInner: React.FC<BookCellProps> = ({
const config = getConfig(bookKey);
const { book, bookDoc } = bookData || {};
// viewSettings drives both viewInsets and the inset-derived geometry.
// Memoize off its identity so contentInsets stays stable while the
// user is just turning pages viewSettings only changes when the
// user toggles settings, not on every relocate. Same logic for
// gridInsets which is keyed off the resolved Insets numbers.
const viewInsets = useMemo(
() => (viewSettings ? getViewInsets(viewSettings) : { top: 0, right: 0, bottom: 0, left: 0 }),
[viewSettings],
);
const contentInsets = useMemo(
() => ({
top: gridInsets.top + viewInsets.top,
right: gridInsets.right + viewInsets.right,
bottom: gridInsets.bottom + viewInsets.bottom,
left: gridInsets.left + viewInsets.left,
}),
[
gridInsets.top,
gridInsets.right,
gridInsets.bottom,
gridInsets.left,
viewInsets.top,
viewInsets.right,
viewInsets.bottom,
viewInsets.left,
],
);
// viewInsets/contentInsets stay stable while the user is just turning pages
// (margins are unchanged) but update when a margin setting changes — even
// though saveViewSettings mutates viewSettings in place (#4898).
const { viewInsets, contentInsets } = useContentInsets(viewSettings, gridInsets);
// Stable callback so HeaderBar doesn't see a new prop reference per
// BooksGrid render.