mirror of
https://github.com/bookorbit/bookorbit.git
synced 2026-11-03 00:11:37 -06:00
fix(reader): reopen a PDF at its saved page instead of the first
The PDF reader restored the saved page with a smooth scroll, which Chrome starts about a second after it is asked. With Fit page, Fit width or Automatic zoom, the first viewport resize refits the page from the current offset with an instant scroll, and a classic scrollbar appearing as the document loads is such a resize. The refit cancelled the restore before it moved, so the reader stayed on page 1 while the toolbar showed the saved page, and the next scroll saved page 1 or 2 over the position. Restore the opening page with an instant scroll, so the refit starts from the saved page and keeps it. Page turns still scroll smoothly. Fixes #1857
This commit is contained in:
@@ -10,7 +10,7 @@ const mocks = vi.hoisted(() => ({
|
||||
layoutReadyListener: null as ((event: LayoutReadyEvent) => void) | null,
|
||||
pageChangeListener: null as ((event: PageChangeEvent) => void) | null,
|
||||
totalPages: 10,
|
||||
scrollToPage: vi.fn<(options: { pageNumber: number }) => void>(),
|
||||
scrollToPage: vi.fn<(options: { pageNumber: number; behavior?: ScrollBehavior }) => void>(),
|
||||
}))
|
||||
|
||||
vi.mock('@embedpdf/plugin-scroll/vue', async () => {
|
||||
@@ -21,7 +21,7 @@ vi.mock('@embedpdf/plugin-scroll/vue', async () => {
|
||||
state: ref({ currentPage: 1, totalPages: mocks.totalPages }),
|
||||
provides: ref({
|
||||
// EmbedPDF reports the target page synchronously when a programmatic page change starts.
|
||||
scrollToPage: (options: { pageNumber: number }) => {
|
||||
scrollToPage: (options: { pageNumber: number; behavior?: ScrollBehavior }) => {
|
||||
mocks.scrollToPage(options)
|
||||
mocks.pageChangeListener?.({ documentId: 'document-1', pageNumber: options.pageNumber, totalPages: mocks.totalPages })
|
||||
},
|
||||
@@ -125,6 +125,15 @@ describe('PdfReaderContent', () => {
|
||||
expect(mocks.scrollToPage.mock.calls.length).toBeLessThanOrEqual(1)
|
||||
})
|
||||
|
||||
it('restores the opening page with an instant scroll', () => {
|
||||
mountContent(7)
|
||||
layoutReady()
|
||||
|
||||
// A smooth scroll that has not started is cancelled by the fit zoom's refit on the first
|
||||
// viewport resize, which leaves the reader on page 1.
|
||||
expect(mocks.scrollToPage).toHaveBeenCalledExactlyOnceWith({ pageNumber: 7, behavior: 'instant' })
|
||||
})
|
||||
|
||||
it('marks the opening page as restored and later turns as moves', () => {
|
||||
const wrapper = mountContent(null, 37.5)
|
||||
layoutReady()
|
||||
|
||||
@@ -343,7 +343,10 @@ watch(
|
||||
restoredInitialPage.value = true
|
||||
if (page > 1) {
|
||||
restoringPage = page
|
||||
scroll.value?.scrollToPage({ pageNumber: page })
|
||||
// Instant, because a fit zoom refits on the first viewport resize (a classic scrollbar
|
||||
// appearing) from the current offset, which cancels a smooth scroll that has not started
|
||||
// and strands the reader on page 1, so the next scroll saves page 1 over the position.
|
||||
scroll.value?.scrollToPage({ pageNumber: page, behavior: 'instant' })
|
||||
}
|
||||
})
|
||||
const unsubscribePage = capability.onPageChange((event) => {
|
||||
|
||||
Reference in New Issue
Block a user