feat: add options to show/hide header and footer widgets in paginated and scrolled mode, also closes #602 (#620)

This commit is contained in:
Huang Xin
2025-03-17 22:30:12 +08:00
committed by GitHub
parent 66bd8d74f3
commit 48074f0f53
32 changed files with 257 additions and 152 deletions
@@ -244,5 +244,8 @@
"Contrast": "التباين",
"Sunset": "غروب الشمس",
"Double Border": "حدود مزدوجة",
"Border Color": "لون الحدود"
"Border Color": "لون الحدود",
"Border Frame": "إطار الحدود",
"Show Header": "عرض الرأس",
"Show Footer": "عرض التذييل"
}
@@ -244,5 +244,8 @@
"Contrast": "Kontrast",
"Sunset": "Sonnenuntergang",
"Double Border": "Doppelter Rand",
"Border Color": "Randfarbe"
"Border Color": "Randfarbe",
"Border Frame": "Rahmenrand",
"Show Header": "Kopfzeile anzeigen",
"Show Footer": "Fußzeile anzeigen"
}
@@ -244,5 +244,8 @@
"Contrast": "Αντίθεση",
"Sunset": "Ηλιοβασίλεμα",
"Double Border": "Διπλό περιθώριο",
"Border Color": "Χρώμα περιγράμματος"
"Border Color": "Χρώμα περιγράμματος",
"Border Frame": "Πλαίσιο περιγράμματος",
"Show Header": "Εμφάνιση κεφαλίδας",
"Show Footer": "Εμφάνιση υποσέλιδου"
}
@@ -244,5 +244,8 @@
"Contrast": "Contraste",
"Sunset": "Atardecer",
"Double Border": "Doble borde",
"Border Color": "Color del borde"
"Border Color": "Color del borde",
"Border Frame": "Marco de borde",
"Show Header": "Mostrar encabezado",
"Show Footer": "Mostrar pie de página"
}
@@ -244,5 +244,8 @@
"Contrast": "Contraste",
"Sunset": "Coucher de soleil",
"Double Border": "Double bordure",
"Border Color": "Couleur de la bordure"
"Border Color": "Couleur de la bordure",
"Border Frame": "Cadre de bordure",
"Show Header": "Afficher l'en-tête",
"Show Footer": "Afficher le pied de page"
}
@@ -244,5 +244,8 @@
"Contrast": "विरोधाभास",
"Sunset": "सनसेट",
"Double Border": "डबल बॉर्डर",
"Border Color": "बॉर्डर रंग"
"Border Color": "बॉर्डर रंग",
"Border Frame": "बॉर्डर फ्रेम",
"Show Header": "हेडर दिखाएं",
"Show Footer": "फ़ुटर दिखाएं"
}
@@ -244,5 +244,8 @@
"Contrast": "Kontras",
"Sunset": "Senja",
"Double Border": "Garis Ganda",
"Border Color": "Warna Garis"
"Border Color": "Warna Garis",
"Border Frame": "Bingkai Garis",
"Show Header": "Tampilkan Header",
"Show Footer": "Tampilkan Footer"
}
@@ -244,5 +244,8 @@
"Contrast": "Contrasto",
"Sunset": "Tramonto",
"Double Border": "Doppio bordo",
"Border Color": "Colore bordo"
"Border Color": "Colore bordo",
"Border Frame": "Cornice bordo",
"Show Header": "Mostra intestazione",
"Show Footer": "Mostra piè di pagina"
}
@@ -244,5 +244,8 @@
"Contrast": "コントラスト",
"Sunset": "サンセット",
"Double Border": "二重枠",
"Border Color": "ボーダーカラー"
"Border Color": "ボーダーカラー",
"Border Frame": "ボーダーフレーム",
"Show Header": "ヘッダーを表示",
"Show Footer": "フッターを表示"
}
@@ -244,5 +244,8 @@
"Contrast": "대비",
"Sunset": "일몰",
"Double Border": "이중 테두리",
"Border Color": "테두리 색상"
"Border Color": "테두리 색상",
"Border Frame": "테두리 프레임",
"Show Header": "헤더 표시",
"Show Footer": "푸터 표시"
}
@@ -244,5 +244,8 @@
"Contrast": "Kontrast",
"Sunset": "Zachód słońca",
"Double Border": "Podwójna ramka",
"Border Color": "Kolor ramki"
"Border Color": "Kolor ramki",
"Border Frame": "Ramka",
"Show Header": "Pokaż nagłówek",
"Show Footer": "Pokaż stopkę"
}
@@ -244,5 +244,8 @@
"Contrast": "Contraste",
"Sunset": "Pôr do Sol",
"Double Border": "Borda Dupla",
"Border Color": "Cor da Borda"
"Border Color": "Cor da Borda",
"Border Frame": "Moldura da Borda",
"Show Header": "Mostrar Cabeçalho",
"Show Footer": "Mostrar Rodapé"
}
@@ -244,5 +244,8 @@
"Contrast": "Контраст",
"Sunset": "Закат",
"Double Border": "Двойная граница",
"Border Color": "Цвет границы"
"Border Color": "Цвет границы",
"Border Frame": "Граница рамки",
"Show Header": "Показать заголовок",
"Show Footer": "Показать нижний колонтитул"
}
@@ -244,5 +244,8 @@
"Contrast": "Kontrast",
"Sunset": "Gün Batımı",
"Double Border": "Çift Sınır",
"Border Color": "Sınır Rengi"
"Border Color": "Sınır Rengi",
"Border Frame": "Sınır Çerçevesi",
"Show Header": "Başlık Göster",
"Show Footer": "Altbilgi Göster"
}
@@ -244,5 +244,8 @@
"Contrast": "Контраст",
"Sunset": "Захід сонця",
"Double Border": "Подвійна рамка",
"Border Color": "Колір рамки"
"Border Color": "Колір рамки",
"Border Frame": "Рамка рамки",
"Show Header": "Показати заголовок",
"Show Footer": "Показати нижню частину"
}
@@ -244,5 +244,8 @@
"Contrast": "Tương phản",
"Sunset": "Hoàng hôn",
"Double Border": "Đôi viền",
"Border Color": "Màu viền"
"Border Color": "Màu viền",
"Border Frame": "Khung viền",
"Show Header": "Hiển thị tiêu đề",
"Show Footer": "Hiển thị chân trang"
}
@@ -243,6 +243,9 @@
"Preview": "预览",
"Contrast": "对比",
"Sunset": "日落",
"Double Border": "页面版框",
"Border Color": "版框颜色"
"Double Border": "显示版框",
"Border Color": "版框颜色",
"Border Frame": "页面版框",
"Show Header": "显示页眉",
"Show Footer": "显示页脚"
}
@@ -243,6 +243,9 @@
"Preview": "預覽",
"Contrast": "對比",
"Sunset": "日落",
"Double Border": "頁面邊框",
"Border Color": "邊框顏色"
"Double Border": "顯示邊框",
"Border Color": "邊框顏色",
"Border Frame": "頁面邊框",
"Show Header": "顯示頁眉",
"Show Footer": "顯示頁腳"
}
@@ -81,36 +81,50 @@ const BooksGrid: React.FC<BooksGridProps> = ({ bookKeys, onCloseBook }) => {
/>
<FoliateViewer bookKey={bookKey} bookDoc={bookDoc} config={config} />
<FootnotePopup bookKey={bookKey} bookDoc={bookDoc} />
{viewSettings.scrolled ? null : (
<>
{viewSettings.vertical && viewSettings.doubleBorder && (
<DoubleBorder
borderColor={viewSettings.borderColor}
horizontalGap={horizontalGapPercent}
verticalMargin={verticalMarginPixels}
/>
)}
<SectionInfo
section={sectionLabel}
isVertical={viewSettings.vertical}
horizontalGap={horizontalGapPercent}
verticalMargin={verticalMarginPixels}
/>
<HintInfo
bookKey={bookKey}
isVertical={viewSettings.vertical}
horizontalGap={horizontalGapPercent}
verticalMargin={verticalMarginPixels}
/>
<PageInfoView
bookFormat={book.format}
section={section}
pageinfo={pageinfo}
isVertical={viewSettings.vertical}
horizontalGap={horizontalGapPercent}
verticalMargin={verticalMarginPixels}
/>
</>
<div
className='bg-base-100 absolute left-0 top-0 h-full'
style={{
width: `${horizontalGapPercent}%`,
}}
/>
<div
className='bg-base-100 absolute right-0 top-0 h-full'
style={{
width: `${horizontalGapPercent}%`,
}}
/>
{viewSettings.vertical && viewSettings.doubleBorder && (
<DoubleBorder
showHeader={viewSettings.showHeader}
showFooter={viewSettings.showFooter}
borderColor={viewSettings.borderColor}
horizontalGap={horizontalGapPercent}
verticalMargin={verticalMarginPixels}
/>
)}
{viewSettings.showHeader && (
<SectionInfo
section={sectionLabel}
isVertical={viewSettings.vertical}
horizontalGap={horizontalGapPercent}
verticalMargin={verticalMarginPixels}
/>
)}
<HintInfo
bookKey={bookKey}
isVertical={viewSettings.vertical}
horizontalGap={horizontalGapPercent}
verticalMargin={verticalMarginPixels}
/>
{viewSettings.showFooter && (
<PageInfoView
bookFormat={book.format}
section={section}
pageinfo={pageinfo}
isVertical={viewSettings.vertical}
horizontalGap={horizontalGapPercent}
verticalMargin={verticalMarginPixels}
/>
)}
<Annotator bookKey={bookKey} />
<FooterBar
@@ -2,6 +2,8 @@ interface DoubleBorderProps {
borderColor: string;
horizontalGap: number;
verticalMargin: number;
showHeader: boolean;
showFooter: boolean;
}
const paddingPx = 10;
@@ -10,51 +12,63 @@ const DoubleBorder: React.FC<DoubleBorderProps> = ({
borderColor,
horizontalGap,
verticalMargin,
showHeader,
showFooter,
}) => {
return (
<>
{/* outter frame */}
<div
className={'borderframe pointer-events-none absolute'}
style={{
border: `4px solid ${borderColor}`,
height: `calc(100% - ${verticalMargin * 2}px + ${paddingPx * 2}px)`,
top: `calc(${verticalMargin}px - ${paddingPx}px)`,
left: `calc(${horizontalGap * 2}% - 32px - ${paddingPx}px)`,
right: `calc(${horizontalGap * 2}% - 32px - ${paddingPx}px)`,
left: `calc(${horizontalGap}% - ${showFooter ? 32 : 0}px - ${paddingPx}px)`,
right: `calc(${horizontalGap}% - ${showHeader ? 32 : 0}px - ${paddingPx}px)`,
}}
></div>
{/* inner frame */}
<div
className={'borderframe pointer-events-none absolute'}
style={{
border: `1px solid ${borderColor}`,
height: `calc(100% - ${verticalMargin * 2}px)`,
top: `${verticalMargin}px`,
left: `${horizontalGap * 2}%`,
right: `${horizontalGap * 2}%`,
}}
/>
<div
className={'borderframe pointer-events-none absolute'}
style={{
border: `1px solid ${borderColor}`,
width: '32px',
height: `calc(100% - ${verticalMargin * 2}px)`,
top: `${verticalMargin}px`,
left: `calc(${horizontalGap * 2}% - 32px)`,
borderRight: 'none',
}}
/>
<div
className={'borderframe pointer-events-none absolute'}
style={{
border: `1px solid ${borderColor}`,
width: '32px',
height: `calc(100% - ${verticalMargin * 2}px)`,
top: `${verticalMargin}px`,
left: `calc(100% - ${horizontalGap * 2}%)`,
borderLeft: 'none',
left: showFooter ? `${horizontalGap}%` : `calc(${horizontalGap}%)`,
right: showHeader ? `${horizontalGap}%` : `calc(${horizontalGap}%)`,
}}
/>
{/* footer */}
{showFooter && (
<div
className={'borderframe pointer-events-none absolute'}
style={{
borderTop: `1px solid ${borderColor}`,
borderBottom: `1px solid ${borderColor}`,
borderLeft: `1px solid ${borderColor}`,
width: '32px',
height: `calc(100% - ${verticalMargin * 2}px)`,
top: `${verticalMargin}px`,
left: `calc(${horizontalGap}% - 32px)`,
}}
/>
)}
{/* header */}
{showHeader && (
<div
className={'borderframe pointer-events-none absolute'}
style={{
borderTop: `1px solid ${borderColor}`,
borderBottom: `1px solid ${borderColor}`,
borderRight: `1px solid ${borderColor}`,
width: '32px',
height: `calc(100% - ${verticalMargin * 2}px)`,
top: `${verticalMargin}px`,
left: `calc(100% - ${horizontalGap}%)`,
}}
/>
)}
</>
);
};
@@ -35,7 +35,7 @@ const FoliateViewer: React.FC<{
const { getView, setView: setFoliateView, setProgress } = useReaderStore();
const { getViewSettings, setViewSettings } = useReaderStore();
const { getParallels } = useParallelViewStore();
const { themeCode, isDarkMode } = useThemeStore();
const { themeCode, isDarkMode, getIsDarkMode } = useThemeStore();
const viewSettings = getViewSettings(bookKey)!;
const [toastMessage, setToastMessage] = useState('');
@@ -64,7 +64,7 @@ const FoliateViewer: React.FC<{
viewSettings.rtl = writingDir?.rtl || viewSettings.writingMode.includes('rl') || false;
setViewSettings(bookKey, viewSettings);
applyColorScheme(detail.doc, isDarkMode);
applyColorScheme(detail.doc, getIsDarkMode());
mountAdditionalFonts(detail.doc);
if (!detail.doc.isEventListenersAdded) {
@@ -1,7 +1,5 @@
import clsx from 'clsx';
import React, { useEffect, useRef } from 'react';
import { useSidebarStore } from '@/store/sidebarStore';
import { useTrafficLightStore } from '@/store/trafficLightStore';
import { eventDispatcher } from '@/utils/event';
interface SectionInfoProps {
@@ -17,8 +15,6 @@ const HintInfo: React.FC<SectionInfoProps> = ({
horizontalGap,
verticalMargin,
}) => {
const { isSideBarVisible } = useSidebarStore();
const { isTrafficLightVisible } = useTrafficLightStore();
const [hintMessage, setHintMessage] = React.useState<string | null>(null);
const hintTimeout = useRef(2000);
const dismissTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);
@@ -49,17 +45,15 @@ const HintInfo: React.FC<SectionInfoProps> = ({
return (
<div
className={clsx(
'sectioninfo absolute flex justify-end overflow-hidden',
!isVertical && (isTrafficLightVisible && !isSideBarVisible ? 'h-[44px]' : 'h-[30px]'),
isVertical ? 'writing-vertical-rl w-[32px] items-center' : 'top-0 items-end',
isVertical ? 'max-h-[50%]' : 'max-w-[50%]',
'hintinfo absolute flex items-center justify-end overflow-hidden',
hintMessage ? 'bg-base-100' : 'bg-transparent',
isVertical ? 'writing-vertical-rl max-h-[50%] w-[30px]' : 'top-0 h-[44px] max-w-[50%]',
)}
style={
isVertical
? {
bottom: `calc(${horizontalGap / 2}% + ${verticalMargin}px)`,
left: `calc(100% - ${horizontalGap * 2}%)`,
height: `calc(100% - ${verticalMargin * 2}px)`,
bottom: `${verticalMargin * 1.5}px`,
left: `calc(100% - ${horizontalGap}%)`,
}
: { right: `${horizontalGap}%` }
}
@@ -42,14 +42,13 @@ const PageInfoView: React.FC<PageInfoProps> = ({
<div
className={clsx(
'pageinfo absolute bottom-0 flex items-center justify-end',
isVertical ? 'left-0' : 'right-0',
isVertical ? 'writing-vertical-rl w-[32px]' : 'h-12',
isVertical ? 'writing-vertical-rl left-0 w-[32px]' : 'bg-base-100 right-0 h-12 w-full',
)}
style={
isVertical
? {
bottom: `calc(${horizontalGap / 2}% + ${verticalMargin}px)`,
left: `calc(${horizontalGap * 2}% - 32px)`,
bottom: `${verticalMargin * 1.5}px`,
left: `calc(${horizontalGap}% - 32px)`,
height: `calc(100% - ${verticalMargin * 2}px)`,
}
: { paddingRight: `${horizontalGap}%` }
@@ -1,9 +1,6 @@
import clsx from 'clsx';
import React from 'react';
import { useSidebarStore } from '@/store/sidebarStore';
import { useTrafficLightStore } from '@/store/trafficLightStore';
interface SectionInfoProps {
section?: string;
isVertical: boolean;
@@ -17,24 +14,22 @@ const SectionInfo: React.FC<SectionInfoProps> = ({
horizontalGap,
verticalMargin,
}) => {
const { isSideBarVisible } = useSidebarStore();
const { isTrafficLightVisible } = useTrafficLightStore();
return (
<div
className={clsx(
'sectioninfo absolute flex overflow-hidden',
!isVertical && (isTrafficLightVisible && !isSideBarVisible ? 'h-[44px]' : 'h-[30px]'),
isVertical ? 'writing-vertical-rl w-[32px] items-center' : 'top-0 items-end',
isVertical ? 'max-h-[50%]' : 'max-w-[50%]',
'sectioninfo absolute flex items-center overflow-hidden',
isVertical
? 'writing-vertical-rl max-h-[85%] w-[32px]'
: 'bg-base-100 top-0 h-[44px] w-full',
)}
style={
isVertical
? {
top: `calc(${horizontalGap / 2}% + ${verticalMargin}px)`,
left: `calc(100% - ${horizontalGap * 2}%)`,
top: `${verticalMargin * 1.5}px`,
left: `calc(100% - ${horizontalGap}%)`,
height: `calc(100% - ${verticalMargin * 2}px)`,
}
: { left: `${horizontalGap}%` }
: { paddingLeft: `${horizontalGap}%` }
}
>
<h2 className={clsx('text-neutral-content text-center font-sans text-xs font-light')}>
@@ -225,7 +225,6 @@ const FontPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
<div className='card border-base-200 border shadow'>
<div className='divide-base-200 divide-y'>
<NumberInput
className='config-item-top'
label={_('Default Font Size')}
value={defaultFontSize}
onChange={setDefaultFontSize}
@@ -233,7 +232,6 @@ const FontPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
max={120}
/>
<NumberInput
className='config-item-bottom'
label={_('Minimum Font Size')}
value={minFontSize}
onChange={setMinFontSize}
@@ -249,7 +247,6 @@ const FontPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
<div className='card border-base-200 border shadow'>
<div className='divide-base-200 divide-y'>
<NumberInput
className='config-item-top'
label={_('Font Weight')}
value={fontWeight}
onChange={setFontWeight}
@@ -265,7 +262,7 @@ const FontPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
<h2 className='mb-2 font-medium'>{_('Font Family')}</h2>
<div className='card border-base-200 border shadow'>
<div className='divide-base-200 divide-y'>
<div className='config-item config-item-top'>
<div className='config-item'>
<span className=''>{_('Default Font')}</span>
<FontDropdown
options={fontFamilyOptions}
@@ -275,7 +272,7 @@ const FontPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
/>
</div>
<div className='config-item config-item-bottom'>
<div className='config-item'>
<span className=''>{_('Override Book Font')}</span>
<input
type='checkbox'
@@ -40,6 +40,8 @@ const LayoutPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
const [isScrolledMode, setScrolledMode] = useState(viewSettings.scrolled!);
const [doubleBorder, setDoubleBorder] = useState(viewSettings.doubleBorder!);
const [borderColor, setBorderColor] = useState(viewSettings.borderColor!);
const [showHeader, setShowHeader] = useState(viewSettings.showHeader!);
const [showFooter, setShowFooter] = useState(viewSettings.showFooter!);
useEffect(() => {
viewSettings.paragraphMargin = paragraphMargin;
@@ -246,6 +248,26 @@ const LayoutPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [borderColor]);
useEffect(() => {
viewSettings.showHeader = showHeader;
setViewSettings(bookKey, viewSettings);
if (isFontLayoutSettingsGlobal) {
settings.globalViewSettings.showHeader = showHeader;
setSettings(settings);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [showHeader]);
useEffect(() => {
viewSettings.showFooter = showFooter;
setViewSettings(bookKey, viewSettings);
if (isFontLayoutSettingsGlobal) {
settings.globalViewSettings.showFooter = showFooter;
setSettings(settings);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [showFooter]);
const langCode = getBookLangCode(bookData.bookDoc?.metadata?.language);
const mightBeRTLBook = MIGHT_BE_RTL_LANGS.includes(langCode) || isCJKEnv();
@@ -309,36 +331,37 @@ const LayoutPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
)}
{viewSettings.vertical && (
<>
<div className='w-full'>
<div className='flex items-center justify-between'>
<h2 className='font-medium'>{_('Double Border')}</h2>
<input
type='checkbox'
className='toggle'
checked={doubleBorder}
onChange={() => setDoubleBorder(!doubleBorder)}
/>
</div>
</div>
<div className='w-full'>
<h2 className='mb-2 font-medium'>{_('Border Frame')}</h2>
<div className='card bg-base-100 border-base-200 border shadow'>
<div className='divide-base-200 divide-y'>
<div className='config-item'>
<span className=''>{_('Double Border')}</span>
<input
type='checkbox'
className='toggle'
checked={doubleBorder}
onChange={() => setDoubleBorder(!doubleBorder)}
/>
</div>
<div className='w-full'>
<div className='flex items-center justify-between'>
<h2 className='font-medium'>{_('Border Color')}</h2>
<div className='flex gap-4'>
<button
className={`btn btn-circle btn-sm bg-red-300 hover:bg-red-500 ${borderColor === 'red' ? 'btn-active !bg-red-500' : ''}`}
onClick={() => setBorderColor('red')}
></button>
<div className='config-item'>
<span className=''>{_('Border Color')}</span>
<div className='flex gap-4'>
<button
className={`btn btn-circle btn-sm bg-red-300 hover:bg-red-500 ${borderColor === 'red' ? 'btn-active !bg-red-500' : ''}`}
onClick={() => setBorderColor('red')}
></button>
<button
className={`btn btn-circle btn-sm bg-black/50 hover:bg-black ${borderColor === 'black' ? 'btn-active !bg-black' : ''}`}
onClick={() => setBorderColor('black')}
></button>
<button
className={`btn btn-circle btn-sm bg-black/50 hover:bg-black ${borderColor === 'black' ? 'btn-active !bg-black' : ''}`}
onClick={() => setBorderColor('black')}
></button>
</div>
</div>
</div>
</div>
</>
</div>
)}
<div className='w-full'>
@@ -346,7 +369,6 @@ const LayoutPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
<div className='card bg-base-100 border-base-200 border shadow'>
<div className='divide-base-200 divide-y'>
<NumberInput
className='config-item-top'
label={_('Paragraph Margin')}
value={paragraphMargin}
onChange={setParagraphMargin}
@@ -386,7 +408,7 @@ const LayoutPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
max={4}
step={1}
/>
<div className='config-item config-item-bottom'>
<div className='config-item'>
<span className=''>{_('Full Justification')}</span>
<input
type='checkbox'
@@ -395,7 +417,7 @@ const LayoutPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
onChange={() => setFullJustification(!fullJustification)}
/>
</div>
<div className='config-item config-item-bottom'>
<div className='config-item'>
<span className=''>{_('Hyphenation')}</span>
<input
type='checkbox'
@@ -404,7 +426,7 @@ const LayoutPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
onChange={() => setHyphenation(!hyphenation)}
/>
</div>
<div className='config-item config-item-bottom'>
<div className='config-item'>
<span className=''>{_('Override Book Layout')}</span>
<input
type='checkbox'
@@ -421,8 +443,25 @@ const LayoutPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
<h2 className='mb-2 font-medium'>{_('Page')}</h2>
<div className='card bg-base-100 border-base-200 border shadow'>
<div className='divide-base-200 divide-y'>
<div className='config-item'>
<span className=''>{_('Show Header')}</span>
<input
type='checkbox'
className='toggle'
checked={showHeader}
onChange={() => setShowHeader(!showHeader)}
/>
</div>
<div className='config-item'>
<span className=''>{_('Show Footer')}</span>
<input
type='checkbox'
className='toggle'
checked={showFooter}
onChange={() => setShowFooter(!showFooter)}
/>
</div>
<NumberInput
className='config-item-top'
label={_('Vertical Margins (px)')}
value={marginPx}
onChange={setMarginPx}
@@ -436,6 +475,7 @@ const LayoutPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
onChange={setGapPercent}
min={viewSettings.vertical ? 2 : 0}
max={30}
step={0.5}
/>
<NumberInput
label={_('Maximum Number of Columns')}
@@ -107,7 +107,7 @@ const MiscPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
<h2 className='mb-2 font-medium'>{_('Animation')}</h2>
<div className='card border-base-200 bg-base-100 border shadow'>
<div className='divide-base-200 divide-y'>
<div className='config-item config-item-top config-item-bottom'>
<div className='config-item'>
<span className=''>{_('Paging Animation')}</span>
<input
type='checkbox'
@@ -124,7 +124,7 @@ const MiscPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
<h2 className='mb-2 font-medium'>{_('Behavior')}</h2>
<div className='card border-base-200 bg-base-100 border shadow'>
<div className='divide-base-200 divide-y'>
<div className='config-item config-item-top'>
<div className='config-item'>
<span className=''>{_('Continuous Scroll')}</span>
<input
type='checkbox'
@@ -133,7 +133,7 @@ const MiscPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
onChange={() => setIsContinuousScroll(!isContinuousScroll)}
/>
</div>
<div className='config-item config-item-bottom'>
<div className='config-item'>
<span className=''>{_('Disable Click-to-Flip')}</span>
<input
type='checkbox'
@@ -73,6 +73,8 @@ export const DEFAULT_BOOK_LAYOUT: BookLayout = {
rtl: false,
doubleBorder: true,
borderColor: 'red',
showHeader: true,
showFooter: true,
};
export const DEFAULT_BOOK_STYLE: BookStyle = {
+2
View File
@@ -10,6 +10,7 @@ interface ThemeState {
systemIsDarkMode: boolean;
themeCode: ThemeCode;
isDarkMode: boolean;
getIsDarkMode: () => boolean;
setThemeMode: (mode: ThemeMode) => void;
setThemeColor: (color: string) => void;
updateAppTheme: (color: keyof Palette) => void;
@@ -61,6 +62,7 @@ export const useThemeStore = create<ThemeState>((set, get) => {
systemIsDarkMode,
isDarkMode,
themeCode,
getIsDarkMode: () => get().isDarkMode,
setThemeMode: (mode) => {
if (typeof window !== 'undefined' && localStorage) {
localStorage.setItem('themeMode', mode);
-8
View File
@@ -191,14 +191,6 @@ foliate-view {
@apply hover:bg-base-100/50;
}
.config-item-top {
@apply rounded-t-2xl;
}
.config-item-bottom {
@apply rounded-b-2xl;
}
.collapse-arrow > .collapse-title:after {
top: var(--top-override, default-value);
inset-inline-end: var(--end-override, default-value);
+2
View File
@@ -70,6 +70,8 @@ export interface BookLayout {
rtl: boolean;
doubleBorder: boolean;
borderColor: string;
showHeader: boolean;
showFooter: boolean;
}
export interface BookStyle {