Add footer bar for flip paging

This commit is contained in:
chrox
2024-10-24 23:48:06 +02:00
parent 4263ab7fc4
commit 4e6b13960b
6 changed files with 79 additions and 6 deletions
@@ -48,6 +48,8 @@ export interface FoliateView extends HTMLElement {
init: (options: { lastLocation: string }) => void;
goTo: (href: string) => void;
goToFraction: (fraction: number) => void;
goLeft: () => void;
goRight: () => void;
renderer: {
setStyles: (css: string) => void;
next: () => Promise<void>;
@@ -3,8 +3,8 @@
import * as React from 'react';
import { useState } from 'react';
import { useSearchParams, useRouter } from 'next/navigation';
import { BsLayoutSidebar } from 'react-icons/bs';
import { VscLayoutSidebarLeft, VscLayoutSidebarLeftOff } from 'react-icons/vsc';
import { RiArrowLeftWideLine, RiArrowRightWideLine } from 'react-icons/ri';
import { useEnv } from '@/context/EnvContext';
import { useReaderStore, DEFAULT_BOOK_STATE } from '@/store/readerStore';
@@ -20,6 +20,7 @@ const ReaderContent = () => {
const { envConfig } = useEnv();
const { books, settings, initBookState, saveConfig, saveSettings } = useReaderStore();
const { getFoliateView } = useReaderStore();
const [sideBarWidth, setSideBarWidth] = useState(
settings.globalReadSettings.sideBarWidth ?? '25%',
@@ -33,6 +34,8 @@ const ReaderContent = () => {
const bookStates = ids.map((id, index) => books[getKey(id, index)] || DEFAULT_BOOK_STATE);
const [sideBarBookKey, setSideBarBookKey] = useState(getKey(ids[0] ?? '', 0));
let sliderProgress = 0;
React.useEffect(() => {
if (ids.length === 0) return;
const uniqueIds = new Set<string>();
@@ -70,6 +73,24 @@ const ReaderContent = () => {
router.back();
};
const handleProgressChange = (bookKey: string, event: React.ChangeEvent) => {
console.log('progress change', bookKey, event);
const newProgress = parseInt((event.target as HTMLInputElement).value, 10);
sliderProgress = newProgress;
const foliateView = getFoliateView(bookKey);
foliateView?.goToFraction(newProgress / 100.0);
};
const handleGoPrev = (bookKey: string) => {
const foliateView = getFoliateView(bookKey);
foliateView?.goLeft();
};
const handleGoNext = (bookKey: string) => {
const foliateView = getFoliateView(bookKey);
foliateView?.goRight();
};
const getGridTemplate = () => {
const count = ids.length;
const aspectRatio = window.innerWidth / window.innerHeight;
@@ -135,6 +156,17 @@ const ReaderContent = () => {
const key = getKey(ids[index]!, index);
const { book, config, bookDoc } = bookState;
if (!book || !config || !bookDoc) return null;
const { section, pageinfo, progress } = config;
const pageInfo =
book.format === 'PDF'
? section
? `${section.current + 1} / ${section.total}`
: ''
: pageinfo
? `Loc. ${pageinfo.current + 1} / ${pageinfo.total}`
: '';
const progressInfo = progress ? `${Math.round(progress * 100)}%` : '';
sliderProgress = progress ? progress * 100 : 0;
return (
<div key={key} className='relative h-full w-full overflow-hidden'>
<div
@@ -167,6 +199,34 @@ const ReaderContent = () => {
</div>
</div>
<FoliateViewer bookKey={key} bookDoc={bookDoc!} bookConfig={config!} />
<div className='pageinfo absolute bottom-0 left-0 right-0 flex h-12 items-center justify-center'>
<h2 className='px-2 text-center font-sans text-xs font-extralight text-slate-500'>
{pageInfo}
</h2>
</div>
<div className='footer-bar shadow-xs absolute bottom-0 flex h-12 w-full items-center bg-gray-100 px-4 opacity-0 transition-opacity duration-300 hover:opacity-100'>
<button
className='btn btn-ghost mx-2 h-8 min-h-8 w-8 p-0'
onClick={() => handleGoPrev(key)}
>
<RiArrowLeftWideLine size={20} />
</button>
<span className='mx-2 text-center text-sm text-black'>{progressInfo}</span>
<input
type='range'
className='mx-2 w-full'
min={0}
max={100}
value={sliderProgress}
onChange={(e) => handleProgressChange(key, e)}
/>
<button
className='btn btn-ghost mx-2 h-8 min-h-8 w-8 p-0'
onClick={() => handleGoNext(key)}
>
<RiArrowRightWideLine size={20} />
</button>
</div>
</div>
);
})}
@@ -110,10 +110,10 @@ const SideBar: React.FC<{
</button>
</div>
</div>
<div className='border-b px-3 shadow-sm'>
<div className='border-b px-3'>
<BookCard cover={book.coverImageUrl!} title={book.title} author={book.author} />
</div>
<div className='sidebar-content overflow-y-auto'>
<div className='sidebar-content overflow-y-auto border-b shadow-inner'>
{activeTab === 'toc' && bookDoc!.toc && (
<TOCView toc={bookDoc!.toc} bookKey={bookKey} currentHref={currentHref} />
)}
@@ -21,8 +21,15 @@ export const useFoliateEvents = (
const defaultRelocateHandler = (event: Event) => {
const detail = (event as CustomEvent).detail;
// console.log('relocate:', detail);
setProgress(bookKey, detail.fraction, detail.cfi, detail.tocItem?.href, detail.location);
console.log('relocate:', detail);
setProgress(
bookKey,
detail.fraction,
detail.cfi,
detail.tocItem?.href,
detail.section,
detail.location,
);
};
const onLoad = handlers?.onLoad || defaultLoadHandler;
@@ -30,6 +30,7 @@ interface ReaderStore {
progress: number,
location: string,
href: string,
section: PageInfo,
pageinfo: PageInfo,
) => void;
setFoliateView: (key: string, view: FoliateView) => void;
@@ -137,6 +138,7 @@ export const useReaderStore = create<ReaderStore>((set, get) => ({
progress: number,
location: string,
href: string,
section: PageInfo,
pageinfo: PageInfo,
) =>
set((state) => {
@@ -153,6 +155,7 @@ export const useReaderStore = create<ReaderStore>((set, get) => ({
href,
progress,
location,
section,
pageinfo,
},
},
+2 -1
View File
@@ -14,7 +14,7 @@ export interface Book {
export interface PageInfo {
current: number;
next: number;
next?: number;
total: number;
}
@@ -34,6 +34,7 @@ export interface BookConfig {
progress?: number;
location?: string;
href?: string;
section?: PageInfo;
pageinfo?: PageInfo;
bookmarks?: BookNote[];
annotations?: BookNote[];