diff --git a/NEWS.md b/NEWS.md index 55cb85634..e6794092f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -37,6 +37,10 @@ border-radius: 128px; - The Admin Tagging Status table shows what is being looked up right now. - Sorting by a tag column outside the table view (cover cards, OPDS feeds) no longer errors. + - Reading Bottom to Top jumped to the wrong page. The page list runs + backwards in that direction, so opening a comic, changing pages from the + toolbar or following a link landed on the mirrored page — page one showed + the last page. Top to Bottom was never affected. ## v2.2.11 diff --git a/frontend/src/components/reader/pager/pager-vertical.vue b/frontend/src/components/reader/pager/pager-vertical.vue index 153a83630..c4cf6523d 100644 --- a/frontend/src/components/reader/pager/pager-vertical.vue +++ b/frontend/src/components/reader/pager/pager-vertical.vue @@ -150,7 +150,13 @@ export default { this.programmaticScroll = true; const vs = this.$refs.verticalScroll; if (vs) { - vs.scrollToIndex(page); + /* + * ``items`` runs backwards for bottom-to-top reading, so a page + * number is not its own index there: page 0 is the last item. + * Look the page up in ``items`` rather than repeating the + * reversal, so this keeps following however that list is built. + */ + vs.scrollToIndex(this.items.indexOf(page)); } else { console.debug("Can't find verticalScroll component."); } diff --git a/frontend/tests/unit/pager-vertical.test.js b/frontend/tests/unit/pager-vertical.test.js new file mode 100644 index 000000000..5579208b4 --- /dev/null +++ b/frontend/tests/unit/pager-vertical.test.js @@ -0,0 +1,99 @@ +/* + * Tests for ``pager-vertical.vue`` page-to-index mapping. + * + * The vertical pager feeds ``v-virtual-scroll`` a list of page numbers, and + * reverses that list for bottom-to-top reading. ``scrollToIndex`` takes an + * index into that list, so a page number is only its own index while + * reading top-to-bottom. Passing the page number straight through sent + * bottom-to-top readers to the mirrored page — opening at page 0 landed on + * the last page. + */ +import { createTestingPinia } from "@pinia/testing"; +import { mount } from "@vue/test-utils"; +import { afterEach, describe, expect, test, vi } from "vitest"; + +import PagerVertical from "@/components/reader/pager/pager-vertical.vue"; +import vuetify from "@/plugins/vuetify"; + +const PK = 7; +const MAX_PAGE = 9; + +let wrappers = []; + +function mountPager(readingDirection) { + const scrollToIndex = vi.fn(); + const pinia = createTestingPinia({ + // getBookSettings has to really run to return the seeded settings. + stubActions: false, + initialState: { + reader: { + page: 0, + // Seeded settings are returned as-is by getBookSettings. + bookSettings: { + [PK]: { + readingDirection, + isVertical: true, + isReadInReverse: readingDirection === "btt", + }, + }, + }, + }, + }); + const wrapper = mount(PagerVertical, { + props: { book: { pk: PK, maxPage: MAX_PAGE } }, + global: { + plugins: [pinia, vuetify], + stubs: { + ScaleForScroll: { template: "