Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5c2270007 |
+13
-11
@@ -71,7 +71,7 @@ templ Reader(user User, metadata ReaderMetadata, progress ReadingProgress, bookm
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</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>
|
<foliate-view id="reader-view" class="block w-full h-full"></foliate-view>
|
||||||
</div>
|
</div>
|
||||||
@DictionaryPopup()
|
@DictionaryPopup()
|
||||||
@@ -82,7 +82,7 @@ templ Reader(user User, metadata ReaderMetadata, progress ReadingProgress, bookm
|
|||||||
templ ReaderChrome(user User, metadata ReaderMetadata, progress ReadingProgress) {
|
templ ReaderChrome(user User, metadata ReaderMetadata, progress ReadingProgress) {
|
||||||
<div id="reader-chrome" class="transition-opacity duration-300">
|
<div id="reader-chrome" class="transition-opacity duration-300">
|
||||||
<!-- Top bar -->
|
<!-- 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">
|
<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">
|
<a href={ "/media/" + metadata.MediaItemID } class="text-base sm:text-lg hover:underline">
|
||||||
← Back
|
← Back
|
||||||
@@ -97,7 +97,7 @@ templ ReaderChrome(user User, metadata ReaderMetadata, progress ReadingProgress)
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div> <!-- Bottom bar -->
|
</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">
|
<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 -->
|
<!-- 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">
|
<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 -->
|
<!-- Separator -->
|
||||||
<div class="w-px h-6 bg-gray-600 mx-1"></div>
|
<div class="w-px h-6 bg-gray-600 mx-1"></div>
|
||||||
<!-- Progress display -->
|
<!-- Progress display -->
|
||||||
<div id="progress-display" x-text="progressText" @click="cycleProgressMode()" :title="progressTooltip()" class="text-sm min-w-[4rem] text-center cursor-pointer">
|
<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">
|
||||||
if progress.FormatGroup == "reflowable" {
|
<span class="hidden sm:inline" x-text="progressLabel"></span><span x-text="progressMain">
|
||||||
if metadata.EstimatedPages > 0 {
|
if progress.FormatGroup == "reflowable" {
|
||||||
{ fmt.Sprintf("%.0f%% · Page %d/%d", progress.Percentage, progress.CurrentPage, metadata.EstimatedPages) }
|
if metadata.EstimatedPages > 0 {
|
||||||
|
{ fmt.Sprintf("%.0f%% · Page %d/%d", progress.Percentage, progress.CurrentPage, metadata.EstimatedPages) }
|
||||||
|
} else {
|
||||||
|
{ fmt.Sprintf("%.0f%%", progress.Percentage) }
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
{ fmt.Sprintf("%.0f%%", progress.Percentage) }
|
{ fmt.Sprintf("%d/%d", progress.CurrentPage, progress.TotalPages) }
|
||||||
}
|
}
|
||||||
} else {
|
</span>
|
||||||
{ fmt.Sprintf("%d/%d", progress.CurrentPage, progress.TotalPages) }
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
<!-- Separator -->
|
<!-- Separator -->
|
||||||
<div class="w-px h-6 bg-gray-600 mx-1"></div>
|
<div class="w-px h-6 bg-gray-600 mx-1"></div>
|
||||||
|
|||||||
+10
-10
@@ -126,7 +126,7 @@ func Reader(user User, metadata ReaderMetadata, progress ReadingProgress, bookma
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</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))]\"><foliate-view id=\"reader-view\" class=\"block w-full h-full\"></foliate-view></div>")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</div></div></div><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>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@@ -163,7 +163,7 @@ func ReaderChrome(user User, metadata ReaderMetadata, progress ReadingProgress)
|
|||||||
templ_7745c5c3_Var4 = templ.NopComponent
|
templ_7745c5c3_Var4 = templ.NopComponent
|
||||||
}
|
}
|
||||||
ctx = templ.ClearChildren(ctx)
|
ctx = templ.ClearChildren(ctx)
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<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 class=\"flex items-center justify-between px-3 py-2 sm:px-4 sm:py-3\"><a href=\"")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "<div id=\"reader-chrome\" class=\"transition-opacity duration-300\"><!-- Top bar --><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=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@@ -189,7 +189,7 @@ func ReaderChrome(user User, metadata ReaderMetadata, progress ReadingProgress)
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</h1><button @click=\"toggleSettings()\" class=\"p-1.5 sm:p-2 rounded-lg hover:bg-gray-700\" title=\"Settings\">⚙️</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 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\"><svg class=\"reader-icon\" width=\"24\" height=\"24\" aria-hidden=\"true\"><path d=\"M 15 6 L 9 12 L 15 18\"></path></svg></button><!-- Progress slider --><input id=\"progress-slider\" type=\"range\" min=\"0\" max=\"1\" step=\"any\" list=\"tick-marks\" @input=\"goToFraction($event.target.value)\" class=\"grow\"> <datalist id=\"tick-marks\"></datalist><!-- Right navigation --><button @click=\"goRight()\" class=\"p-1.5 sm:p-2 rounded-lg hover:bg-gray-700\" title=\"Go Right\" aria-label=\"Go right\"><svg class=\"reader-icon\" width=\"24\" height=\"24\" aria-hidden=\"true\"><path d=\"M 9 6 L 15 12 L 9 18\"></path></svg></button><!-- Separator --><div class=\"w-px h-6 bg-gray-600 mx-1\"></div><!-- Zoom controls (fixed-layout only) --><template x-if=\"isFixedLayout\"><div class=\"flex items-center gap-1\"><!-- Zoom out --><button @click=\"zoomOut()\" class=\"p-1.5 sm:p-2 rounded-lg hover:bg-gray-700\" title=\"Zoom Out\" aria-label=\"Zoom out\"><svg class=\"reader-icon\" width=\"20\" height=\"20\" aria-hidden=\"true\"><path d=\"M 5 10 L 15 10\"></path></svg></button><!-- Zoom percentage --><button @click=\"resetZoom()\" class=\"text-xs px-1 rounded-lg hover:bg-gray-700 min-w-[3rem]\" title=\"Reset Zoom\" aria-label=\"Reset zoom\"><span x-text=\"zoomPercent + '%'\">100%</span></button><!-- Zoom in --><button @click=\"zoomIn()\" class=\"p-1.5 sm:p-2 rounded-lg hover:bg-gray-700\" title=\"Zoom In\" aria-label=\"Zoom in\"><svg class=\"reader-icon\" width=\"20\" height=\"20\" aria-hidden=\"true\"><path d=\"M 10 5 L 10 15 M 5 10 L 15 10\"></path></svg></button><!-- Magnifier --><button @click=\"toggleMagnifier()\" class=\"p-1.5 sm:p-2 rounded-lg hover:bg-gray-700\" title=\"Magnifier\" aria-label=\"Toggle magnifier\"><svg class=\"reader-icon\" width=\"20\" height=\"20\" aria-hidden=\"true\"><circle cx=\"9\" cy=\"9\" r=\"5\"></circle> <path d=\"M 13 13 L 18 18\"></path></svg></button><!-- Pan/Select mode (PDF only) --><button x-show=\"isPDF\" @click=\"toggleInteractionMode()\" class=\"p-1.5 sm:p-2 rounded-lg hover:bg-gray-700\" title=\"Pan/Select Mode\" aria-label=\"Toggle pan/select mode\"><svg class=\"reader-icon\" width=\"20\" height=\"20\" aria-hidden=\"true\"><path d=\"M 5 3 v 12 M 5 15 l -2 2 M 5 15 l 2 2 M 5 3 l 3 3\"></path></svg></button></div></template><!-- 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\">")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</h1><button @click=\"toggleSettings()\" class=\"p-1.5 sm:p-2 rounded-lg hover:bg-gray-700\" title=\"Settings\">⚙️</button></div></div><!-- Bottom bar --><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\"><svg class=\"reader-icon\" width=\"24\" height=\"24\" aria-hidden=\"true\"><path d=\"M 15 6 L 9 12 L 15 18\"></path></svg></button><!-- Progress slider --><input id=\"progress-slider\" type=\"range\" min=\"0\" max=\"1\" step=\"any\" list=\"tick-marks\" @input=\"goToFraction($event.target.value)\" class=\"grow\"> <datalist id=\"tick-marks\"></datalist><!-- Right navigation --><button @click=\"goRight()\" class=\"p-1.5 sm:p-2 rounded-lg hover:bg-gray-700\" title=\"Go Right\" aria-label=\"Go right\"><svg class=\"reader-icon\" width=\"24\" height=\"24\" aria-hidden=\"true\"><path d=\"M 9 6 L 15 12 L 9 18\"></path></svg></button><!-- Separator --><div class=\"w-px h-6 bg-gray-600 mx-1\"></div><!-- Zoom controls (fixed-layout only) --><template x-if=\"isFixedLayout\"><div class=\"flex items-center gap-1\"><!-- Zoom out --><button @click=\"zoomOut()\" class=\"p-1.5 sm:p-2 rounded-lg hover:bg-gray-700\" title=\"Zoom Out\" aria-label=\"Zoom out\"><svg class=\"reader-icon\" width=\"20\" height=\"20\" aria-hidden=\"true\"><path d=\"M 5 10 L 15 10\"></path></svg></button><!-- Zoom percentage --><button @click=\"resetZoom()\" class=\"text-xs px-1 rounded-lg hover:bg-gray-700 min-w-[3rem]\" title=\"Reset Zoom\" aria-label=\"Reset zoom\"><span x-text=\"zoomPercent + '%'\">100%</span></button><!-- Zoom in --><button @click=\"zoomIn()\" class=\"p-1.5 sm:p-2 rounded-lg hover:bg-gray-700\" title=\"Zoom In\" aria-label=\"Zoom in\"><svg class=\"reader-icon\" width=\"20\" height=\"20\" aria-hidden=\"true\"><path d=\"M 10 5 L 10 15 M 5 10 L 15 10\"></path></svg></button><!-- Magnifier --><button @click=\"toggleMagnifier()\" class=\"p-1.5 sm:p-2 rounded-lg hover:bg-gray-700\" title=\"Magnifier\" aria-label=\"Toggle magnifier\"><svg class=\"reader-icon\" width=\"20\" height=\"20\" aria-hidden=\"true\"><circle cx=\"9\" cy=\"9\" r=\"5\"></circle> <path d=\"M 13 13 L 18 18\"></path></svg></button><!-- Pan/Select mode (PDF only) --><button x-show=\"isPDF\" @click=\"toggleInteractionMode()\" class=\"p-1.5 sm:p-2 rounded-lg hover:bg-gray-700\" title=\"Pan/Select Mode\" aria-label=\"Toggle pan/select mode\"><svg class=\"reader-icon\" width=\"20\" height=\"20\" aria-hidden=\"true\"><path d=\"M 5 3 v 12 M 5 15 l -2 2 M 5 15 l 2 2 M 5 3 l 3 3\"></path></svg></button></div></template><!-- Separator --><div class=\"w-px h-6 bg-gray-600 mx-1\"></div><!-- Progress display --><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 templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@@ -198,7 +198,7 @@ func ReaderChrome(user User, metadata ReaderMetadata, progress ReadingProgress)
|
|||||||
var templ_7745c5c3_Var7 string
|
var templ_7745c5c3_Var7 string
|
||||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.0f%% · Page %d/%d", progress.Percentage, progress.CurrentPage, metadata.EstimatedPages))
|
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.0f%% · Page %d/%d", progress.Percentage, progress.CurrentPage, metadata.EstimatedPages))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/reader.templ`, Line: 168, Col: 112}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/reader.templ`, Line: 169, Col: 113}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -208,7 +208,7 @@ func ReaderChrome(user User, metadata ReaderMetadata, progress ReadingProgress)
|
|||||||
var templ_7745c5c3_Var8 string
|
var templ_7745c5c3_Var8 string
|
||||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.0f%%", progress.Percentage))
|
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%.0f%%", progress.Percentage))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/reader.templ`, Line: 170, Col: 51}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/reader.templ`, Line: 171, Col: 52}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -219,14 +219,14 @@ func ReaderChrome(user User, metadata ReaderMetadata, progress ReadingProgress)
|
|||||||
var templ_7745c5c3_Var9 string
|
var templ_7745c5c3_Var9 string
|
||||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d/%d", progress.CurrentPage, progress.TotalPages))
|
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d/%d", progress.CurrentPage, progress.TotalPages))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/reader.templ`, Line: 173, Col: 71}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/reader.templ`, Line: 174, Col: 72}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</div><!-- Separator --><div class=\"w-px h-6 bg-gray-600 mx-1\"></div><!-- Action buttons --><div class=\"flex items-center gap-1\"><button @click=\"toggleTOC()\" class=\"p-1.5 sm:p-2 rounded-lg hover:bg-gray-700\" title=\"Table of Contents\">📖</button> <button @click=\"addBookmark()\" class=\"p-1.5 sm:p-2 rounded-lg hover:bg-gray-700\" title=\"Bookmark\">🏷️</button> <button @click=\"toggleBookmarks()\" class=\"p-1.5 sm:p-2 rounded-lg hover:bg-gray-700\" title=\"Notes\">📝</button></div></div></div></div>")
|
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</span></div><!-- Separator --><div class=\"w-px h-6 bg-gray-600 mx-1\"></div><!-- Action buttons --><div class=\"flex items-center gap-1\"><button @click=\"toggleTOC()\" class=\"p-1.5 sm:p-2 rounded-lg hover:bg-gray-700\" title=\"Table of Contents\">📖</button> <button @click=\"addBookmark()\" class=\"p-1.5 sm:p-2 rounded-lg hover:bg-gray-700\" title=\"Bookmark\">🏷️</button> <button @click=\"toggleBookmarks()\" class=\"p-1.5 sm:p-2 rounded-lg hover:bg-gray-700\" title=\"Notes\">📝</button></div></div></div></div>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@@ -359,7 +359,7 @@ func ReaderBookmarksPanel(bookmarks []Bookmark) templ.Component {
|
|||||||
var templ_7745c5c3_Var14 string
|
var templ_7745c5c3_Var14 string
|
||||||
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.ResolveAttributeValue(bookmark.CfiPosition)
|
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.ResolveAttributeValue(bookmark.CfiPosition)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/reader.templ`, Line: 390, Col: 38}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/reader.templ`, Line: 392, Col: 38}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var14)
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var14)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -372,7 +372,7 @@ func ReaderBookmarksPanel(bookmarks []Bookmark) templ.Component {
|
|||||||
var templ_7745c5c3_Var15 string
|
var templ_7745c5c3_Var15 string
|
||||||
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(bookmark.Title)
|
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(bookmark.Title)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/reader.templ`, Line: 393, Col: 49}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/reader.templ`, Line: 395, Col: 49}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@@ -385,7 +385,7 @@ func ReaderBookmarksPanel(bookmarks []Bookmark) templ.Component {
|
|||||||
var templ_7745c5c3_Var16 string
|
var templ_7745c5c3_Var16 string
|
||||||
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(bookmark.Position)
|
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(bookmark.Position)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/reader.templ`, Line: 395, Col: 27}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/reader.templ`, Line: 397, Col: 27}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
|
|||||||
+93
-51
@@ -372,6 +372,8 @@ document.addEventListener("alpine:init", () => {
|
|||||||
interactionMode: "select" as string,
|
interactionMode: "select" as string,
|
||||||
magnifierEnabled: false,
|
magnifierEnabled: false,
|
||||||
progressText: "",
|
progressText: "",
|
||||||
|
progressLabel: "",
|
||||||
|
progressMain: "",
|
||||||
sliderValue: 0,
|
sliderValue: 0,
|
||||||
settings: null as ReaderSettings | null,
|
settings: null as ReaderSettings | null,
|
||||||
justify: true,
|
justify: true,
|
||||||
@@ -489,21 +491,20 @@ document.addEventListener("alpine:init", () => {
|
|||||||
tocItem,
|
tocItem,
|
||||||
section,
|
section,
|
||||||
};
|
};
|
||||||
const progressStr = this.formatProgress(
|
const progressParts = this.formatProgressParts(
|
||||||
fraction,
|
fraction,
|
||||||
location,
|
location,
|
||||||
pageItem,
|
pageItem,
|
||||||
tocItem,
|
tocItem,
|
||||||
section,
|
section,
|
||||||
);
|
);
|
||||||
this.progressText = progressStr;
|
this.setProgress(progressParts);
|
||||||
this.sliderValue = fraction;
|
this.sliderValue = fraction;
|
||||||
const slider = document.getElementById(
|
const slider = document.getElementById(
|
||||||
"progress-slider",
|
"progress-slider",
|
||||||
) as HTMLInputElement;
|
) as HTMLInputElement;
|
||||||
if (slider) {
|
if (slider) {
|
||||||
slider.value = fraction;
|
slider.value = fraction;
|
||||||
slider.title = progressStr;
|
|
||||||
}
|
}
|
||||||
const range = e.detail.range as Range | undefined;
|
const range = e.detail.range as Range | undefined;
|
||||||
if (range) {
|
if (range) {
|
||||||
@@ -547,6 +548,34 @@ document.addEventListener("alpine:init", () => {
|
|||||||
}
|
}
|
||||||
this.initTime = Date.now();
|
this.initTime = Date.now();
|
||||||
this.fetchReadingSpeed();
|
this.fetchReadingSpeed();
|
||||||
|
this.setupViewportInsets();
|
||||||
|
},
|
||||||
|
updateViewportInsets() {
|
||||||
|
const top = document.getElementById("reader-topbar");
|
||||||
|
const bot = document.getElementById("reader-bottombar");
|
||||||
|
const vp = document.getElementById("reader-viewport");
|
||||||
|
if (!top || !bot || !vp) return;
|
||||||
|
const margin = 6;
|
||||||
|
vp.style.setProperty("top", `${top.offsetHeight + margin}px`);
|
||||||
|
vp.style.setProperty("bottom", `${bot.offsetHeight + margin}px`);
|
||||||
|
},
|
||||||
|
setupViewportInsets() {
|
||||||
|
const top = document.getElementById("reader-topbar");
|
||||||
|
const bot = document.getElementById("reader-bottombar");
|
||||||
|
this.updateViewportInsets();
|
||||||
|
window.addEventListener("resize", () => this.updateViewportInsets());
|
||||||
|
window.addEventListener("orientationchange", () =>
|
||||||
|
setTimeout(() => this.updateViewportInsets(), 250),
|
||||||
|
);
|
||||||
|
if (
|
||||||
|
typeof ResizeObserver !== "undefined" &&
|
||||||
|
top &&
|
||||||
|
bot
|
||||||
|
) {
|
||||||
|
const ro = new ResizeObserver(() => this.updateViewportInsets());
|
||||||
|
ro.observe(top);
|
||||||
|
ro.observe(bot);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
debouncedSaveProgress(fraction: number, location: any, cfi: string) {
|
debouncedSaveProgress(fraction: number, location: any, cfi: string) {
|
||||||
if (Date.now() - this.initTime < 5000) return;
|
if (Date.now() - this.initTime < 5000) return;
|
||||||
@@ -774,19 +803,20 @@ document.addEventListener("alpine:init", () => {
|
|||||||
/* ignore bookmark errors for now */
|
/* ignore bookmark errors for now */
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
formatProgress(
|
formatProgressParts(
|
||||||
fraction: number,
|
fraction: number,
|
||||||
location: { current: number; next: number; total: number },
|
location: { current: number; next: number; total: number },
|
||||||
pageItem: { id: number; label: string; href: string },
|
pageItem: { id: number; label: string; href: string },
|
||||||
tocItem: FoliateTocItem | null,
|
tocItem: FoliateTocItem | null,
|
||||||
section: { current: number; total: number },
|
section: { current: number; total: number },
|
||||||
): string {
|
): { label: string; main: string } {
|
||||||
const percent = new Intl.NumberFormat("en", { style: "percent" }).format(
|
const percent = new Intl.NumberFormat("en", { style: "percent" }).format(
|
||||||
fraction,
|
fraction,
|
||||||
);
|
);
|
||||||
|
const chapterLabel = tocItem?.label ? `${tocItem.label} · ` : "";
|
||||||
switch (this.progressMode) {
|
switch (this.progressMode) {
|
||||||
case "percentage":
|
case "percentage":
|
||||||
return percent;
|
return { label: "", main: percent };
|
||||||
case "chapter": {
|
case "chapter": {
|
||||||
if (this.isFixedLayout && tocItem && this.chapterBoundaries.length > 0) {
|
if (this.isFixedLayout && tocItem && this.chapterBoundaries.length > 0) {
|
||||||
const totalSections = this.book?.sections?.filter(
|
const totalSections = this.book?.sections?.filter(
|
||||||
@@ -809,10 +839,10 @@ document.addEventListener("alpine:init", () => {
|
|||||||
1,
|
1,
|
||||||
Math.min(currentPage - chapterStart + 1, chapterPages),
|
Math.min(currentPage - chapterStart + 1, chapterPages),
|
||||||
);
|
);
|
||||||
const label = tocItem.label
|
return {
|
||||||
? `${tocItem.label} · `
|
label: chapterLabel,
|
||||||
: "";
|
main: `${currentInChapter} / ${chapterPages}`,
|
||||||
return `${label}${currentInChapter} / ${chapterPages}`;
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tocItem && this.chapterBoundaries.length > 0) {
|
if (tocItem && this.chapterBoundaries.length > 0) {
|
||||||
@@ -836,10 +866,10 @@ document.addEventListener("alpine:init", () => {
|
|||||||
1,
|
1,
|
||||||
Math.min(currentPage - chapterStart + 1, chapterPages),
|
Math.min(currentPage - chapterStart + 1, chapterPages),
|
||||||
);
|
);
|
||||||
const label = tocItem.label
|
return {
|
||||||
? `${tocItem.label} · `
|
label: chapterLabel,
|
||||||
: "";
|
main: `${currentInChapter} / ${chapterPages}`,
|
||||||
return `${label}${currentInChapter} / ${chapterPages}`;
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (section && this.sectionFractionsArr.length > 1) {
|
if (section && this.sectionFractionsArr.length > 1) {
|
||||||
@@ -859,16 +889,19 @@ document.addEventListener("alpine:init", () => {
|
|||||||
Math.round((fraction - startFrac) * pageBase),
|
Math.round((fraction - startFrac) * pageBase),
|
||||||
);
|
);
|
||||||
const clamped = Math.min(currentInSec, totalInSec);
|
const clamped = Math.min(currentInSec, totalInSec);
|
||||||
const label = tocItem?.label
|
return {
|
||||||
? `${tocItem.label} · `
|
label: chapterLabel,
|
||||||
: "";
|
main: `${clamped} / ${totalInSec}`,
|
||||||
return `${label}${clamped} / ${totalInSec}`;
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (location.total > 0) {
|
if (location.total > 0) {
|
||||||
return `${percent} · ${location.current} / ${location.total}`;
|
return {
|
||||||
|
label: "",
|
||||||
|
main: `${percent} · ${location.current} / ${location.total}`,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return percent;
|
return { label: "", main: percent };
|
||||||
}
|
}
|
||||||
case "time-left": {
|
case "time-left": {
|
||||||
if (this.readingSpeedPpm > 0 && location.total > 0) {
|
if (this.readingSpeedPpm > 0 && location.total > 0) {
|
||||||
@@ -877,30 +910,47 @@ document.addEventListener("alpine:init", () => {
|
|||||||
if (mins >= 60) {
|
if (mins >= 60) {
|
||||||
const hrs = Math.floor(mins / 60);
|
const hrs = Math.floor(mins / 60);
|
||||||
const m = mins % 60;
|
const m = mins % 60;
|
||||||
return `${percent} · ~${hrs}h ${m}m left`;
|
return { label: "", main: `${percent} · ~${hrs}h ${m}m left` };
|
||||||
}
|
}
|
||||||
return `${percent} · ~${mins} min left`;
|
return { label: "", main: `${percent} · ~${mins} min left` };
|
||||||
}
|
}
|
||||||
return `${percent} · ~-- min left`;
|
return { label: "", main: `${percent} · ~-- min left` };
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
if (this.isFixedLayout) {
|
if (this.isFixedLayout) {
|
||||||
const pageInfo = this.getRenderedPageInfo();
|
const pageInfo = this.getRenderedPageInfo();
|
||||||
if (pageInfo) {
|
if (pageInfo) {
|
||||||
return `${pageInfo.current} / ${pageInfo.total}`;
|
return { label: "", main: `${pageInfo.current} / ${pageInfo.total}` };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pageItem) {
|
if (pageItem) {
|
||||||
return `${percent} · Page ${pageItem.label}`;
|
return { label: "", main: `${percent} · Page ${pageItem.label}` };
|
||||||
}
|
}
|
||||||
const pageInfoReflow = this.getRenderedPageInfo();
|
const pageInfoReflow = this.getRenderedPageInfo();
|
||||||
if (pageInfoReflow) {
|
if (pageInfoReflow) {
|
||||||
return `${percent} · ${pageInfoReflow.current + 1} / ${pageInfoReflow.total}`;
|
return {
|
||||||
|
label: "",
|
||||||
|
main: `${percent} · ${pageInfoReflow.current + 1} / ${pageInfoReflow.total}`,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return `${percent} · ${location.current} / ${location.total}`;
|
return {
|
||||||
|
label: "",
|
||||||
|
main: `${percent} · ${location.current} / ${location.total}`,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
setProgress(parts: { label: string; main: string }, sliderTitle?: string) {
|
||||||
|
this.progressLabel = parts.label;
|
||||||
|
this.progressMain = parts.main;
|
||||||
|
this.progressText = parts.label + parts.main;
|
||||||
|
const slider = document.getElementById(
|
||||||
|
"progress-slider",
|
||||||
|
) as HTMLInputElement;
|
||||||
|
if (slider) {
|
||||||
|
slider.title = sliderTitle ?? this.progressText;
|
||||||
|
}
|
||||||
|
},
|
||||||
cycleProgressMode() {
|
cycleProgressMode() {
|
||||||
const modes = ["pages", "chapter", "percentage", "time-left"];
|
const modes = ["pages", "chapter", "percentage", "time-left"];
|
||||||
const idx = modes.indexOf(this.progressMode);
|
const idx = modes.indexOf(this.progressMode);
|
||||||
@@ -909,19 +959,15 @@ document.addEventListener("alpine:init", () => {
|
|||||||
if (this.lastRelocateDetail) {
|
if (this.lastRelocateDetail) {
|
||||||
const { fraction, location, pageItem, tocItem, section } =
|
const { fraction, location, pageItem, tocItem, section } =
|
||||||
this.lastRelocateDetail;
|
this.lastRelocateDetail;
|
||||||
this.progressText = this.formatProgress(
|
this.setProgress(
|
||||||
fraction,
|
this.formatProgressParts(
|
||||||
location,
|
fraction,
|
||||||
pageItem,
|
location,
|
||||||
tocItem,
|
pageItem,
|
||||||
section,
|
tocItem,
|
||||||
|
section,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
const slider = document.getElementById(
|
|
||||||
"progress-slider",
|
|
||||||
) as HTMLInputElement;
|
|
||||||
if (slider) {
|
|
||||||
slider.title = this.progressText;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async fetchReadingSpeed() {
|
async fetchReadingSpeed() {
|
||||||
@@ -944,19 +990,15 @@ document.addEventListener("alpine:init", () => {
|
|||||||
if (this.lastRelocateDetail) {
|
if (this.lastRelocateDetail) {
|
||||||
const { fraction, location, pageItem, tocItem, section } =
|
const { fraction, location, pageItem, tocItem, section } =
|
||||||
this.lastRelocateDetail;
|
this.lastRelocateDetail;
|
||||||
this.progressText = this.formatProgress(
|
this.setProgress(
|
||||||
fraction,
|
this.formatProgressParts(
|
||||||
location,
|
fraction,
|
||||||
pageItem,
|
location,
|
||||||
tocItem,
|
pageItem,
|
||||||
section,
|
tocItem,
|
||||||
|
section,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
const slider = document.getElementById(
|
|
||||||
"progress-slider",
|
|
||||||
) as HTMLInputElement;
|
|
||||||
if (slider) {
|
|
||||||
slider.title = this.progressText;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computeFixedLayoutChapterBoundaries() {
|
computeFixedLayoutChapterBoundaries() {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user