feat(settings): added an option to disable animation in E-Ink mode, closes #2253 (#2257)

This commit is contained in:
Huang Xin
2025-10-18 00:00:58 +08:00
committed by GitHub
parent c1d6825793
commit 35fbce3506
33 changed files with 147 additions and 26 deletions
@@ -623,5 +623,7 @@
"Size": "حجم",
"Cover": "غطاء",
"Contain": "احتواء",
"{{number}} pages left in chapter": "تبقّت {{number}} صفحات في هذا الفصل"
"{{number}} pages left in chapter": "تبقّت {{number}} صفحات في هذا الفصل",
"Device": "الجهاز",
"E-Ink Mode": "وضع الحبر الإلكتروني"
}
@@ -607,5 +607,7 @@
"Size": "আকার",
"Cover": "ঢাকা",
"Contain": "ধারণ",
"{{number}} pages left in chapter": "অধ্যায়ে {{number}} পৃষ্ঠা বাকি"
"{{number}} pages left in chapter": "অধ্যায়ে {{number}} পৃষ্ঠা বাকি",
"Device": "যন্ত্র",
"E-Ink Mode": "ই-ইঙ্ক মোড"
}
@@ -603,5 +603,7 @@
"Size": "ཨང་",
"Cover": "དེབ་གྱི་སྤྱོད་བྱས་མ་ཐུབ།",
"Contain": "འབྱོར་བ།",
"{{number}} pages left in chapter": "དོན་ཚན་ནང་ཤོག་ཨང་ {{number}} ལོག་གི་འདུག།"
"{{number}} pages left in chapter": "དོན་ཚན་ནང་ཤོག་ཨང་ {{number}} ལོག་གི་འདུག།",
"Device": "རྐྱབ་སྐོར",
"E-Ink Mode": "ཡིག་སྒྱུར་སྤོ་བ"
}
@@ -607,5 +607,7 @@
"Size": "Größe",
"Cover": "Cover",
"Contain": "Inhalt",
"{{number}} pages left in chapter": "{{number}} Seiten verbleibend im Kapitel"
"{{number}} pages left in chapter": "{{number}} Seiten verbleibend im Kapitel",
"Device": "Gerät",
"E-Ink Mode": "E-Ink-Modus"
}
@@ -607,5 +607,7 @@
"Size": "Μέγεθος",
"Cover": "Εξώφυλλο",
"Contain": "Περιέχει",
"{{number}} pages left in chapter": "Μένουν {{number}} σελίδες στο κεφάλαιο"
"{{number}} pages left in chapter": "Μένουν {{number}} σελίδες στο κεφάλαιο",
"Device": "Συσκευή",
"E-Ink Mode": "Λειτουργία E-Ink"
}
@@ -611,5 +611,7 @@
"Size": "Tamaño",
"Cover": "Cubierta",
"Contain": "Contener",
"{{number}} pages left in chapter": "{{number}} páginas restantes en el capítulo"
"{{number}} pages left in chapter": "{{number}} páginas restantes en el capítulo",
"Device": "Dispositivo",
"E-Ink Mode": "Modo E-Ink"
}
@@ -611,5 +611,7 @@
"Size": "Taille",
"Cover": "Couverture",
"Contain": "Contenir",
"{{number}} pages left in chapter": "{{number}} pages restantes dans le chapitre"
"{{number}} pages left in chapter": "{{number}} pages restantes dans le chapitre",
"Device": "Appareil",
"E-Ink Mode": "Mode E-Ink"
}
@@ -607,5 +607,7 @@
"Size": "आकार",
"Cover": "कवर",
"Contain": "समाहित करें",
"{{number}} pages left in chapter": "इस अध्याय में {{number}} पृष्ठ शेष हैं"
"{{number}} pages left in chapter": "इस अध्याय में {{number}} पृष्ठ शेष हैं",
"Device": "डिवाइस",
"E-Ink Mode": "ई-इंक मोड"
}
@@ -603,5 +603,7 @@
"Size": "Ukuran",
"Cover": "Sampul",
"Contain": "Mengandung",
"{{number}} pages left in chapter": "{{number}} halaman tersisa di bab"
"{{number}} pages left in chapter": "{{number}} halaman tersisa di bab",
"Device": "Perangkat",
"E-Ink Mode": "Mode E-Ink"
}
@@ -611,5 +611,7 @@
"Size": "Dimensione",
"Cover": "Copertura",
"Contain": "Contenere",
"{{number}} pages left in chapter": "{{number}} pagine rimaste nel capitolo"
"{{number}} pages left in chapter": "{{number}} pagine rimaste nel capitolo",
"Device": "Dispositivo",
"E-Ink Mode": "Modalità E-Ink"
}
@@ -603,5 +603,7 @@
"Size": "サイズ",
"Cover": "カバー",
"Contain": "含む",
"{{number}} pages left in chapter": "章に{{number}}ページ残り"
"{{number}} pages left in chapter": "章に{{number}}ページ残り",
"Device": "デバイス",
"E-Ink Mode": "E-Inkモード"
}
@@ -603,5 +603,7 @@
"Size": "크기",
"Cover": "표지",
"Contain": "포함",
"{{number}} pages left in chapter": "남은 페이지 {{number}}장"
"{{number}} pages left in chapter": "남은 페이지 {{number}}장",
"Device": "장치",
"E-Ink Mode": "E-Ink 모드"
}
@@ -607,5 +607,7 @@
"Size": "Grootte",
"Cover": "Omslag",
"Contain": "Bevatten",
"{{number}} pages left in chapter": "Nog {{number}} paginas in hoofdstuk"
"{{number}} pages left in chapter": "Nog {{number}} paginas in hoofdstuk",
"Device": "Apparaat",
"E-Ink Mode": "E-Ink Modus"
}
@@ -615,5 +615,7 @@
"Size": "Rozmiar",
"Cover": "Okładka",
"Contain": "Zawierać",
"{{number}} pages left in chapter": "Pozostało {{number}} stron w rozdziale"
"{{number}} pages left in chapter": "Pozostało {{number}} stron w rozdziale",
"Device": "Urządzenie",
"E-Ink Mode": "Tryb E-Ink"
}
@@ -611,5 +611,7 @@
"Size": "Tamanho",
"Cover": "Capa",
"Contain": "Contém",
"{{number}} pages left in chapter": "Faltam {{number}} páginas neste capítulo"
"{{number}} pages left in chapter": "Faltam {{number}} páginas neste capítulo",
"Device": "Dispositivo",
"E-Ink Mode": "Modo E-Ink"
}
@@ -615,5 +615,7 @@
"Size": "Размер",
"Cover": "Обложка",
"Contain": "Содержать",
"{{number}} pages left in chapter": "Осталось {{number}} страниц в главе"
"{{number}} pages left in chapter": "Осталось {{number}} страниц в главе",
"Device": "Устройство",
"E-Ink Mode": "E-Ink режим"
}
@@ -607,5 +607,7 @@
"Size": "ප්‍රමාණය",
"Cover": "ආවරණය",
"Contain": "අඩංගු වන්න",
"{{number}} pages left in chapter": "පරිච්ඡේදයේ පිටු {{number}} ඉතිරිව ඇත"
"{{number}} pages left in chapter": "පරිච්ඡේදයේ පිටු {{number}} ඉතිරිව ඇත",
"Device": "උපකරණය",
"E-Ink Mode": "E-Ink ආකාරය"
}
@@ -607,5 +607,7 @@
"Size": "Storlek",
"Cover": "Omslag",
"Contain": "Innehålla",
"{{number}} pages left in chapter": "{{number}} sidor kvar i kapitlet"
"{{number}} pages left in chapter": "{{number}} sidor kvar i kapitlet",
"Device": "Enhet",
"E-Ink Mode": "E-Ink-läge"
}
@@ -607,5 +607,7 @@
"Size": "அளவு",
"Cover": "மூடு",
"Contain": "அடங்கும்",
"{{number}} pages left in chapter": "அத்தியாயத்தில் {{number}} பக்கங்கள் மீதமுள்ளன"
"{{number}} pages left in chapter": "அத்தியாயத்தில் {{number}} பக்கங்கள் மீதமுள்ளன",
"Device": "சாதனம்",
"E-Ink Mode": "E-Ink முறை"
}
@@ -603,5 +603,7 @@
"Size": "ขนาด",
"Cover": "ปก",
"Contain": "บรรจุ",
"{{number}} pages left in chapter": "เหลือ {{number}} หน้าในบท"
"{{number}} pages left in chapter": "เหลือ {{number}} หน้าในบท",
"Device": "อุปกรณ์",
"E-Ink Mode": "โหมด E-Ink"
}
@@ -607,5 +607,7 @@
"Size": "Boyut",
"Cover": "Kapak",
"Contain": "İçerir",
"{{number}} pages left in chapter": "Bu bölümde {{number}} sayfa kaldı"
"{{number}} pages left in chapter": "Bu bölümde {{number}} sayfa kaldı",
"Device": "Cihaz",
"E-Ink Mode": "E-Ink Modu"
}
@@ -615,5 +615,7 @@
"Size": "Розмір",
"Cover": "Обкладинка",
"Contain": "Вміщати",
"{{number}} pages left in chapter": "Залишилось {{number}} сторінок у розділі"
"{{number}} pages left in chapter": "Залишилось {{number}} сторінок у розділі",
"Device": "Пристрій",
"E-Ink Mode": "E-Ink режим"
}
@@ -603,5 +603,7 @@
"Size": "Kích thước",
"Cover": "Bìa",
"Contain": "Chứa",
"{{number}} pages left in chapter": "Còn {{number}} trang trong chương"
"{{number}} pages left in chapter": "Còn {{number}} trang trong chương",
"Device": "Thiết bị",
"E-Ink Mode": "Chế độ E-Ink"
}
@@ -603,5 +603,7 @@
"Size": "大小",
"Cover": "覆盖",
"Contain": "适应",
"{{number}} pages left in chapter": "本章剩余{{number}}页"
"{{number}} pages left in chapter": "本章剩余{{number}}页",
"Device": "设备",
"E-Ink Mode": "E-Ink 模式"
}
@@ -603,5 +603,7 @@
"Size": "大小",
"Cover": "覆蓋",
"Contain": "適應",
"{{number}} pages left in chapter": "本章剩餘{{number}}頁"
"{{number}} pages left in chapter": "本章剩餘{{number}}頁",
"Device": "設備",
"E-Ink Mode": "E-Ink 模式"
}
@@ -18,6 +18,7 @@ import { useProgressAutoSave } from '../hooks/useProgressAutoSave';
import { useBackgroundTexture } from '@/hooks/useBackgroundTexture';
import { useAutoFocus } from '@/hooks/useAutoFocus';
import { useTranslation } from '@/hooks/useTranslation';
import { useEinkMode } from '@/hooks/useEinkMode';
import { useKOSync } from '../hooks/useKOSync';
import {
applyFixedlayoutStyles,
@@ -77,6 +78,7 @@ const FoliateViewer: React.FC<{
const { getParallels } = useParallelViewStore();
const { getBookData } = useBookDataStore();
const { applyBackgroundTexture } = useBackgroundTexture();
const { applyEinkMode } = useEinkMode();
const viewState = getViewState(bookKey);
const viewSettings = getViewSettings(bookKey);
@@ -313,6 +315,7 @@ const FoliateViewer: React.FC<{
doubleClickDisabled.current = viewSettings.disableDoubleClick!;
const animated = viewSettings.animated!;
const eink = viewSettings.isEink!;
const maxColumnCount = viewSettings.maxColumnCount!;
const maxInlineSize = getMaxInlineSize(viewSettings);
const maxBlockSize = viewSettings.maxBlockSize!;
@@ -325,6 +328,14 @@ const FoliateViewer: React.FC<{
} else {
view.renderer.removeAttribute('animated');
}
if (appService?.isAndroidApp) {
if (eink) {
view.renderer.setAttribute('eink', '');
} else {
view.renderer.removeAttribute('eink');
}
applyEinkMode(eink);
}
if (bookDoc?.rendition?.layout === 'pre-paginated') {
view.renderer.setAttribute('zoom', viewSettings.zoomMode);
view.renderer.setAttribute('spread', viewSettings.spreadMode);
@@ -13,6 +13,7 @@ import { useDeviceControlStore } from '@/store/deviceStore';
import { useSafeAreaInsets } from '@/hooks/useSafeAreaInsets';
import { useDefaultIconSize } from '@/hooks/useResponsiveSize';
import { useBackgroundTexture } from '@/hooks/useBackgroundTexture';
import { useEinkMode } from '@/hooks/useEinkMode';
import { getLocale } from '@/utils/misc';
const Providers = ({ children }: { children: React.ReactNode }) => {
@@ -20,6 +21,7 @@ const Providers = ({ children }: { children: React.ReactNode }) => {
const { applyUILanguage } = useSettingsStore();
const { setScreenBrightness } = useDeviceControlStore();
const { applyBackgroundTexture } = useBackgroundTexture();
const { applyEinkMode } = useEinkMode();
const iconSize = useDefaultIconSize();
useSafeAreaInsets(); // Initialize safe area insets
@@ -48,6 +50,9 @@ const Providers = ({ children }: { children: React.ReactNode }) => {
setScreenBrightness(brightness / 100);
}
applyBackgroundTexture(envConfig, globalViewSettings);
if (appService.isAndroidApp) {
applyEinkMode(globalViewSettings.isEink);
}
});
}
}, [envConfig, appService, applyUILanguage, setScreenBrightness, applyBackgroundTexture]);
@@ -6,6 +6,7 @@ import { useTranslation } from '@/hooks/useTranslation';
import { useBookDataStore } from '@/store/bookDataStore';
import { useSettingsStore } from '@/store/settingsStore';
import { useResetViewSettings } from '@/hooks/useResetSettings';
import { useEinkMode } from '@/hooks/useEinkMode';
import { getStyles } from '@/utils/style';
import { saveAndReload } from '@/utils/reload';
import { getMaxInlineSize } from '@/utils/config';
@@ -19,6 +20,7 @@ const ControlPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterRes
const { getView, getViewSettings } = useReaderStore();
const { getBookData } = useBookDataStore();
const { settings } = useSettingsStore();
const { applyEinkMode } = useEinkMode();
const { acquireVolumeKeyInterception, releaseVolumeKeyInterception } = useDeviceControlStore();
const bookData = getBookData(bookKey);
const viewSettings = getViewSettings(bookKey) || settings.globalViewSettings;
@@ -31,6 +33,7 @@ const ControlPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterRes
const [swapClickArea, setSwapClickArea] = useState(viewSettings.swapClickArea);
const [isDisableDoubleClick, setIsDisableDoubleClick] = useState(viewSettings.disableDoubleClick);
const [animated, setAnimated] = useState(viewSettings.animated);
const [isEink, setIsEink] = useState(viewSettings.isEink);
const [allowScript, setAllowScript] = useState(viewSettings.allowScript);
const resetToDefaults = useResetViewSettings();
@@ -44,6 +47,7 @@ const ControlPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterRes
disableClick: setIsDisableClick,
swapClickArea: setSwapClickArea,
animated: setAnimated,
isEink: setIsEink,
allowScript: setAllowScript,
});
};
@@ -113,6 +117,17 @@ const ControlPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterRes
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [animated]);
useEffect(() => {
saveViewSettings(envConfig, bookKey, 'isEink', isEink, false, false);
if (isEink) {
getView(bookKey)?.renderer.setAttribute('eink', '');
} else {
getView(bookKey)?.renderer.removeAttribute('eink');
}
applyEinkMode(isEink);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isEink]);
useEffect(() => {
if (viewSettings.allowScript === allowScript) return;
saveViewSettings(envConfig, bookKey, 'allowScript', allowScript, true, false);
@@ -221,6 +236,25 @@ const ControlPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterRes
</div>
</div>
{appService?.isAndroidApp && (
<div className='w-full'>
<h2 className='mb-2 font-medium'>{_('Device')}</h2>
<div className='card border-base-200 bg-base-100 border shadow'>
<div className='divide-base-200 divide-y'>
<div className='config-item'>
<span className=''>{_('E-Ink Mode')}</span>
<input
type='checkbox'
className='toggle'
checked={isEink}
onChange={() => setIsEink(!isEink)}
/>
</div>
</div>
</div>
</div>
)}
<div className='w-full'>
<h2 className='mb-2 font-medium'>{_('Security')}</h2>
<div className='card border-base-200 bg-base-100 border shadow'>
+13
View File
@@ -0,0 +1,13 @@
import { useCallback } from 'react';
export const useEinkMode = () => {
const applyEinkMode = useCallback((isEink: boolean) => {
if (isEink) {
document.body.classList.add('no-transitions');
} else {
document.body.classList.remove('no-transitions');
}
}, []);
return { applyEinkMode };
};
@@ -132,6 +132,7 @@ export const DEFAULT_BOOK_LAYOUT: BookLayout = {
maxInlineSize: getDefaultMaxInlineSize(),
maxBlockSize: getDefaultMaxBlockSize(),
animated: false,
isEink: false,
writingMode: 'auto',
vertical: false,
rtl: false,
@@ -177,6 +178,8 @@ export const DEFAULT_MOBILE_VIEW_SETTINGS: Partial<ViewSettings> = {
export const DEFAULT_CJK_VIEW_SETTINGS: Partial<ViewSettings> = {
fullJustification: true,
textIndent: 2,
paragraphMargin: 1,
lineHeight: 1.6,
};
export const DEFAULT_FIXED_LAYOUT_VIEW_SETTINGS: Partial<ViewSettings> = {
+4
View File
@@ -382,3 +382,7 @@ foliate-view {
.animate-reverse-spin {
animation: spin-counterclockwise 1s linear;
}
.no-transitions * {
transition: none !important;
}
+1
View File
@@ -105,6 +105,7 @@ export interface BookLayout {
maxInlineSize: number;
maxBlockSize: number;
animated: boolean;
isEink: boolean;
writingMode: WritingMode;
vertical: boolean;
rtl: boolean;