@@ -1,10 +1,9 @@
|
||||
import clsx from 'clsx';
|
||||
import React, { useState } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { PiUserCircle } from 'react-icons/pi';
|
||||
import { PiUserCircleCheck } from 'react-icons/pi';
|
||||
import { PiUserCircle, PiUserCircleCheck, PiGear } from 'react-icons/pi';
|
||||
import { PiSun, PiMoon } from 'react-icons/pi';
|
||||
import { TbSunMoon } from 'react-icons/tb';
|
||||
import { BiMoon, BiSun } from 'react-icons/bi';
|
||||
|
||||
import { invoke, PermissionState } from '@tauri-apps/api/core';
|
||||
import { isTauriAppPlatform, isWebAppPlatform } from '@/services/environment';
|
||||
@@ -42,6 +41,7 @@ const SettingsMenu: React.FC<SettingsMenuProps> = ({ setIsDropdownOpen }) => {
|
||||
const { userPlan, quotas } = useQuotaStats(true);
|
||||
const { themeMode, setThemeMode } = useThemeStore();
|
||||
const { settings, setSettings, saveSettings } = useSettingsStore();
|
||||
const { setFontLayoutSettingsDialogOpen } = useSettingsStore();
|
||||
const [isAutoUpload, setIsAutoUpload] = useState(settings.autoUpload);
|
||||
const [isAutoCheckUpdates, setIsAutoCheckUpdates] = useState(settings.autoCheckUpdates);
|
||||
const [isAlwaysOnTop, setIsAlwaysOnTop] = useState(settings.alwaysOnTop);
|
||||
@@ -174,6 +174,11 @@ const SettingsMenu: React.FC<SettingsMenuProps> = ({ setIsDropdownOpen }) => {
|
||||
setIsDropdownOpen?.(false);
|
||||
};
|
||||
|
||||
const openSettingsDialog = () => {
|
||||
setIsDropdownOpen?.(false);
|
||||
setFontLayoutSettingsDialogOpen(true);
|
||||
};
|
||||
|
||||
const toggleAlwaysInForeground = async () => {
|
||||
const requestAlwaysInForeground = !settings.alwaysInForeground;
|
||||
|
||||
@@ -297,9 +302,10 @@ const SettingsMenu: React.FC<SettingsMenuProps> = ({ setIsDropdownOpen }) => {
|
||||
<MenuItem label={_('Reload Page')} onClick={handleReloadPage} />
|
||||
<MenuItem
|
||||
label={themeModeLabel}
|
||||
Icon={themeMode === 'dark' ? BiMoon : themeMode === 'light' ? BiSun : TbSunMoon}
|
||||
Icon={themeMode === 'dark' ? PiMoon : themeMode === 'light' ? PiSun : TbSunMoon}
|
||||
onClick={cycleThemeMode}
|
||||
/>
|
||||
<MenuItem label={_('Settings')} Icon={PiGear} onClick={openSettingsDialog} />
|
||||
{appService?.canCustomizeRootDir && (
|
||||
<>
|
||||
<hr aria-hidden='true' className='border-base-200 my-1' />
|
||||
|
||||
@@ -54,6 +54,7 @@ import LibraryHeader from './components/LibraryHeader';
|
||||
import Bookshelf from './components/Bookshelf';
|
||||
import useShortcuts from '@/hooks/useShortcuts';
|
||||
import DropIndicator from '@/components/DropIndicator';
|
||||
import SettingsDialog from '@/components/settings/SettingsDialog';
|
||||
|
||||
const LibraryPageWithSearchParams = () => {
|
||||
const searchParams = useSearchParams();
|
||||
@@ -77,6 +78,7 @@ const LibraryPageContent = ({ searchParams }: { searchParams: ReadonlyURLSearchP
|
||||
const { selectFiles } = useFileSelector(appService, _);
|
||||
const { safeAreaInsets: insets, isRoundedWindow } = useThemeStore();
|
||||
const { settings, setSettings, saveSettings } = useSettingsStore();
|
||||
const { isFontLayoutSettingsDialogOpen } = useSettingsStore();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const isInitiating = useRef(false);
|
||||
const [libraryLoaded, setLibraryLoaded] = useState(false);
|
||||
@@ -89,6 +91,7 @@ const LibraryPageContent = ({ searchParams }: { searchParams: ReadonlyURLSearchP
|
||||
}>({});
|
||||
const [pendingNavigationBookIds, setPendingNavigationBookIds] = useState<string[] | null>(null);
|
||||
const [isDragging, setIsDragging] = useState(false);
|
||||
|
||||
const demoBooks = useDemoBooks();
|
||||
const osRef = useRef<OverlayScrollbarsComponentRef>(null);
|
||||
const containerRef: React.MutableRefObject<HTMLDivElement | null> = useRef(null);
|
||||
@@ -730,6 +733,7 @@ const LibraryPageContent = ({ searchParams }: { searchParams: ReadonlyURLSearchP
|
||||
<AboutWindow />
|
||||
<UpdaterWindow />
|
||||
<MigrateDataWindow />
|
||||
{isFontLayoutSettingsDialogOpen && <SettingsDialog bookKey={''} />}
|
||||
<Toast />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -10,13 +10,13 @@ import { useBookDataStore } from '@/store/bookDataStore';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { getGridTemplate, getInsetEdges } from '@/utils/grid';
|
||||
import { getViewInsets } from '@/utils/insets';
|
||||
import SettingsDialog from '@/components/settings/SettingsDialog';
|
||||
import FoliateViewer from './FoliateViewer';
|
||||
import SectionInfo from './SectionInfo';
|
||||
import HeaderBar from './HeaderBar';
|
||||
import FooterBar from './FooterBar';
|
||||
import ProgressInfoView from './ProgressInfo';
|
||||
import Ribbon from './Ribbon';
|
||||
import SettingsDialog from './settings/SettingsDialog';
|
||||
import Annotator from './annotator/Annotator';
|
||||
import FootnotePopup from './FootnotePopup';
|
||||
import HintInfo from './HintInfo';
|
||||
@@ -34,7 +34,7 @@ const BooksGrid: React.FC<BooksGridProps> = ({ bookKeys, onCloseBook }) => {
|
||||
const { getProgress, getViewState, getViewSettings } = useReaderStore();
|
||||
const { setGridInsets, hoveredBookKey } = useReaderStore();
|
||||
const { sideBarBookKey } = useSidebarStore();
|
||||
const { isFontLayoutSettingsDialogOpen, setFontLayoutSettingsDialogOpen } = useSettingsStore();
|
||||
const { isFontLayoutSettingsDialogOpen } = useSettingsStore();
|
||||
|
||||
const { safeAreaInsets: screenInsets } = useThemeStore();
|
||||
const aspectRatio = window.innerWidth / window.innerHeight;
|
||||
@@ -120,7 +120,6 @@ const BooksGrid: React.FC<BooksGridProps> = ({ bookKeys, onCloseBook }) => {
|
||||
isTopLeft={index === 0}
|
||||
isHoveredAnim={bookKeys.length > 2}
|
||||
onCloseBook={onCloseBook}
|
||||
onSetSettingsDialogOpen={setFontLayoutSettingsDialogOpen}
|
||||
gridInsets={gridInsets}
|
||||
/>
|
||||
<FoliateViewer
|
||||
@@ -203,7 +202,7 @@ const BooksGrid: React.FC<BooksGridProps> = ({ bookKeys, onCloseBook }) => {
|
||||
isHoveredAnim={false}
|
||||
gridInsets={gridInsets}
|
||||
/>
|
||||
{isFontLayoutSettingsDialogOpen && <SettingsDialog bookKey={bookKey} config={config} />}
|
||||
{isFontLayoutSettingsDialogOpen && <SettingsDialog bookKey={bookKey} />}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -18,9 +18,9 @@ import { useSidebarStore } from '@/store/sidebarStore';
|
||||
import { useBookDataStore } from '@/store/bookDataStore';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { useResponsiveSize } from '@/hooks/useResponsiveSize';
|
||||
import { saveViewSettings } from '@/helpers/viewSettings';
|
||||
import { eventDispatcher } from '@/utils/event';
|
||||
import { viewPagination } from '../hooks/usePagination';
|
||||
import { saveViewSettings } from '../utils/viewSettingsHelper';
|
||||
import { PageInfo } from '@/types/book';
|
||||
import { Insets } from '@/types/misc';
|
||||
import Button from '@/components/Button';
|
||||
|
||||
@@ -26,7 +26,6 @@ interface HeaderBarProps {
|
||||
isHoveredAnim: boolean;
|
||||
gridInsets: Insets;
|
||||
onCloseBook: (bookKey: string) => void;
|
||||
onSetSettingsDialogOpen: (open: boolean) => void;
|
||||
}
|
||||
|
||||
const HeaderBar: React.FC<HeaderBarProps> = ({
|
||||
@@ -36,7 +35,6 @@ const HeaderBar: React.FC<HeaderBarProps> = ({
|
||||
isHoveredAnim,
|
||||
gridInsets,
|
||||
onCloseBook,
|
||||
onSetSettingsDialogOpen,
|
||||
}) => {
|
||||
const _ = useTranslation();
|
||||
const { appService } = useEnv();
|
||||
@@ -185,7 +183,7 @@ const HeaderBar: React.FC<HeaderBarProps> = ({
|
||||
toggleButton={<PiDotsThreeVerticalBold size={iconSize16} />}
|
||||
onToggle={handleToggleDropdown}
|
||||
>
|
||||
<ViewMenu bookKey={bookKey} onSetSettingsDialogOpen={onSetSettingsDialogOpen} />
|
||||
<ViewMenu bookKey={bookKey} />
|
||||
</Dropdown>
|
||||
|
||||
<WindowButtons
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useEnv } from '@/context/EnvContext';
|
||||
import { useReaderStore } from '@/store/readerStore';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { useBookDataStore } from '@/store/bookDataStore';
|
||||
import { saveViewSettings } from '../utils/viewSettingsHelper';
|
||||
import { saveViewSettings } from '@/helpers/viewSettings';
|
||||
import { isTranslationAvailable } from '@/services/translators/utils';
|
||||
import Button from '@/components/Button';
|
||||
|
||||
|
||||
@@ -16,32 +16,29 @@ import { useAuth } from '@/context/AuthContext';
|
||||
import { useThemeStore } from '@/store/themeStore';
|
||||
import { useReaderStore } from '@/store/readerStore';
|
||||
import { useBookDataStore } from '@/store/bookDataStore';
|
||||
import { useSettingsStore } from '@/store/settingsStore';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { getStyles } from '@/utils/style';
|
||||
import { navigateToLogin } from '@/utils/nav';
|
||||
import { eventDispatcher } from '@/utils/event';
|
||||
import { getMaxInlineSize } from '@/utils/config';
|
||||
import { saveViewSettings } from '@/helpers/viewSettings';
|
||||
import { tauriHandleToggleFullScreen } from '@/utils/window';
|
||||
import { saveViewSettings } from '../utils/viewSettingsHelper';
|
||||
import MenuItem from '@/components/MenuItem';
|
||||
import Menu from '@/components/Menu';
|
||||
|
||||
interface ViewMenuProps {
|
||||
bookKey: string;
|
||||
setIsDropdownOpen?: (open: boolean) => void;
|
||||
onSetSettingsDialogOpen: (open: boolean) => void;
|
||||
}
|
||||
|
||||
const ViewMenu: React.FC<ViewMenuProps> = ({
|
||||
bookKey,
|
||||
setIsDropdownOpen,
|
||||
onSetSettingsDialogOpen,
|
||||
}) => {
|
||||
const ViewMenu: React.FC<ViewMenuProps> = ({ bookKey, setIsDropdownOpen }) => {
|
||||
const _ = useTranslation();
|
||||
const router = useRouter();
|
||||
const { user } = useAuth();
|
||||
const { envConfig, appService } = useEnv();
|
||||
const { getConfig, getBookData } = useBookDataStore();
|
||||
const { setFontLayoutSettingsDialogOpen } = useSettingsStore();
|
||||
const { getView, getViewSettings, getViewState, setViewSettings } = useReaderStore();
|
||||
const config = getConfig(bookKey)!;
|
||||
const bookData = getBookData(bookKey)!;
|
||||
@@ -65,7 +62,7 @@ const ViewMenu: React.FC<ViewMenuProps> = ({
|
||||
|
||||
const openFontLayoutMenu = () => {
|
||||
setIsDropdownOpen?.(false);
|
||||
onSetSettingsDialogOpen(true);
|
||||
setFontLayoutSettingsDialogOpen(true);
|
||||
};
|
||||
|
||||
const cycleThemeMode = () => {
|
||||
|
||||
@@ -87,7 +87,7 @@ export const AboutWindow = () => {
|
||||
boxClassName='sm:!w-[480px] sm:!max-w-screen-sm sm:h-auto'
|
||||
>
|
||||
{isOpen && (
|
||||
<div className='about-content flex h-full flex-col items-center justify-center gap-4'>
|
||||
<div className='about-content flex h-full flex-col items-center justify-center gap-4 pb-10 sm:pb-0'>
|
||||
<div className='flex flex-1 flex-col items-center justify-end gap-2 px-8 py-2'>
|
||||
<div className='mb-2 mt-6'>
|
||||
<Image src='/icon.png' alt='App Logo' className='h-20 w-20' width={64} height={64} />
|
||||
|
||||
@@ -402,7 +402,7 @@ export const UpdaterContent = ({
|
||||
</div>
|
||||
<div className='text-base-content text-sm'>
|
||||
<h3 className='mb-2 font-bold'>{_('Changelog')}</h3>
|
||||
<div className='bg-base-300 mb-4 rounded-lg px-4 pb-2 pt-4'>
|
||||
<div className='bg-base-200 mb-4 rounded-lg px-4 pb-2 pt-4'>
|
||||
{changelogs.length > 0 ? (
|
||||
changelogs.map((entry: Changelog) => (
|
||||
<div key={entry.version} className='mb-4'>
|
||||
|
||||
+6
-6
@@ -18,8 +18,8 @@ import { useReaderStore } from '@/store/readerStore';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { useSettingsStore } from '@/store/settingsStore';
|
||||
import { useResponsiveSize } from '@/hooks/useResponsiveSize';
|
||||
import { useResetViewSettings } from '../../hooks/useResetSettings';
|
||||
import { saveViewSettings } from '../../utils/viewSettingsHelper';
|
||||
import { useResetViewSettings } from '@/hooks/useResetSettings';
|
||||
import { saveViewSettings } from '@/helpers/viewSettings';
|
||||
import { CODE_LANGUAGES, CodeLanguage, manageSyntaxHighlighting } from '@/utils/highlightjs';
|
||||
import { SettingsPanelPanelProp } from './SettingsDialog';
|
||||
import Select from '@/components/Select';
|
||||
@@ -32,7 +32,7 @@ const ColorPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterReset
|
||||
const { envConfig } = useEnv();
|
||||
const { settings, setSettings } = useSettingsStore();
|
||||
const { getView, getViewSettings } = useReaderStore();
|
||||
const viewSettings = getViewSettings(bookKey)!;
|
||||
const viewSettings = getViewSettings(bookKey) || settings.globalViewSettings;
|
||||
const [invertImgColorInDark, setInvertImgColorInDark] = useState(
|
||||
viewSettings.invertImgColorInDark,
|
||||
);
|
||||
@@ -42,9 +42,9 @@ const ColorPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterReset
|
||||
const [editTheme, setEditTheme] = useState<CustomTheme | null>(null);
|
||||
const [customThemes, setCustomThemes] = useState<Theme[]>([]);
|
||||
const [showCustomThemeEditor, setShowCustomThemeEditor] = useState(false);
|
||||
const [overrideColor, setOverrideColor] = useState(viewSettings.overrideColor!);
|
||||
const [codeHighlighting, setcodeHighlighting] = useState(viewSettings.codeHighlighting!);
|
||||
const [codeLanguage, setCodeLanguage] = useState(viewSettings.codeLanguage!);
|
||||
const [overrideColor, setOverrideColor] = useState(viewSettings.overrideColor);
|
||||
const [codeHighlighting, setcodeHighlighting] = useState(viewSettings.codeHighlighting);
|
||||
const [codeLanguage, setCodeLanguage] = useState(viewSettings.codeLanguage);
|
||||
|
||||
const resetToDefaults = useResetViewSettings();
|
||||
|
||||
+16
-16
@@ -4,11 +4,12 @@ import { useReaderStore } from '@/store/readerStore';
|
||||
import { useDeviceControlStore } from '@/store/deviceStore';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { useBookDataStore } from '@/store/bookDataStore';
|
||||
import { useResetViewSettings } from '../../hooks/useResetSettings';
|
||||
import { useSettingsStore } from '@/store/settingsStore';
|
||||
import { useResetViewSettings } from '@/hooks/useResetSettings';
|
||||
import { getStyles } from '@/utils/style';
|
||||
import { saveAndReload } from '@/utils/reload';
|
||||
import { getMaxInlineSize } from '@/utils/config';
|
||||
import { saveViewSettings } from '../../utils/viewSettingsHelper';
|
||||
import { saveViewSettings } from '@/helpers/viewSettings';
|
||||
import { SettingsPanelPanelProp } from './SettingsDialog';
|
||||
import NumberInput from './NumberInput';
|
||||
|
||||
@@ -17,21 +18,20 @@ const ControlPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterRes
|
||||
const { envConfig, appService } = useEnv();
|
||||
const { getView, getViewSettings } = useReaderStore();
|
||||
const { getBookData } = useBookDataStore();
|
||||
const { settings } = useSettingsStore();
|
||||
const { acquireVolumeKeyInterception, releaseVolumeKeyInterception } = useDeviceControlStore();
|
||||
const bookData = getBookData(bookKey)!;
|
||||
const viewSettings = getViewSettings(bookKey)!;
|
||||
const bookData = getBookData(bookKey);
|
||||
const viewSettings = getViewSettings(bookKey) || settings.globalViewSettings;
|
||||
|
||||
const [isScrolledMode, setScrolledMode] = useState(viewSettings.scrolled!);
|
||||
const [isContinuousScroll, setIsContinuousScroll] = useState(viewSettings.continuousScroll!);
|
||||
const [scrollingOverlap, setScrollingOverlap] = useState(viewSettings.scrollingOverlap!);
|
||||
const [volumeKeysToFlip, setVolumeKeysToFlip] = useState(viewSettings.volumeKeysToFlip!);
|
||||
const [isDisableClick, setIsDisableClick] = useState(viewSettings.disableClick!);
|
||||
const [swapClickArea, setSwapClickArea] = useState(viewSettings.swapClickArea!);
|
||||
const [isDisableDoubleClick, setIsDisableDoubleClick] = useState(
|
||||
viewSettings.disableDoubleClick!,
|
||||
);
|
||||
const [animated, setAnimated] = useState(viewSettings.animated!);
|
||||
const [allowScript, setAllowScript] = useState(viewSettings.allowScript!);
|
||||
const [isScrolledMode, setScrolledMode] = useState(viewSettings.scrolled);
|
||||
const [isContinuousScroll, setIsContinuousScroll] = useState(viewSettings.continuousScroll);
|
||||
const [scrollingOverlap, setScrollingOverlap] = useState(viewSettings.scrollingOverlap);
|
||||
const [volumeKeysToFlip, setVolumeKeysToFlip] = useState(viewSettings.volumeKeysToFlip);
|
||||
const [isDisableClick, setIsDisableClick] = useState(viewSettings.disableClick);
|
||||
const [swapClickArea, setSwapClickArea] = useState(viewSettings.swapClickArea);
|
||||
const [isDisableDoubleClick, setIsDisableDoubleClick] = useState(viewSettings.disableDoubleClick);
|
||||
const [animated, setAnimated] = useState(viewSettings.animated);
|
||||
const [allowScript, setAllowScript] = useState(viewSettings.allowScript);
|
||||
|
||||
const resetToDefaults = useResetViewSettings();
|
||||
|
||||
@@ -234,7 +234,7 @@ const ControlPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterRes
|
||||
type='checkbox'
|
||||
className='toggle'
|
||||
checked={allowScript}
|
||||
disabled={bookData.book?.format !== 'EPUB'}
|
||||
disabled={bookData?.book?.format !== 'EPUB'}
|
||||
onChange={() => setAllowScript(!allowScript)}
|
||||
/>
|
||||
</div>
|
||||
+4
-2
@@ -5,10 +5,11 @@ import { IoMdCloseCircleOutline } from 'react-icons/io';
|
||||
import { useEnv } from '@/context/EnvContext';
|
||||
import { useReaderStore } from '@/store/readerStore';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { useSettingsStore } from '@/store/settingsStore';
|
||||
import { useCustomFontStore } from '@/store/customFontStore';
|
||||
import { useFileSelector } from '@/hooks/useFileSelector';
|
||||
import { saveViewSettings } from '@/helpers/viewSettings';
|
||||
import { CustomFont, mountCustomFont } from '@/styles/fonts';
|
||||
import { saveViewSettings } from '../../utils/viewSettingsHelper';
|
||||
|
||||
interface CustomFontsProps {
|
||||
bookKey: string;
|
||||
@@ -23,6 +24,7 @@ type FontFamily = {
|
||||
const CustomFonts: React.FC<CustomFontsProps> = ({ bookKey, onBack }) => {
|
||||
const _ = useTranslation();
|
||||
const { appService, envConfig } = useEnv();
|
||||
const { settings } = useSettingsStore();
|
||||
const {
|
||||
fonts: customFonts,
|
||||
addFont,
|
||||
@@ -32,7 +34,7 @@ const CustomFonts: React.FC<CustomFontsProps> = ({ bookKey, onBack }) => {
|
||||
saveCustomFonts,
|
||||
} = useCustomFontStore();
|
||||
const { getViewSettings } = useReaderStore();
|
||||
const viewSettings = getViewSettings(bookKey)!;
|
||||
const viewSettings = getViewSettings(bookKey) || settings.globalViewSettings;
|
||||
const [isDeleteMode, setIsDeleteMode] = useState(false);
|
||||
|
||||
const { selectFiles } = useFileSelector(appService, _);
|
||||
+14
-14
@@ -27,8 +27,8 @@ import { getOSPlatform, isCJKEnv } from '@/utils/misc';
|
||||
import { getSysFontsList } from '@/utils/bridge';
|
||||
import { isCJKStr } from '@/utils/lang';
|
||||
import { isTauriAppPlatform } from '@/services/environment';
|
||||
import { saveViewSettings } from '../../utils/viewSettingsHelper';
|
||||
import { useResetViewSettings } from '../../hooks/useResetSettings';
|
||||
import { useResetViewSettings } from '@/hooks/useResetSettings';
|
||||
import { saveViewSettings } from '@/helpers/viewSettings';
|
||||
import { SettingsPanelPanelProp } from './SettingsDialog';
|
||||
import NumberInput from './NumberInput';
|
||||
import FontDropdown from './FontDropDown';
|
||||
@@ -91,7 +91,7 @@ const FontPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterReset
|
||||
const _ = useTranslation();
|
||||
const { envConfig, appService } = useEnv();
|
||||
const { getView, getViewSettings } = useReaderStore();
|
||||
const { fontPanelView, setFontPanelView } = useSettingsStore();
|
||||
const { settings, fontPanelView, setFontPanelView } = useSettingsStore();
|
||||
const {
|
||||
fonts: allCustomFonts,
|
||||
getAllFonts,
|
||||
@@ -99,8 +99,8 @@ const FontPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterReset
|
||||
removeFont,
|
||||
saveCustomFonts,
|
||||
} = useCustomFontStore();
|
||||
const viewSettings = getViewSettings(bookKey)!;
|
||||
const view = getView(bookKey)!;
|
||||
const viewSettings = getViewSettings(bookKey) || settings.globalViewSettings;
|
||||
const view = getView(bookKey);
|
||||
const iconSize18 = useResponsiveSize(18);
|
||||
|
||||
const fontFamilyOptions = [
|
||||
@@ -136,15 +136,15 @@ const FontPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterReset
|
||||
break;
|
||||
}
|
||||
const [sysFonts, setSysFonts] = useState<string[]>(defaultSysFonts);
|
||||
const [defaultFont, setDefaultFont] = useState(viewSettings.defaultFont!);
|
||||
const [defaultFontSize, setDefaultFontSize] = useState(viewSettings.defaultFontSize!);
|
||||
const [minFontSize, setMinFontSize] = useState(viewSettings.minimumFontSize!);
|
||||
const [overrideFont, setOverrideFont] = useState(viewSettings.overrideFont!);
|
||||
const [defaultCJKFont, setDefaultCJKFont] = useState(viewSettings.defaultCJKFont!);
|
||||
const [serifFont, setSerifFont] = useState(viewSettings.serifFont!);
|
||||
const [sansSerifFont, setSansSerifFont] = useState(viewSettings.sansSerifFont!);
|
||||
const [monospaceFont, setMonospaceFont] = useState(viewSettings.monospaceFont!);
|
||||
const [fontWeight, setFontWeight] = useState(viewSettings.fontWeight!);
|
||||
const [defaultFont, setDefaultFont] = useState(viewSettings.defaultFont);
|
||||
const [defaultFontSize, setDefaultFontSize] = useState(viewSettings.defaultFontSize);
|
||||
const [minFontSize, setMinFontSize] = useState(viewSettings.minimumFontSize);
|
||||
const [overrideFont, setOverrideFont] = useState(viewSettings.overrideFont);
|
||||
const [defaultCJKFont, setDefaultCJKFont] = useState(viewSettings.defaultCJKFont);
|
||||
const [serifFont, setSerifFont] = useState(viewSettings.serifFont);
|
||||
const [sansSerifFont, setSansSerifFont] = useState(viewSettings.sansSerifFont);
|
||||
const [monospaceFont, setMonospaceFont] = useState(viewSettings.monospaceFont);
|
||||
const [fontWeight, setFontWeight] = useState(viewSettings.fontWeight);
|
||||
|
||||
const [customFonts, setCustomFonts] = useState<string[]>(getFontFamilies());
|
||||
const [CJKFonts, setCJKFonts] = useState<string[]>(() => {
|
||||
+9
-9
@@ -5,11 +5,11 @@ import { useAuth } from '@/context/AuthContext';
|
||||
import { useReaderStore } from '@/store/readerStore';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { useSettingsStore } from '@/store/settingsStore';
|
||||
import { saveViewSettings } from '../../utils/viewSettingsHelper';
|
||||
import { saveViewSettings } from '@/helpers/viewSettings';
|
||||
import { getTranslators } from '@/services/translators';
|
||||
import { useResetViewSettings } from '@/hooks/useResetSettings';
|
||||
import { TRANSLATED_LANGS, TRANSLATOR_LANGS } from '@/services/constants';
|
||||
import { SettingsPanelPanelProp } from './SettingsDialog';
|
||||
import { useResetViewSettings } from '../../hooks/useResetSettings';
|
||||
import { saveAndReload } from '@/utils/reload';
|
||||
import Select from '@/components/Select';
|
||||
|
||||
@@ -17,15 +17,15 @@ const LangPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterReset
|
||||
const _ = useTranslation();
|
||||
const { token } = useAuth();
|
||||
const { envConfig } = useEnv();
|
||||
const { applyUILanguage } = useSettingsStore();
|
||||
const { settings, applyUILanguage } = useSettingsStore();
|
||||
const { getViewSettings, setViewSettings } = useReaderStore();
|
||||
const viewSettings = getViewSettings(bookKey)!;
|
||||
const viewSettings = getViewSettings(bookKey) || settings.globalViewSettings;
|
||||
|
||||
const [uiLanguage, setUILanguage] = useState(viewSettings.uiLanguage!);
|
||||
const [translationEnabled, setTranslationEnabled] = useState(viewSettings.translationEnabled!);
|
||||
const [translationProvider, setTranslationProvider] = useState(viewSettings.translationProvider!);
|
||||
const [translateTargetLang, setTranslateTargetLang] = useState(viewSettings.translateTargetLang!);
|
||||
const [showTranslateSource, setShowTranslateSource] = useState(viewSettings.showTranslateSource!);
|
||||
const [uiLanguage, setUILanguage] = useState(viewSettings.uiLanguage);
|
||||
const [translationEnabled, setTranslationEnabled] = useState(viewSettings.translationEnabled);
|
||||
const [translationProvider, setTranslationProvider] = useState(viewSettings.translationProvider);
|
||||
const [translateTargetLang, setTranslateTargetLang] = useState(viewSettings.translateTargetLang);
|
||||
const [showTranslateSource, setShowTranslateSource] = useState(viewSettings.showTranslateSource);
|
||||
|
||||
const resetToDefaults = useResetViewSettings();
|
||||
|
||||
+39
-38
@@ -7,14 +7,15 @@ import { TbTextDirectionRtl } from 'react-icons/tb';
|
||||
import { useEnv } from '@/context/EnvContext';
|
||||
import { useReaderStore } from '@/store/readerStore';
|
||||
import { useBookDataStore } from '@/store/bookDataStore';
|
||||
import { useSettingsStore } from '@/store/settingsStore';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { useResetViewSettings } from '../../hooks/useResetSettings';
|
||||
import { useResetViewSettings } from '@/hooks/useResetSettings';
|
||||
import { isCJKEnv } from '@/utils/misc';
|
||||
import { getStyles } from '@/utils/style';
|
||||
import { saveAndReload } from '@/utils/reload';
|
||||
import { getMaxInlineSize } from '@/utils/config';
|
||||
import { lockScreenOrientation } from '@/utils/bridge';
|
||||
import { saveViewSettings } from '../../utils/viewSettingsHelper';
|
||||
import { saveViewSettings } from '@/helpers/viewSettings';
|
||||
import { getBookDirFromWritingMode, getBookLangCode } from '@/utils/book';
|
||||
import { MIGHT_BE_RTL_LANGS } from '@/services/constants';
|
||||
import { SettingsPanelPanelProp } from './SettingsDialog';
|
||||
@@ -24,52 +25,52 @@ import NumberInput from './NumberInput';
|
||||
const LayoutPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterReset }) => {
|
||||
const _ = useTranslation();
|
||||
const { envConfig, appService } = useEnv();
|
||||
const { settings } = useSettingsStore();
|
||||
const { getView, getViewSettings, getGridInsets, setViewSettings } = useReaderStore();
|
||||
const { getBookData } = useBookDataStore();
|
||||
const view = getView(bookKey);
|
||||
const bookData = getBookData(bookKey)!;
|
||||
const viewSettings = getViewSettings(bookKey)!;
|
||||
const gridInsets = getGridInsets(bookKey)!;
|
||||
const viewSettings = getViewSettings(bookKey) || settings.globalViewSettings;
|
||||
|
||||
const [paragraphMargin, setParagraphMargin] = useState(viewSettings.paragraphMargin!);
|
||||
const [lineHeight, setLineHeight] = useState(viewSettings.lineHeight!);
|
||||
const [wordSpacing, setWordSpacing] = useState(viewSettings.wordSpacing!);
|
||||
const [letterSpacing, setLetterSpacing] = useState(viewSettings.letterSpacing!);
|
||||
const view = getView(bookKey);
|
||||
const bookData = getBookData(bookKey);
|
||||
const gridInsets = getGridInsets(bookKey) || { top: 0, bottom: 0, left: 0, right: 0 };
|
||||
|
||||
const [paragraphMargin, setParagraphMargin] = useState(viewSettings.paragraphMargin);
|
||||
const [lineHeight, setLineHeight] = useState(viewSettings.lineHeight);
|
||||
const [wordSpacing, setWordSpacing] = useState(viewSettings.wordSpacing);
|
||||
const [letterSpacing, setLetterSpacing] = useState(viewSettings.letterSpacing);
|
||||
const [textIndent, setTextIndent] = useState(viewSettings.textIndent!);
|
||||
const [fullJustification, setFullJustification] = useState(viewSettings.fullJustification!);
|
||||
const [hyphenation, setHyphenation] = useState(viewSettings.hyphenation!);
|
||||
const [marginTopPx, setMarginTopPx] = useState(
|
||||
viewSettings.marginPx || viewSettings.marginTopPx!,
|
||||
);
|
||||
const [marginBottomPx, setMarginBottomPx] = useState(viewSettings.marginBottomPx!);
|
||||
const [marginLeftPx, setMarginLeftPx] = useState(viewSettings.marginLeftPx!);
|
||||
const [marginRightPx, setMarginRightPx] = useState(viewSettings.marginRightPx!);
|
||||
const [fullJustification, setFullJustification] = useState(viewSettings.fullJustification);
|
||||
const [hyphenation, setHyphenation] = useState(viewSettings.hyphenation);
|
||||
const [marginTopPx, setMarginTopPx] = useState(viewSettings.marginPx || viewSettings.marginTopPx);
|
||||
const [marginBottomPx, setMarginBottomPx] = useState(viewSettings.marginBottomPx);
|
||||
const [marginLeftPx, setMarginLeftPx] = useState(viewSettings.marginLeftPx);
|
||||
const [marginRightPx, setMarginRightPx] = useState(viewSettings.marginRightPx);
|
||||
const [compactMarginTopPx, setCompactMarginTopPx] = useState(
|
||||
viewSettings.compactMarginPx || viewSettings.compactMarginTopPx!,
|
||||
viewSettings.compactMarginPx || viewSettings.compactMarginTopPx,
|
||||
);
|
||||
const [compactMarginBottomPx, setCompactMarginBottomPx] = useState(
|
||||
viewSettings.compactMarginBottomPx!,
|
||||
viewSettings.compactMarginBottomPx,
|
||||
);
|
||||
const [gapPercent, setGapPercent] = useState(viewSettings.gapPercent!);
|
||||
const [compactMarginLeftPx, setCompactMarginLeftPx] = useState(viewSettings.compactMarginLeftPx!);
|
||||
const [gapPercent, setGapPercent] = useState(viewSettings.gapPercent);
|
||||
const [compactMarginLeftPx, setCompactMarginLeftPx] = useState(viewSettings.compactMarginLeftPx);
|
||||
const [compactMarginRightPx, setCompactMarginRightPx] = useState(
|
||||
viewSettings.compactMarginRightPx!,
|
||||
viewSettings.compactMarginRightPx,
|
||||
);
|
||||
const [maxColumnCount, setMaxColumnCount] = useState(viewSettings.maxColumnCount!);
|
||||
const [maxInlineSize, setMaxInlineSize] = useState(viewSettings.maxInlineSize!);
|
||||
const [maxBlockSize, setMaxBlockSize] = useState(viewSettings.maxBlockSize!);
|
||||
const [writingMode, setWritingMode] = useState(viewSettings.writingMode!);
|
||||
const [overrideLayout, setOverrideLayout] = useState(viewSettings.overrideLayout!);
|
||||
const [doubleBorder, setDoubleBorder] = useState(viewSettings.doubleBorder!);
|
||||
const [borderColor, setBorderColor] = useState(viewSettings.borderColor!);
|
||||
const [showHeader, setShowHeader] = useState(viewSettings.showHeader!);
|
||||
const [showFooter, setShowFooter] = useState(viewSettings.showFooter!);
|
||||
const [showBarsOnScroll, setShowBarsOnScroll] = useState(viewSettings.showBarsOnScroll!);
|
||||
const [showRemainingTime, setShowRemainingTime] = useState(viewSettings.showRemainingTime!);
|
||||
const [showRemainingPages, setShowRemainingPages] = useState(viewSettings.showRemainingPages!);
|
||||
const [showProgressInfo, setShowProgressInfo] = useState(viewSettings.showProgressInfo!);
|
||||
const [maxColumnCount, setMaxColumnCount] = useState(viewSettings.maxColumnCount);
|
||||
const [maxInlineSize, setMaxInlineSize] = useState(viewSettings.maxInlineSize);
|
||||
const [maxBlockSize, setMaxBlockSize] = useState(viewSettings.maxBlockSize);
|
||||
const [writingMode, setWritingMode] = useState(viewSettings.writingMode);
|
||||
const [overrideLayout, setOverrideLayout] = useState(viewSettings.overrideLayout);
|
||||
const [doubleBorder, setDoubleBorder] = useState(viewSettings.doubleBorder);
|
||||
const [borderColor, setBorderColor] = useState(viewSettings.borderColor);
|
||||
const [showHeader, setShowHeader] = useState(viewSettings.showHeader);
|
||||
const [showFooter, setShowFooter] = useState(viewSettings.showFooter);
|
||||
const [showBarsOnScroll, setShowBarsOnScroll] = useState(viewSettings.showBarsOnScroll);
|
||||
const [showRemainingTime, setShowRemainingTime] = useState(viewSettings.showRemainingTime);
|
||||
const [showRemainingPages, setShowRemainingPages] = useState(viewSettings.showRemainingPages);
|
||||
const [showProgressInfo, setShowProgressInfo] = useState(viewSettings.showProgressInfo);
|
||||
const [progressStyle, setProgressStyle] = useState(viewSettings.progressStyle);
|
||||
const [screenOrientation, setScreenOrientation] = useState(viewSettings.screenOrientation!);
|
||||
const [screenOrientation, setScreenOrientation] = useState(viewSettings.screenOrientation);
|
||||
const resetToDefaults = useResetViewSettings();
|
||||
|
||||
const handleReset = () => {
|
||||
@@ -363,7 +364,7 @@ const LayoutPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterRese
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [screenOrientation]);
|
||||
|
||||
const langCode = getBookLangCode(bookData.bookDoc?.metadata?.language);
|
||||
const langCode = getBookLangCode(bookData?.bookDoc?.metadata?.language);
|
||||
const mightBeRTLBook = MIGHT_BE_RTL_LANGS.includes(langCode) || isCJKEnv();
|
||||
const isVertical = viewSettings.vertical || writingMode.includes('vertical');
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@ import { useEnv } from '@/context/EnvContext';
|
||||
import { useReaderStore } from '@/store/readerStore';
|
||||
import { useSettingsStore } from '@/store/settingsStore';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { useResetViewSettings } from '../../hooks/useResetSettings';
|
||||
import { useResetViewSettings } from '@/hooks/useResetSettings';
|
||||
import { SettingsPanelPanelProp } from './SettingsDialog';
|
||||
import { getStyles } from '@/utils/style';
|
||||
import cssValidate from '@/utils/css';
|
||||
@@ -18,7 +18,7 @@ const MiscPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterReset
|
||||
const { appService } = useEnv();
|
||||
const { settings, isFontLayoutSettingsGlobal, setSettings } = useSettingsStore();
|
||||
const { getView, getViewSettings, setViewSettings } = useReaderStore();
|
||||
const viewSettings = getViewSettings(bookKey)!;
|
||||
const viewSettings = getViewSettings(bookKey) || settings.globalViewSettings;
|
||||
|
||||
const [draftContentStylesheet, setDraftContentStylesheet] = useState(viewSettings.userStylesheet);
|
||||
const [draftContentStylesheetSaved, setDraftContentStylesheetSaved] = useState(true);
|
||||
+2
-3
@@ -1,6 +1,5 @@
|
||||
import clsx from 'clsx';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { BookConfig } from '@/types/book';
|
||||
import { useEnv } from '@/context/EnvContext';
|
||||
import { useSettingsStore } from '@/store/settingsStore';
|
||||
import { useResponsiveSize } from '@/hooks/useResponsiveSize';
|
||||
@@ -35,7 +34,7 @@ type TabConfig = {
|
||||
label: string;
|
||||
};
|
||||
|
||||
const SettingsDialog: React.FC<{ bookKey: string; config: BookConfig }> = ({ bookKey }) => {
|
||||
const SettingsDialog: React.FC<{ bookKey: string }> = ({ bookKey }) => {
|
||||
const _ = useTranslation();
|
||||
const { appService } = useEnv();
|
||||
const closeIconSize = useResponsiveSize(16);
|
||||
@@ -168,7 +167,7 @@ const SettingsDialog: React.FC<{ bookKey: string; config: BookConfig }> = ({ boo
|
||||
isOpen={true}
|
||||
onClose={handleClose}
|
||||
className='modal-open'
|
||||
bgClassName='sm:!bg-black/20'
|
||||
bgClassName={bookKey ? 'sm:!bg-black/20' : 'sm:!bg-black/50'}
|
||||
boxClassName={clsx('sm:min-w-[520px]', appService?.isMobile && 'sm:max-w-[90%] sm:w-3/4')}
|
||||
snapHeight={appService?.isMobile ? 0.7 : undefined}
|
||||
header={
|
||||
+9
-6
@@ -17,21 +17,24 @@ export const saveViewSettings = async <K extends keyof ViewSettings>(
|
||||
useSettingsStore.getState();
|
||||
const { getView, getViewSettings, setViewSettings } = useReaderStore.getState();
|
||||
const { getConfig, saveConfig } = useBookDataStore.getState();
|
||||
const viewSettings = getViewSettings(bookKey)!;
|
||||
const config = getConfig(bookKey)!;
|
||||
if (viewSettings[key] !== value) {
|
||||
const viewSettings = getViewSettings(bookKey);
|
||||
const config = getConfig(bookKey);
|
||||
if (bookKey && viewSettings && viewSettings[key] !== value) {
|
||||
viewSettings[key] = value;
|
||||
if (applyStyles) {
|
||||
const view = getView(bookKey);
|
||||
view?.renderer.setStyles?.(getStyles(viewSettings));
|
||||
}
|
||||
}
|
||||
setViewSettings(bookKey, viewSettings);
|
||||
|
||||
if (isFontLayoutSettingsGlobal && !skipGlobal) {
|
||||
settings.globalViewSettings[key] = value;
|
||||
setSettings(settings);
|
||||
await saveSettings(envConfig, settings);
|
||||
}
|
||||
|
||||
if (bookKey && config && viewSettings) {
|
||||
setViewSettings(bookKey, viewSettings);
|
||||
await saveConfig(envConfig, bookKey, config, settings);
|
||||
}
|
||||
await saveConfig(envConfig, bookKey, config, settings);
|
||||
await saveSettings(envConfig, settings);
|
||||
};
|
||||
@@ -222,6 +222,7 @@ export const useReaderStore = create<ReaderStore>((set, get) => ({
|
||||
},
|
||||
getViewSettings: (key: string) => get().viewStates[key]?.viewSettings || null,
|
||||
setViewSettings: (key: string, viewSettings: ViewSettings) => {
|
||||
if (!key) return;
|
||||
const id = key.split('-')[0]!;
|
||||
const bookData = useBookDataStore.getState().booksData[id];
|
||||
const viewState = get().viewStates[key];
|
||||
|
||||
Reference in New Issue
Block a user