Add keyboard shortcuts for page turning and book selection && header chapter info
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
|
||||
"productName": "Readest",
|
||||
"version": "0.2.0",
|
||||
"version": "0.3.0",
|
||||
"identifier": "com.bilingify.digest",
|
||||
"build": {
|
||||
"frontendDist": "../out",
|
||||
|
||||
@@ -37,9 +37,20 @@ foliate-view {
|
||||
border: none;
|
||||
}
|
||||
|
||||
@keyframes scaleUpAndDown {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.02);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.hover-bar-anim:hover ~ .foliate-viewer {
|
||||
transform: scale(1.02);
|
||||
transition: transform 0.3s ease;
|
||||
animation: scaleUpAndDown 0.3s ease forwards;
|
||||
}
|
||||
|
||||
.window-button {
|
||||
|
||||
@@ -1,15 +1,33 @@
|
||||
import React from 'react';
|
||||
import React, { useEffect } from 'react';
|
||||
import { FaSearch } from 'react-icons/fa';
|
||||
import { PiPlus } from 'react-icons/pi';
|
||||
import { MdSelectAll } from 'react-icons/md';
|
||||
import { PiSelectionAllDuotone } from 'react-icons/pi';
|
||||
|
||||
import WindowButtons from '@/components/WindowButtons';
|
||||
|
||||
interface LibraryHeaderProps {
|
||||
isSelectMode: boolean;
|
||||
onImportBooks: () => void;
|
||||
onToggleSelectMode: () => void;
|
||||
}
|
||||
|
||||
const LibraryHeader: React.FC<LibraryHeaderProps> = ({ onImportBooks, onToggleSelectMode }) => {
|
||||
const LibraryHeader: React.FC<LibraryHeaderProps> = ({
|
||||
isSelectMode,
|
||||
onImportBooks,
|
||||
onToggleSelectMode,
|
||||
}) => {
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if (e.ctrlKey || e.shiftKey) {
|
||||
onToggleSelectMode();
|
||||
}
|
||||
};
|
||||
window.addEventListener('keydown', handleKeyDown);
|
||||
return () => {
|
||||
window.removeEventListener('keydown', handleKeyDown);
|
||||
};
|
||||
}, [onToggleSelectMode]);
|
||||
|
||||
return (
|
||||
<div
|
||||
id='titlebar'
|
||||
@@ -42,7 +60,10 @@ const LibraryHeader: React.FC<LibraryHeaderProps> = ({ onImportBooks, onToggleSe
|
||||
</span>
|
||||
<button onClick={onToggleSelectMode} aria-label='Select Multiple Books' className='h-6'>
|
||||
<div className='lg:tooltip lg:tooltip-bottom cursor-pointer' data-tip='Select books'>
|
||||
<MdSelectAll role='button' className='h-6 w-6' />
|
||||
<PiSelectionAllDuotone
|
||||
role='button'
|
||||
className={`h-6 w-6 ${isSelectMode ? 'fill-gray-400' : 'fill-gray-500'}`}
|
||||
/>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -75,6 +75,7 @@ const LibraryPage = () => {
|
||||
return (
|
||||
<div className='rounded-window min-h-screen select-none bg-gray-100'>
|
||||
<LibraryHeader
|
||||
isSelectMode={isSelectMode}
|
||||
onImportBooks={handleImportBooks}
|
||||
onToggleSelectMode={handleToggleSelectMode}
|
||||
/>
|
||||
|
||||
@@ -85,7 +85,7 @@ const FoliateViewer: React.FC<{
|
||||
if ('setStyles' in view.renderer) {
|
||||
view.renderer.setStyles(getCSS(2.4, true, true));
|
||||
}
|
||||
view.renderer.setAttribute('margin', '35px');
|
||||
view.renderer.setAttribute('margin', '44px');
|
||||
view.renderer.setAttribute('gap', '4%');
|
||||
const lastLocation = bookConfig.location;
|
||||
if (lastLocation) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useEffect } from 'react';
|
||||
import clsx from 'clsx';
|
||||
import { RiArrowLeftWideLine, RiArrowRightWideLine } from 'react-icons/ri';
|
||||
|
||||
@@ -9,6 +9,7 @@ interface FooterBarProps {
|
||||
progress: number | undefined;
|
||||
isHoveredAnim: boolean;
|
||||
hoveredBookKey: string;
|
||||
sideBarBookKey: string;
|
||||
setHoveredBookKey: (key: string) => void;
|
||||
}
|
||||
|
||||
@@ -17,6 +18,7 @@ const FooterBar: React.FC<FooterBarProps> = ({
|
||||
progress,
|
||||
isHoveredAnim,
|
||||
hoveredBookKey,
|
||||
sideBarBookKey,
|
||||
setHoveredBookKey,
|
||||
}) => {
|
||||
const { getFoliateView } = useReaderStore();
|
||||
@@ -37,6 +39,23 @@ const FooterBar: React.FC<FooterBarProps> = ({
|
||||
foliateView?.goRight();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if (sideBarBookKey === bookKey) {
|
||||
if (e.key === 'ArrowLeft') {
|
||||
handleGoPrev();
|
||||
} else if (e.key === 'ArrowRight') {
|
||||
handleGoNext();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('keydown', handleKeyDown);
|
||||
return () => {
|
||||
window.removeEventListener('keydown', handleKeyDown);
|
||||
};
|
||||
}, [sideBarBookKey, bookKey]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
|
||||
@@ -13,6 +13,7 @@ import SideBar from './SideBar';
|
||||
import PageInfo from './PageInfo';
|
||||
import HeaderBar from './HeaderBar';
|
||||
import FooterBar from './FooterBar';
|
||||
import SectionInfo from './SectionInfo';
|
||||
|
||||
const ReaderContent = () => {
|
||||
const router = useRouter();
|
||||
@@ -137,7 +138,7 @@ 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 { section, pageinfo, progress, chapter } = config;
|
||||
return (
|
||||
<div key={key} className='relative h-full w-full overflow-hidden'>
|
||||
<HeaderBar
|
||||
@@ -152,12 +153,14 @@ const ReaderContent = () => {
|
||||
setHoveredBookKey={setHoveredBookKey}
|
||||
/>
|
||||
<FoliateViewer bookKey={key} bookDoc={bookDoc!} bookConfig={config!} />
|
||||
<SectionInfo chapter={chapter} />
|
||||
<PageInfo bookFormat={book.format} section={section} pageinfo={pageinfo} />
|
||||
<FooterBar
|
||||
bookKey={key}
|
||||
progress={progress}
|
||||
isHoveredAnim={false}
|
||||
hoveredBookKey={hoveredBookKey}
|
||||
sideBarBookKey={sideBarBookKey}
|
||||
setHoveredBookKey={setHoveredBookKey}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import React from 'react';
|
||||
|
||||
interface SectionInfoProps {
|
||||
chapter?: string;
|
||||
}
|
||||
|
||||
const SectionInfo: React.FC<SectionInfoProps> = ({ chapter }) => {
|
||||
return (
|
||||
<div className='pageinfo absolute left-[4%] right-0 top-0 flex h-9 items-end'>
|
||||
<h2
|
||||
className='text-center font-sans font-extralight text-slate-500'
|
||||
style={{ fontSize: '10px' }}
|
||||
>
|
||||
{chapter || ''}
|
||||
</h2>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SectionInfo;
|
||||
@@ -61,6 +61,8 @@ const TOCItemView: React.FC<{
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {}, [currentHref]);
|
||||
|
||||
const isActive = currentHref === item.href;
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -21,12 +21,13 @@ export const useFoliateEvents = (
|
||||
|
||||
const defaultRelocateHandler = (event: Event) => {
|
||||
const detail = (event as CustomEvent).detail;
|
||||
console.log('relocate:', detail);
|
||||
// console.log('relocate:', detail);
|
||||
setProgress(
|
||||
bookKey,
|
||||
detail.fraction,
|
||||
detail.cfi,
|
||||
detail.tocItem?.href,
|
||||
detail.tocItem?.label,
|
||||
detail.section,
|
||||
detail.location,
|
||||
);
|
||||
|
||||
@@ -30,6 +30,7 @@ interface ReaderStore {
|
||||
progress: number,
|
||||
location: string,
|
||||
href: string,
|
||||
chapter: string,
|
||||
section: PageInfo,
|
||||
pageinfo: PageInfo,
|
||||
) => void;
|
||||
@@ -149,6 +150,7 @@ export const useReaderStore = create<ReaderStore>((set, get) => ({
|
||||
progress: number,
|
||||
location: string,
|
||||
href: string,
|
||||
chapter: string,
|
||||
section: PageInfo,
|
||||
pageinfo: PageInfo,
|
||||
) =>
|
||||
@@ -164,6 +166,7 @@ export const useReaderStore = create<ReaderStore>((set, get) => ({
|
||||
...book.config,
|
||||
lastUpdated: Date.now(),
|
||||
href,
|
||||
chapter,
|
||||
progress,
|
||||
location,
|
||||
section,
|
||||
|
||||
@@ -34,6 +34,7 @@ export interface BookConfig {
|
||||
progress?: number;
|
||||
location?: string;
|
||||
href?: string;
|
||||
chapter?: string;
|
||||
section?: PageInfo;
|
||||
pageinfo?: PageInfo;
|
||||
bookmarks?: BookNote[];
|
||||
|
||||
Reference in New Issue
Block a user