fix(layout): add top/bottom margin to container in scrolled mode, closes #3463 (#3504)

* fix(layout): add top/bottom margin to container in scrolled mode, closes #3463

When showMarginsOnScroll is enabled, the paginator margins are set to 0
but the FoliateViewer container had no compensating padding, causing
header/footer bars to overlap content. Now the container padding aligns
content top to the bottom of the header bar (gridInsets.top + 44px) and
content bottom to the top of the footer bar (52px + safe area padding).
Also fixes the footer bar height constant from 44 to 52 to match
ProgressBar's actual h-[52px].

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore(ci): cache all crates including local path deps in Tauri build

Add cache-all-crates: 'true' to Swatinem/rust-cache so that vendored
local path dependencies (packages/tauri/crates/, packages/tauri-plugins/)
are cached between CI runs instead of being recompiled from scratch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Huang Xin 2026-03-10 17:40:03 +08:00 committed by GitHub
parent 5646e0cfb5
commit bcd7a90f27
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 20 additions and 5 deletions

View file

@ -123,6 +123,7 @@ jobs:
- uses: Swatinem/rust-cache@v2
with:
key: tauri-cargo
cache-all-crates: 'true'
- name: install system dependencies
run: |

View file

@ -103,6 +103,7 @@ const FoliateViewer: React.FC<{
const doubleClickDisabled = useRef(!!viewSettings?.disableDoubleClick);
const [toastMessage, setToastMessage] = useState('');
const [loading, setLoading] = useState(false);
const [scrollMargins, setScrollMargins] = useState({ top: 0, bottom: 0 });
const docLoaded = useRef(false);
useAutoFocus<HTMLDivElement>({ ref: containerRef });
@ -537,7 +538,7 @@ const FoliateViewer: React.FC<{
const ttsBarHeight =
viewState?.ttsEnabled && viewSettings.showTTSBar ? 52 + gridInsets.bottom * 0.33 : 0;
const moreBottomInset = showBottomFooter
? Math.max(0, Math.max(ttsBarHeight, 44) - insets.bottom)
? Math.max(0, Math.max(ttsBarHeight, 52) - insets.bottom)
: Math.max(0, ttsBarHeight);
const moreRightInset = showDoubleBorderHeader ? 32 : 0;
const moreLeftInset = showDoubleBorderFooter ? 32 : 0;
@ -551,6 +552,18 @@ const FoliateViewer: React.FC<{
viewRef.current?.renderer.setAttribute('margin-right', `${rightMargin}px`);
viewRef.current?.renderer.setAttribute('margin-bottom', `${viewMargins ? 0 : bottomMargin}px`);
viewRef.current?.renderer.setAttribute('margin-left', `${leftMargin}px`);
if (viewMargins) {
const showBarsOnScroll = viewSettings.showBarsOnScroll;
const headerVisible = showTopHeader && showBarsOnScroll;
const footerVisible = showBottomFooter && showBarsOnScroll;
const safeBottomPadding = appService?.hasSafeAreaInset ? gridInsets.bottom * 0.33 : 0;
const footerBarHeight = 52 + safeBottomPadding;
const scrollTop = headerVisible ? gridInsets.top + 44 : 0;
const scrollBottom = footerVisible ? Math.max(footerBarHeight, ttsBarHeight) : ttsBarHeight;
setScrollMargins({ top: scrollTop, bottom: scrollBottom });
} else {
setScrollMargins({ top: 0, bottom: 0 });
}
viewRef.current?.renderer.setAttribute('gap', `${viewSettings.gapPercent}%`);
if (viewSettings.scrolled) {
viewRef.current?.renderer.setAttribute('flow', 'scrolled');
@ -627,11 +640,12 @@ const FoliateViewer: React.FC<{
viewSettings?.showHeader,
viewSettings?.showFooter,
viewSettings?.showTTSBar,
viewSettings?.showBarsOnScroll,
viewSettings?.showMarginsOnScroll,
viewSettings?.scrolled,
viewState?.ttsEnabled,
]);
const showViewMargins = viewSettings?.showMarginsOnScroll && viewSettings?.scrolled;
return (
<>
{selectedImage && (
@ -661,8 +675,8 @@ const FoliateViewer: React.FC<{
viewState?.loading && 'bg-base-100',
)}
style={{
paddingTop: showViewMargins ? insets.top : 0,
paddingBottom: showViewMargins ? insets.bottom : 0,
paddingTop: scrollMargins.top,
paddingBottom: scrollMargins.bottom,
}}
{...mouseHandlers}
{...touchHandlers}