fix: fixed crash when switching allow script (#2351)

This commit is contained in:
Huang Xin
2025-10-29 10:17:17 +08:00
committed by GitHub
parent 78e61060d2
commit 123293dc0e
7 changed files with 55 additions and 25 deletions
@@ -85,12 +85,14 @@ const BooksGrid: React.FC<BooksGridProps> = ({ bookKeys, onCloseBook }) => {
const config = getConfig(bookKey);
const progress = getProgress(bookKey);
const viewSettings = getViewSettings(bookKey);
const viewState = getViewState(bookKey);
const gridInsets = calcGridInsets(index, bookKeys.length);
const { book, bookDoc } = bookData || {};
if (!book || !config || !bookDoc || !viewSettings) return null;
if (!book || !config || !bookDoc || !viewSettings || !viewState) return null;
const { section, pageinfo, timeinfo, sectionLabel } = progress || {};
const isBookmarked = getViewState(bookKey)?.ribbonVisible;
const isBookmarked = viewState.ribbonVisible;
const viewerKey = viewState.viewerKey;
const horizontalGapPercent = viewSettings.gapPercent;
const viewInsets = getViewInsets(viewSettings);
const contentInsets = {
@@ -123,6 +125,7 @@ const BooksGrid: React.FC<BooksGridProps> = ({ bookKeys, onCloseBook }) => {
gridInsets={gridInsets}
/>
<FoliateViewer
key={viewerKey}
bookKey={bookKey}
bookDoc={bookDoc}
config={config}
@@ -271,7 +271,6 @@ const FoliateViewer: React.FC<{
await import('foliate-js/view.js');
const view = wrappedFoliateView(document.createElement('foliate-view') as FoliateView);
view.id = `foliate-view-${bookKey}`;
document.body.append(view);
containerRef.current?.appendChild(view);
const viewSettings = getViewSettings(bookKey)!;
@@ -8,16 +8,16 @@ 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';
import { saveSysSettings, saveViewSettings } from '@/helpers/settings';
import { SettingsPanelPanelProp } from './SettingsDialog';
import { RELOAD_BEFORE_SAVED_TIMEOUT_MS } from '@/services/constants';
import NumberInput from './NumberInput';
const ControlPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterReset }) => {
const _ = useTranslation();
const { envConfig, appService } = useEnv();
const { getView, getViewSettings } = useReaderStore();
const { getView, getViewSettings, recreateViewer } = useReaderStore();
const { getBookData } = useBookDataStore();
const { settings } = useSettingsStore();
const { applyEinkMode } = useEinkMode();
@@ -144,7 +144,9 @@ const ControlPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterRes
useEffect(() => {
if (viewSettings.allowScript === allowScript) return;
saveViewSettings(envConfig, bookKey, 'allowScript', allowScript, true, false);
saveAndReload();
setTimeout(() => {
recreateViewer(envConfig, bookKey);
}, RELOAD_BEFORE_SAVED_TIMEOUT_MS);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [allowScript]);
@@ -8,9 +8,12 @@ import { useSettingsStore } from '@/store/settingsStore';
import { saveViewSettings } from '@/helpers/settings';
import { getTranslators } from '@/services/translators';
import { useResetViewSettings } from '@/hooks/useResetSettings';
import { TRANSLATED_LANGS, TRANSLATOR_LANGS } from '@/services/constants';
import {
RELOAD_BEFORE_SAVED_TIMEOUT_MS,
TRANSLATED_LANGS,
TRANSLATOR_LANGS,
} from '@/services/constants';
import { SettingsPanelPanelProp } from './SettingsDialog';
import { saveAndReload } from '@/utils/reload';
import Select from '@/components/Select';
const LangPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterReset }) => {
@@ -18,7 +21,7 @@ const LangPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterReset
const { token } = useAuth();
const { envConfig } = useEnv();
const { settings, applyUILanguage } = useSettingsStore();
const { getViewSettings, setViewSettings } = useReaderStore();
const { getViewSettings, setViewSettings, recreateViewer } = useReaderStore();
const viewSettings = getViewSettings(bookKey) || settings.globalViewSettings;
const [uiLanguage, setUILanguage] = useState(viewSettings.uiLanguage);
@@ -141,10 +144,8 @@ const LangPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterReset
useEffect(() => {
if (translationEnabled === viewSettings.translationEnabled) return;
saveViewSettings(envConfig, bookKey, 'translationEnabled', translationEnabled, true, false);
viewSettings.translationEnabled = translationEnabled;
setViewSettings(bookKey, { ...viewSettings });
if (!showTranslateSource && !translationEnabled) {
saveAndReload();
if (!showTranslateSource && translationEnabled) {
setTimeout(() => recreateViewer(envConfig, bookKey), RELOAD_BEFORE_SAVED_TIMEOUT_MS);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [translationEnabled]);
@@ -152,7 +153,7 @@ const LangPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterReset
useEffect(() => {
if (showTranslateSource === viewSettings.showTranslateSource) return;
saveViewSettings(envConfig, bookKey, 'showTranslateSource', showTranslateSource, false, false);
saveAndReload();
setTimeout(() => recreateViewer(envConfig, bookKey), RELOAD_BEFORE_SAVED_TIMEOUT_MS);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [showTranslateSource]);
@@ -12,12 +12,11 @@ import { useTranslation } from '@/hooks/useTranslation';
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 '@/helpers/settings';
import { getBookDirFromWritingMode, getBookLangCode } from '@/utils/book';
import { MIGHT_BE_RTL_LANGS } from '@/services/constants';
import { MIGHT_BE_RTL_LANGS, RELOAD_BEFORE_SAVED_TIMEOUT_MS } from '@/services/constants';
import { SettingsPanelPanelProp } from './SettingsDialog';
import Select from '@/components/Select';
import NumberInput from './NumberInput';
@@ -26,7 +25,8 @@ const LayoutPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterRese
const _ = useTranslation();
const { envConfig, appService } = useEnv();
const { settings } = useSettingsStore();
const { getView, getViewSettings, getGridInsets, setViewSettings } = useReaderStore();
const { getView, getViewSettings, getGridInsets } = useReaderStore();
const { setViewSettings, recreateViewer } = useReaderStore();
const { getBookData } = useBookDataStore();
const viewSettings = getViewSettings(bookKey) || settings.globalViewSettings;
@@ -283,7 +283,7 @@ const LayoutPanel: React.FC<SettingsPanelPanelProp> = ({ bookKey, onRegisterRese
(['horizontal-rl', 'vertical-rl'].includes(writingMode) ||
['horizontal-rl', 'vertical-rl'].includes(prevWritingMode))
) {
saveAndReload();
setTimeout(() => recreateViewer(envConfig, bookKey), RELOAD_BEFORE_SAVED_TIMEOUT_MS);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [writingMode]);
+32 -2
View File
@@ -20,11 +20,13 @@ import { SUPPORTED_LANGNAMES } from '@/services/constants';
import { useSettingsStore } from './settingsStore';
import { useBookDataStore } from './bookDataStore';
import { useLibraryStore } from './libraryStore';
import { uniqueId } from '@/utils/misc';
interface ViewState {
/* Unique key for each book view */
key: string;
view: FoliateView | null;
viewerKey: string;
isPrimary: boolean;
loading: boolean;
inited: boolean;
@@ -72,12 +74,14 @@ interface ReaderStore {
id: string,
key: string,
isPrimary?: boolean,
reload?: boolean,
) => Promise<void>;
clearViewState: (key: string) => void;
getViewState: (key: string) => ViewState | null;
getGridInsets: (key: string) => Insets | null;
setGridInsets: (key: string, insets: Insets | null) => void;
setViewInited: (key: string, inited: boolean) => void;
recreateViewer: (envConfig: EnvConfigType, key: string) => void;
}
export const useReaderStore = create<ReaderStore>((set, get) => ({
@@ -110,7 +114,13 @@ export const useReaderStore = create<ReaderStore>((set, get) => ({
});
},
getViewState: (key: string) => get().viewStates[key] || null,
initViewState: async (envConfig: EnvConfigType, id: string, key: string, isPrimary = true) => {
initViewState: async (
envConfig: EnvConfigType,
id: string,
key: string,
isPrimary = true,
reload = false,
) => {
const booksData = useBookDataStore.getState().booksData;
const bookData = booksData[id];
set((state) => ({
@@ -119,6 +129,7 @@ export const useReaderStore = create<ReaderStore>((set, get) => ({
[key]: {
key: '',
view: null,
viewerKey: '',
isPrimary: false,
loading: true,
inited: false,
@@ -134,7 +145,7 @@ export const useReaderStore = create<ReaderStore>((set, get) => ({
}));
try {
const { settings } = useSettingsStore.getState();
if (!bookData) {
if (!bookData || reload) {
const appService = await envConfig.getAppService();
const { library } = useLibraryStore.getState();
const book = library.find((b) => b.hash === id);
@@ -183,6 +194,7 @@ export const useReaderStore = create<ReaderStore>((set, get) => ({
...state.viewStates[key],
key,
view: null,
viewerKey: `${key}-${uniqueId()}`,
isPrimary,
loading: false,
inited: false,
@@ -205,6 +217,7 @@ export const useReaderStore = create<ReaderStore>((set, get) => ({
...state.viewStates[key],
key: '',
view: null,
viewerKey: '',
isPrimary: false,
loading: false,
inited: false,
@@ -378,4 +391,21 @@ export const useReaderStore = create<ReaderStore>((set, get) => ({
},
},
})),
recreateViewer: (envConfig: EnvConfigType, key: string) => {
const id = key.split('-')[0]!;
get()
.initViewState(envConfig, id, key, true, true)
.then(() => {
set((state) => ({
viewStates: {
...state.viewStates,
[key]: {
...state.viewStates[key]!,
viewerKey: `${key}-${uniqueId()}`,
},
},
}));
});
},
}));
-5
View File
@@ -1,5 +0,0 @@
import { RELOAD_BEFORE_SAVED_TIMEOUT_MS } from '@/services/constants';
export const saveAndReload = async () => {
setTimeout(() => window.location.reload(), RELOAD_BEFORE_SAVED_TIMEOUT_MS);
};