fix(reader): keep footer compact on mobile and clear text under chrome
Release / build-and-push (push) Successful in 2m34s
Release / build-and-push (push) Successful in 2m34s
On phones the footer's progress cell rendered the full chapter title (e.g. 'Long Chapter Name · 5 / 12') in a div with no max-width or nowrap, so the text wrapped to multiple lines and ballooned the bottom bar. Combined with viewport offsets that were computed from assumed pixel heights with ~0px margin, the book text slipped underneath the bars.
Chapter label in footer: split #progress-display into two spans (progressLabel hidden on mobile via 'hidden sm:inline', progressMain always shown) and cap it with 'truncate whitespace-nowrap max-w-[5rem] sm:max-w-none' so it can never wrap or grow the bar. Phones now show just '5 / 12'; larger screens keep 'Chapter · 5 / 12'.
Viewport offset: replace the fragile hardcoded calc() with runtime measurement. Gave the chrome bars ids (reader-topbar/reader-bottombar) and added updateViewportInsets(), which sets #reader-viewport top/bottom from each bar's real offsetHeight (which already includes env(safe-area-inset-*) padding) plus a 6px margin. It runs on init and refreshes on resize, orientationchange, and via a ResizeObserver, so the content area tracks the actual chrome height on any DPI, notch, home-indicator, or zoom level instead of guessing.
Refactored formatProgress into formatProgressParts (returns {label, main}; only chapter mode sets a label) with a setProgress() helper wiring progressLabel/progressMain/progressText across the relocate, cycleProgressMode, and applyProgressMode call sites. Rebuilt reader_templ.go and style.css.
This commit is contained in:
+13
-11
@@ -71,7 +71,7 @@ templ Reader(user User, metadata ReaderMetadata, progress ReadingProgress, bookm
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="reader-viewport" class="absolute inset-x-0 top-[calc(44px+env(safe-area-inset-top))] sm:top-[calc(60px+env(safe-area-inset-top))] bottom-[calc(48px+env(safe-area-inset-bottom))] sm:bottom-[calc(60px+env(safe-area-inset-bottom))]">
|
||||
<div id="reader-viewport" class="absolute inset-x-0" style="top: 56px; bottom: 56px;">
|
||||
<foliate-view id="reader-view" class="block w-full h-full"></foliate-view>
|
||||
</div>
|
||||
@DictionaryPopup()
|
||||
@@ -82,7 +82,7 @@ templ Reader(user User, metadata ReaderMetadata, progress ReadingProgress, bookm
|
||||
templ ReaderChrome(user User, metadata ReaderMetadata, progress ReadingProgress) {
|
||||
<div id="reader-chrome" class="transition-opacity duration-300">
|
||||
<!-- Top bar -->
|
||||
<div class="fixed top-0 left-0 right-0 bg-opacity-95 backdrop-blur border-b z-40 pt-[env(safe-area-inset-top)]" style="background-color: var(--bg-primary);">
|
||||
<div id="reader-topbar" class="fixed top-0 left-0 right-0 bg-opacity-95 backdrop-blur border-b z-40 pt-[env(safe-area-inset-top)]" style="background-color: var(--bg-primary);">
|
||||
<div class="flex items-center justify-between px-3 py-2 sm:px-4 sm:py-3">
|
||||
<a href={ "/media/" + metadata.MediaItemID } class="text-base sm:text-lg hover:underline">
|
||||
← Back
|
||||
@@ -97,7 +97,7 @@ templ ReaderChrome(user User, metadata ReaderMetadata, progress ReadingProgress)
|
||||
</button>
|
||||
</div>
|
||||
</div> <!-- Bottom bar -->
|
||||
<div class="fixed bottom-0 left-0 right-0 bg-opacity-95 backdrop-blur border-t z-40 pb-[env(safe-area-inset-bottom)]" style="background-color: var(--bg-primary);">
|
||||
<div id="reader-bottombar" class="fixed bottom-0 left-0 right-0 bg-opacity-95 backdrop-blur border-t z-40 pb-[env(safe-area-inset-bottom)]" style="background-color: var(--bg-primary);">
|
||||
<div class="flex items-center px-1.5 py-1.5 gap-0.5 sm:px-2 sm:py-2 sm:gap-1">
|
||||
<!-- Left navigation -->
|
||||
<button @click="goLeft()" class="p-1.5 sm:p-2 rounded-lg hover:bg-gray-700" title="Go Left" aria-label="Go left">
|
||||
@@ -162,16 +162,18 @@ templ ReaderChrome(user User, metadata ReaderMetadata, progress ReadingProgress)
|
||||
<!-- Separator -->
|
||||
<div class="w-px h-6 bg-gray-600 mx-1"></div>
|
||||
<!-- Progress display -->
|
||||
<div id="progress-display" x-text="progressText" @click="cycleProgressMode()" :title="progressTooltip()" class="text-sm min-w-[4rem] text-center cursor-pointer">
|
||||
if progress.FormatGroup == "reflowable" {
|
||||
if metadata.EstimatedPages > 0 {
|
||||
{ fmt.Sprintf("%.0f%% · Page %d/%d", progress.Percentage, progress.CurrentPage, metadata.EstimatedPages) }
|
||||
<div id="progress-display" @click="cycleProgressMode()" :title="progressTooltip()" class="text-sm min-w-[4rem] max-w-[5rem] sm:max-w-none text-center cursor-pointer truncate whitespace-nowrap overflow-hidden">
|
||||
<span class="hidden sm:inline" x-text="progressLabel"></span><span x-text="progressMain">
|
||||
if progress.FormatGroup == "reflowable" {
|
||||
if metadata.EstimatedPages > 0 {
|
||||
{ fmt.Sprintf("%.0f%% · Page %d/%d", progress.Percentage, progress.CurrentPage, metadata.EstimatedPages) }
|
||||
} else {
|
||||
{ fmt.Sprintf("%.0f%%", progress.Percentage) }
|
||||
}
|
||||
} else {
|
||||
{ fmt.Sprintf("%.0f%%", progress.Percentage) }
|
||||
{ fmt.Sprintf("%d/%d", progress.CurrentPage, progress.TotalPages) }
|
||||
}
|
||||
} else {
|
||||
{ fmt.Sprintf("%d/%d", progress.CurrentPage, progress.TotalPages) }
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
<!-- Separator -->
|
||||
<div class="w-px h-6 bg-gray-600 mx-1"></div>
|
||||
|
||||
Reference in New Issue
Block a user