diff --git a/CHANGELOG.md b/CHANGELOG.md index ae61822a..da9058f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). - (**Library**) Fix total library size chip color in light mode - (**Browse**) Fix missing pinned sources in the source language filter - (**Browse**) Fix incorrectly showing "local source" source in the source language filter (the local source can't be disabled) +- (**Reader**) Fix page shift when toggling the "offset double spreads" setting (currently: enable: shift to the right; disable: shift to the left – now: inverted) ## [20251230.01] (r2937) - 2025-12-30 diff --git a/src/features/reader/Reader.types.ts b/src/features/reader/Reader.types.ts index 8e579f05..648ce079 100644 --- a/src/features/reader/Reader.types.ts +++ b/src/features/reader/Reader.types.ts @@ -306,7 +306,11 @@ export interface ReaderStatePages { setPageToScrollToIndex: (total: number | null) => void; pageUrls: string[]; setPageUrls: (urls: string[]) => void; - pageLoadStates: { url: string; loaded: boolean; error?: boolean }[]; + pageSpreadStates: ReaderPageSpreadState[]; + setPageSpreadStates: ( + set: ((prevStates: ReaderPageSpreadState[]) => ReaderPageSpreadState[]) | ReaderPageSpreadState[], + ) => void; + pageLoadStates: ReaderPageLoadState[]; setPageLoadStates: ( set: ((prevStates: ReaderPageLoadState[]) => ReaderPageLoadState[]) | ReaderPageLoadState[], ) => void; diff --git a/src/features/reader/hotkeys/ReaderHotkeys.tsx b/src/features/reader/hotkeys/ReaderHotkeys.tsx index c1d96b9b..98027365 100644 --- a/src/features/reader/hotkeys/ReaderHotkeys.tsx +++ b/src/features/reader/hotkeys/ReaderHotkeys.tsx @@ -149,10 +149,7 @@ export const ReaderHotkeys = ({ ReaderService.updateSetting('shouldStretchPage', !getReaderSettingsStore().shouldStretchPage.value), ); useHotkeys(hotkeys[ReaderHotkey.OFFSET_SPREAD_PAGES], () => - ReaderService.updateSetting( - 'shouldOffsetDoubleSpreads', - !getReaderSettingsStore().shouldOffsetDoubleSpreads.value, - ), + ReaderService.setOffsetDoubleSpreads(!getReaderSettingsStore().shouldOffsetDoubleSpreads.value), ); useHotkeys(hotkeys[ReaderHotkey.CYCLE_READING_MODE], () => { updateSettingCycleThrough( diff --git a/src/features/reader/overlay/navigation/desktop/quick-settings/ReaderNavBarDesktopQuickSettings.tsx b/src/features/reader/overlay/navigation/desktop/quick-settings/ReaderNavBarDesktopQuickSettings.tsx index 32786e7e..65b24551 100644 --- a/src/features/reader/overlay/navigation/desktop/quick-settings/ReaderNavBarDesktopQuickSettings.tsx +++ b/src/features/reader/overlay/navigation/desktop/quick-settings/ReaderNavBarDesktopQuickSettings.tsx @@ -43,9 +43,7 @@ const BaseReaderNavBarDesktopQuickSettings = ({ openSettings }: Pick - ReaderService.updateSetting('shouldOffsetDoubleSpreads', value) - } + setShouldOffsetDoubleSpreads={(value) => ReaderService.setOffsetDoubleSpreads(value)} /> = { ltr: 'rtl', @@ -237,6 +239,41 @@ export class ReaderService { : DIRECTION_TO_INVERTED[direction]; } + /** + * Updates the setting and updated the current page index accordingly. + * + * In case the current page is a spread page, the page index won't get changed. + * + * Enable: + * Push pages to the left + * + * Page 3+2 -> Page 2+1 - the third page gets pushed to the left, out of the screen + * + * Disable: + * Push pages to the right + * + * Page 3+2 -> Page 4+3 - the second page gets pushed to the right, out of the screen + */ + static setOffsetDoubleSpreads(shouldOffset: boolean): void { + const { pages, currentPageIndex, pageSpreadStates } = getReaderPagesStore(); + const { readingMode } = getReaderSettingsStore(); + + const isDoublePageMode = readingMode.value === ReadingMode.DOUBLE_PAGE; + const isSpreadPage = !!pageSpreadStates[currentPageIndex]?.isSpread; + + const updatePageIndex = isDoublePageMode && !isSpreadPage; + if (!updatePageIndex) { + ReaderService.updateSetting('shouldOffsetDoubleSpreads', shouldOffset); + return; + } + + const page = getPage(currentPageIndex, pages); + const updatedPageIndex = shouldOffset ? page.primary.index : currentPageIndex; + + getReaderPagesStore().setCurrentPageIndex(updatedPageIndex); + ReaderService.updateSetting('shouldOffsetDoubleSpreads', shouldOffset); + } + /** * Writes the change immediately to the cache and sends a mutation in case "commit" is true. */ diff --git a/src/features/reader/stores/ReaderPagesStore.ts b/src/features/reader/stores/ReaderPagesStore.ts index 6acc4290..a8ab0269 100644 --- a/src/features/reader/stores/ReaderPagesStore.ts +++ b/src/features/reader/stores/ReaderPagesStore.ts @@ -22,6 +22,7 @@ export const READER_DEFAULT_PAGES_STATE: Omit< | 'setPageToScrollToIndex' | 'setTotalPages' | 'setPageUrls' + | 'setPageSpreadStates' | 'setPageLoadStates' | 'setPages' | 'setTransitionPageMode' @@ -32,6 +33,7 @@ export const READER_DEFAULT_PAGES_STATE: Omit< currentPageIndex: 0, pageToScrollToIndex: null, pageUrls: [], + pageSpreadStates: [{ url: '', isSpread: false }], pageLoadStates: [{ url: '', loaded: false }], pages: [ { @@ -85,6 +87,19 @@ export const createReaderPagesStoreSlice = ( undefined, createActionName('setPageUrls'), ), + setPageSpreadStates: (spreadStates) => + set( + (draft) => { + if (typeof spreadStates === 'function') { + draft.pages.pageSpreadStates = spreadStates(get().pages.pageSpreadStates); + return; + } + + draft.pages.pageSpreadStates = spreadStates; + }, + undefined, + createActionName('setPageSpreadStates'), + ), setPageLoadStates: (loadStates) => set( (draft) => { diff --git a/src/features/reader/viewer/ReaderChapterViewer.tsx b/src/features/reader/viewer/ReaderChapterViewer.tsx index a4bd3c74..b23e4ba3 100644 --- a/src/features/reader/viewer/ReaderChapterViewer.tsx +++ b/src/features/reader/viewer/ReaderChapterViewer.tsx @@ -50,6 +50,7 @@ const BaseReaderChapterViewer = ({ currentPageIndex, setPages: setContextPages, setPageUrls: setContextPageUrls, + setPageSpreadStates: setContextPageSpreadStates, setPageLoadStates: setContextPageLoadStates, setTotalPages: setContextTotalPages, setCurrentPageIndex: setContextCurrentPageIndex, @@ -93,6 +94,7 @@ const BaseReaderChapterViewer = ({ | 'currentPageIndex' | 'setPages' | 'setPageUrls' + | 'setPageSpreadStates' | 'setPageLoadStates' | 'setTotalPages' | 'setCurrentPageIndex' @@ -140,7 +142,7 @@ const BaseReaderChapterViewer = ({ READER_DEFAULT_PAGES_STATE.pageLoadStates, ); const [pagesToSpreadState, setPagesToSpreadState] = useState( - pageLoadStates.map(({ url }) => ({ url, isSpread: false })), + READER_DEFAULT_PAGES_STATE.pageSpreadStates, ); const ref = useRef(null); @@ -201,7 +203,13 @@ const BaseReaderChapterViewer = ({ () => createUpdateReaderPageLoadState( actualPages, - setPagesToSpreadState, + (value) => { + if (isCurrentChapterRef.current) { + setContextPageSpreadStates(value); + } + + setPagesToSpreadState(value); + }, (value) => { if (isCurrentChapterRef.current) { setContextPageLoadStates(value); @@ -270,7 +278,7 @@ const BaseReaderChapterViewer = ({ (value) => updateState(value, setPages, setContextPages), (value) => updateState(value, setPageUrls, setContextPageUrls), (value) => updateState(value, setPageLoadStates, setContextPageLoadStates), - (value) => updateState(value, setPagesToSpreadState, noOp), + (value) => updateState(value, setPagesToSpreadState, setContextPageSpreadStates), (value) => updateState(value, noOp, setContextCurrentPageIndex), (value) => { if ((isInitialChapter && !arePagesFetched) || scrollIntoView) { diff --git a/src/features/reader/viewer/ReaderViewer.tsx b/src/features/reader/viewer/ReaderViewer.tsx index b6524b3b..d43a87ca 100644 --- a/src/features/reader/viewer/ReaderViewer.tsx +++ b/src/features/reader/viewer/ReaderViewer.tsx @@ -82,6 +82,7 @@ const BaseReaderViewer = ({ totalPages, setPages, setPageUrls, + setPageSpreadStates, setPageLoadStates, setTotalPages, setCurrentPageIndex, @@ -96,6 +97,7 @@ const BaseReaderViewer = ({ totalPages: state.pages.totalPages, setPages: state.pages.setPages, setPageUrls: state.pages.setPageUrls, + setPageSpreadStates: state.pages.setPageSpreadStates, setPageLoadStates: state.pages.setPageLoadStates, setTotalPages: state.pages.setTotalPages, setCurrentPageIndex: state.pages.setCurrentPageIndex, @@ -381,6 +383,7 @@ const BaseReaderViewer = ({ imageRefs={imageRefs} setPages={setPages} setPageUrls={setPageUrls} + setPageSpreadStates={setPageSpreadStates} setPageLoadStates={setPageLoadStates} setTotalPages={setTotalPages} setCurrentPageIndex={setCurrentPageIndex}