fix: use separate compact margin and gap when header and footer are dismissed, closes #734 (#1047)

This commit is contained in:
Huang Xin
2025-05-06 18:38:04 +08:00
committed by GitHub
parent b4cda00a91
commit 4c1af671bb
4 changed files with 52 additions and 11 deletions
@@ -192,8 +192,11 @@ const FoliateViewer: React.FC<{
view.renderer.setStyles?.(getStyles(viewSettings));
const isScrolled = viewSettings.scrolled!;
const marginPx = viewSettings.marginPx!;
const gapPercent = viewSettings.gapPercent!;
const showHeader = viewSettings.showHeader!;
const showFooter = viewSettings.showFooter!;
const isCompact = !showHeader && !showFooter;
const marginPx = isCompact ? viewSettings.compactMarginPx : viewSettings.marginPx;
const gapPercent = isCompact ? viewSettings.compactGapPercent : viewSettings.gapPercent;
const animated = viewSettings.animated!;
const maxColumnCount = viewSettings.maxColumnCount!;
const maxInlineSize = getMaxInlineSize(viewSettings);
@@ -33,6 +33,8 @@ const LayoutPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
const [hyphenation, setHyphenation] = useState(viewSettings.hyphenation!);
const [marginPx, setMarginPx] = useState(viewSettings.marginPx!);
const [gapPercent, setGapPercent] = useState(viewSettings.gapPercent!);
const [compactMarginPx, setCompactMarginPx] = useState(viewSettings.compactMarginPx!);
const [compactGapPercent, setCompactGapPercent] = useState(viewSettings.compactGapPercent!);
const [maxColumnCount, setMaxColumnCount] = useState(viewSettings.maxColumnCount!);
const [maxInlineSize, setMaxInlineSize] = useState(viewSettings.maxInlineSize!);
const [maxBlockSize, setMaxBlockSize] = useState(viewSettings.maxBlockSize!);
@@ -87,6 +89,13 @@ const LayoutPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [marginPx]);
useEffect(() => {
if (compactMarginPx === viewSettings.compactMarginPx) return;
saveViewSettings(envConfig, bookKey, 'compactMarginPx', compactMarginPx, false, false);
view?.renderer.setAttribute('margin', `${compactMarginPx}px`);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [compactMarginPx]);
useEffect(() => {
if (gapPercent === viewSettings.gapPercent) return;
saveViewSettings(envConfig, bookKey, 'gapPercent', gapPercent, false, false);
@@ -97,6 +106,16 @@ const LayoutPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [gapPercent]);
useEffect(() => {
if (compactGapPercent === viewSettings.compactGapPercent) return;
saveViewSettings(envConfig, bookKey, 'compactGapPercent', compactGapPercent, false, false);
view?.renderer.setAttribute('gap', `${compactGapPercent}%`);
if (viewSettings.scrolled) {
view?.renderer.setAttribute('flow', 'scrolled');
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [compactGapPercent]);
useEffect(() => {
if (maxColumnCount === viewSettings.maxColumnCount) return;
saveViewSettings(envConfig, bookKey, 'maxColumnCount', maxColumnCount, false, false);
@@ -179,6 +198,22 @@ const LayoutPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [borderColor]);
useEffect(() => {
saveViewSettings(envConfig, bookKey, 'showBarsOnScroll', showBarsOnScroll, false, false);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [showBarsOnScroll]);
const applyMarginAndGap = () => {
const isCompact = !showHeader && !showFooter;
const marginPx = isCompact ? viewSettings.compactMarginPx : viewSettings.marginPx;
const gapPercent = isCompact ? viewSettings.compactGapPercent : viewSettings.gapPercent;
view?.renderer.setAttribute('margin', `${marginPx}px`);
view?.renderer.setAttribute('gap', `${gapPercent}%`);
if (viewSettings.scrolled) {
view?.renderer.setAttribute('flow', 'scrolled');
}
};
useEffect(() => {
if (showHeader === viewSettings.showHeader) return;
if (showHeader && !viewSettings.vertical) {
@@ -194,14 +229,11 @@ const LayoutPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
setViewSettings(bookKey, viewSettings);
}
saveViewSettings(envConfig, bookKey, 'showHeader', showHeader, false, false);
applyMarginAndGap();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [showHeader]);
useEffect(() => {
saveViewSettings(envConfig, bookKey, 'showBarsOnScroll', showBarsOnScroll, false, false);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [showBarsOnScroll]);
useEffect(() => {
if (showFooter === viewSettings.showFooter) return;
if (showFooter && !viewSettings.vertical) {
@@ -217,6 +249,8 @@ const LayoutPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
setViewSettings(bookKey, viewSettings);
}
saveViewSettings(envConfig, bookKey, 'showFooter', showFooter, false, false);
applyMarginAndGap();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [showFooter]);
@@ -399,16 +433,16 @@ const LayoutPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
<div className='divide-base-200 divide-y'>
<NumberInput
label={_('Vertical Margins (px)')}
value={marginPx}
onChange={setMarginPx}
value={showFooter || showHeader ? marginPx : compactMarginPx}
onChange={showFooter || showHeader ? setMarginPx : setCompactMarginPx}
min={!viewSettings.vertical && (showFooter || showHeader) ? 44 : 0}
max={88}
step={4}
/>
<NumberInput
label={_('Horizontal Margins (%)')}
value={gapPercent}
onChange={setGapPercent}
value={showFooter || showHeader ? gapPercent : compactGapPercent}
onChange={showFooter || showHeader ? setGapPercent : setCompactGapPercent}
min={
viewSettings.vertical && (showFooter || showHeader)
? Math.ceil(4800 / window.innerWidth)
@@ -84,6 +84,8 @@ export const DEFAULT_BOOK_FONT: BookFont = {
export const DEFAULT_BOOK_LAYOUT: BookLayout = {
marginPx: 44,
gapPercent: 5,
compactMarginPx: 0,
compactGapPercent: 0,
scrolled: false,
disableClick: false,
swapClickArea: false,
+2
View File
@@ -68,6 +68,8 @@ export type WritingMode = 'auto' | 'horizontal-tb' | 'horizontal-rl' | 'vertical
export interface BookLayout {
marginPx: number;
gapPercent: number;
compactMarginPx: number;
compactGapPercent: number;
scrolled: boolean;
disableClick: boolean;
swapClickArea: boolean;