fix: various fixes on layout settings and styles, closes #637 (#644)

This commit is contained in:
Huang Xin
2025-03-19 17:14:02 +08:00
committed by GitHub
parent 9a104b918c
commit 18c2ce1274
8 changed files with 64 additions and 34 deletions
@@ -81,7 +81,7 @@ const BooksGrid: React.FC<BooksGridProps> = ({ bookKeys, onCloseBook }) => {
/>
<FoliateViewer bookKey={bookKey} bookDoc={bookDoc} config={config} />
<FootnotePopup bookKey={bookKey} bookDoc={bookDoc} />
{viewSettings.vertical && (
{viewSettings.vertical && viewSettings.scrolled && (
<>
<div
className='bg-base-100 absolute left-0 top-0 h-full'
@@ -9,7 +9,7 @@ import { useClickEvent, useTouchEvent } from '../hooks/useIframeEvents';
import { useFoliateEvents } from '../hooks/useFoliateEvents';
import { useProgressSync } from '../hooks/useProgressSync';
import { useProgressAutoSave } from '../hooks/useProgressAutoSave';
import { applyColorScheme, getStyles, mountAdditionalFonts } from '@/utils/style';
import { getStyles, mountAdditionalFonts } from '@/utils/style';
import { getBookDirFromLanguage, getBookDirFromWritingMode } from '@/utils/book';
import { useUICSS } from '@/hooks/useUICSS';
import {
@@ -35,7 +35,7 @@ const FoliateViewer: React.FC<{
const { getView, setView: setFoliateView, setProgress } = useReaderStore();
const { getViewSettings, setViewSettings } = useReaderStore();
const { getParallels } = useParallelViewStore();
const { themeCode, isDarkMode, getIsDarkMode } = useThemeStore();
const { themeCode, isDarkMode } = useThemeStore();
const viewSettings = getViewSettings(bookKey)!;
const [toastMessage, setToastMessage] = useState('');
@@ -64,7 +64,6 @@ const FoliateViewer: React.FC<{
viewSettings.rtl = writingDir?.rtl || viewSettings.writingMode.includes('rl') || false;
setViewSettings(bookKey, { ...viewSettings });
applyColorScheme(detail.doc, getIsDarkMode());
mountAdditionalFonts(detail.doc);
if (!detail.doc.isEventListenersAdded) {
@@ -123,9 +122,6 @@ const FoliateViewer: React.FC<{
if (viewRef.current && viewRef.current.renderer) {
const viewSettings = getViewSettings(bookKey)!;
viewRef.current.renderer.setStyles?.(getStyles(viewSettings));
// Safari does not recognize color-scheme from the root document in iframe
const doc = viewRef.current.renderer.getContents()[0]!.doc;
applyColorScheme(doc, isDarkMode);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [themeCode, isDarkMode]);
@@ -164,6 +164,7 @@ const LayoutPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
viewSettings.gapPercent,
Math.ceil(4800 / window.innerWidth),
);
setGapPercent(viewSettings.gapPercent);
setViewSettings(bookKey, viewSettings);
}
saveViewSettings(envConfig, bookKey, 'doubleBorder', doubleBorder);
@@ -176,11 +177,35 @@ const LayoutPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
}, [borderColor]);
useEffect(() => {
if (showHeader && !viewSettings.vertical) {
viewSettings.marginPx = Math.max(viewSettings.marginPx, 44);
setMarginPx(viewSettings.marginPx);
setViewSettings(bookKey, viewSettings);
} else if (showHeader && viewSettings.vertical) {
viewSettings.gapPercent = Math.max(
viewSettings.gapPercent,
Math.ceil(4800 / window.innerWidth),
);
setGapPercent(viewSettings.gapPercent);
setViewSettings(bookKey, viewSettings);
}
saveViewSettings(envConfig, bookKey, 'showHeader', showHeader);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [showHeader]);
useEffect(() => {
if (showFooter && !viewSettings.vertical) {
viewSettings.marginPx = Math.max(viewSettings.marginPx, 44);
setMarginPx(viewSettings.marginPx);
setViewSettings(bookKey, viewSettings);
} else if (showFooter && viewSettings.vertical) {
viewSettings.gapPercent = Math.max(
viewSettings.gapPercent,
Math.ceil(4800 / window.innerWidth),
);
setGapPercent(viewSettings.gapPercent);
setViewSettings(bookKey, viewSettings);
}
saveViewSettings(envConfig, bookKey, 'showFooter', showFooter);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [showFooter]);
@@ -382,7 +407,7 @@ const LayoutPanel: React.FC<{ bookKey: string }> = ({ bookKey }) => {
label={_('Vertical Margins (px)')}
value={marginPx}
onChange={setMarginPx}
min={0}
min={!viewSettings.vertical && (showFooter || showHeader) ? 44 : 0}
max={88}
step={4}
/>
@@ -1,5 +1,5 @@
import clsx from 'clsx';
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import { FiMinus, FiPlus } from 'react-icons/fi';
interface NumberInputProps {
@@ -26,6 +26,10 @@ const NumberInput: React.FC<NumberInputProps> = ({
const [localValue, setLocalValue] = useState(value);
const numberStep = step || 1;
useEffect(() => {
setLocalValue(value);
}, [value]);
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
@@ -137,7 +137,11 @@ export const useTouchEvent = (
if (hoveredBookKey && touchEnd) {
const deltaY = touchEnd.screenY - touchStart.screenY;
const deltaX = touchEnd.screenX - touchStart.screenX;
if (Math.abs(deltaX) > Math.abs(deltaY) && Math.abs(deltaX) > 10) {
if (!viewSettings!.scrolled && !viewSettings!.vertical) {
if (Math.abs(deltaX) > Math.abs(deltaY) && Math.abs(deltaX) > 10) {
setHoveredBookKey(null);
}
} else {
setHoveredBookKey(null);
}
}
@@ -161,8 +165,10 @@ export const useTouchEvent = (
Math.abs(deltaY) > Math.abs(deltaX) &&
Math.abs(deltaX) < windowWidth * 0.3
) {
// swipe up to toggle the header bar and the footer bar
setHoveredBookKey(hoveredBookKey ? null : bookKey);
// swipe up to toggle the header bar and the footer bar, only for horizontal page mode
if (!viewSettings!.scrolled && !viewSettings!.vertical) {
setHoveredBookKey(hoveredBookKey ? null : bookKey);
}
} else {
if (hoveredBookKey) {
setHoveredBookKey(null);
@@ -187,15 +193,10 @@ export const useTouchEvent = (
};
useEffect(() => {
// swipe touch is not compatible with scrolled mode, so only enable it in page mode
if (!viewSettings!.scrolled) {
window.addEventListener('message', handleTouch);
return () => {
window.removeEventListener('message', handleTouch);
};
} else {
return () => {};
}
window.addEventListener('message', handleTouch);
return () => {
window.removeEventListener('message', handleTouch);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [hoveredBookKey, viewRef]);
};
+1 -2
View File
@@ -2,7 +2,6 @@ import { useEffect } from 'react';
import { useThemeStore } from '@/store/themeStore';
import { useSettingsStore } from '@/store/settingsStore';
import { applyCustomTheme } from '@/styles/themes';
import { applyColorScheme } from '@/utils/style';
export const useTheme = () => {
const { settings } = useSettingsStore();
@@ -17,6 +16,6 @@ export const useTheme = () => {
useEffect(() => {
const colorScheme = isDarkMode ? 'dark' : 'light';
document.documentElement.setAttribute('data-theme', `${themeColor}-${colorScheme}`);
applyColorScheme(document, isDarkMode);
document.documentElement.style.setProperty('color-scheme', colorScheme);
}, [themeColor, isDarkMode]);
};
+15 -10
View File
@@ -137,10 +137,11 @@ const getLayoutStyles = (
bg: string,
fg: string,
primary: string,
isDarkMode: boolean,
) => `
@namespace epub "http://www.idpf.org/2007/ops";
html {
color-scheme: light dark;
color-scheme: ${isDarkMode ? 'dark' : 'light'};
color: ${fg};
}
a:any-link {
@@ -158,6 +159,8 @@ const getLayoutStyles = (
html {
--theme-bg-color: ${bg};
--theme-fg-color: ${fg};
--theme-primary-color: ${primary};
--default-text-align: ${justify ? 'justify' : 'start'};
hanging-punctuation: allow-end last;
orphans: 2;
@@ -248,15 +251,19 @@ export const getFootnoteStyles = () => `
display: block !important;
}
body {
padding: 1em !important;
}
a:any-link {
text-decoration: none;
}
ol {
margin: 0;
padding: 0;
}
body {
padding: 1em !important;
}
p, li, blockquote, dd {
margin: unset;
text-indent: unset;
@@ -268,6 +275,7 @@ export interface ThemeCode {
fg: string;
primary: string;
palette: Palette;
isDarkMode: boolean;
}
export const getThemeCode = () => {
@@ -303,6 +311,7 @@ export const getThemeCode = () => {
fg: defaultPalette['base-content'],
primary: defaultPalette.primary,
palette: defaultPalette,
isDarkMode,
} as ThemeCode;
};
@@ -325,6 +334,7 @@ export const getStyles = (viewSettings: ViewSettings, themeCode?: ThemeCode) =>
themeCode.bg,
themeCode.fg,
themeCode.primary,
themeCode.isDarkMode,
);
// scale the font size on-the-fly so that we can sync the same font size on different devices
const isMobile = ['ios', 'android'].includes(getOSPlatform());
@@ -364,8 +374,3 @@ export const mountAdditionalFonts = (document: Document) => {
style.textContent = getAdditionalFontFaces();
document.head.appendChild(style);
};
export const applyColorScheme = (document: Document, isDarkMode: boolean) => {
const colorScheme = isDarkMode ? 'dark' : 'light';
document.documentElement.style.setProperty('color-scheme', colorScheme);
};