Newer
Older
import { getTrimValue, setTrimValue } from './trimming.js'
import { viewerState, viewerStatePromise } from './state.js'
import { type PDFViewerApplicationType, type PDFViewerApplicationOptionsType, RenderingStates } from './interface.js'
import type { PdfViewerParams } from '../../types/latex-workshop-protocol-types/index.js'
declare const pdfjsLib: any
declare const PDFViewerApplication: PDFViewerApplicationType
declare const PDFViewerApplicationOptions: PDFViewerApplicationOptionsType
let autoRefreshEnabled = true
export function IsAutoRefreshEnabled() {
return autoRefreshEnabled
export function toggleAutoRefresh() {
autoRefreshEnabled = !autoRefreshEnabled
return autoRefreshEnabled
page: number,
trim: number,
scale: string,
scrollMode: number,
sidebarView: number,
spreadMode: number,
scrollTop: number,
scrollLeft: number
} | undefined
// https://github.com/James-Yu/LaTeX-Workshop/pull/4295#issuecomment-2191226562
clearTimeout(doneRefreshTimeout)
if (shouldRefreshAgain) {
shouldRefreshAgain = false
void refresh()
}
let shouldRefreshAgain = false
let doneRefreshTimeout = 0
sendLog('Auto reload temporarily disabled.')
return
}
shouldRefreshAgain = true
sendLog('Auto reload rate-limiting.')
return
}
// https://github.com/James-Yu/LaTeX-Workshop/pull/4295#issuecomment-2191384019
clearTimeout(doneRefreshTimeout)
doneRefreshTimeout = setTimeout(() => doneRefresh(), 1000)
// Fail-safe. For unknown reasons, the pack may have null values #4076
const currentState = {
page: PDFViewerApplication.pdfViewer.currentPageNumber ?? prevState?.page,
trim: getTrimValue(),
scale: PDFViewerApplication.pdfViewer.currentScaleValue ?? prevState?.scale,
scrollMode: PDFViewerApplication.pdfViewer.scrollMode ?? prevState?.scrollMode,
sidebarView: PDFViewerApplication.pdfSidebar.visibleView ?? prevState?.sidebarView,
spreadMode: PDFViewerApplication.pdfViewer.spreadMode ?? prevState?.spreadMode,
scrollTop: document.getElementById('viewerContainer')!.scrollTop ?? prevState?.scrollTop,
scrollLeft: document.getElementById('viewerContainer')!.scrollLeft ?? prevState?.scrollLeft
}
prevState = currentState
// Note: without showPreviousViewOnLoad = false restoring the position after the refresh will fail if
// the user has clicked on any link in the past (pdf.js will automatically navigate to that link).
PDFViewerApplicationOptions.set('showPreviousViewOnLoad', false)
// Override the spread mode specified in PDF documents with the current one.
// https://github.com/James-Yu/LaTeX-Workshop/issues/1871
if (typeof prevState.spreadMode === 'number') {
PDFViewerApplicationOptions.set('spreadModeOnLoad', prevState.spreadMode)
}
const masks = addMasks()
const cb = () => {
if (!allPagesRendered()) {
return
}
removeMasks(masks)
PDFViewerApplication.eventBus.off('pagerendered', cb)
}
PDFViewerApplication.eventBus.on('pagerendered', cb)
const { encodedPath, docTitle } = utils.parseURL()
/* eslint-disable */
const doc = await pdfjsLib.getDocument({
cMapUrl: '../cmaps/'
}).promise
PDFViewerApplication.load(doc)
/* eslint-enable */
// reset the document title to the original value to avoid duplication
document.title = docTitle
}
export async function restoreState() {
if (prevState === undefined) {
await restoreDefault()
return
}
if (prevState.page !== undefined) {
PDFViewerApplication.pdfViewer.currentPageNumber = prevState.page
}
if (prevState.trim !== undefined) {
setTrimValue(prevState.trim)
}
if (prevState.scale !== undefined) {
PDFViewerApplication.pdfViewer.currentScaleValue = prevState.scale
}
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
if (prevState.sidebarView) {
PDFViewerApplication.pdfSidebar.switchView(prevState.sidebarView)
}
if (typeof prevState.scrollMode === 'number' && PDFViewerApplication.pdfViewer.scrollMode !== prevState.scrollMode) {
PDFViewerApplication.pdfViewer.scrollMode = prevState.scrollMode
}
if (typeof prevState.spreadMode === 'number' && PDFViewerApplication.pdfViewer.spreadMode !== prevState.spreadMode) {
PDFViewerApplication.pdfViewer.spreadMode = prevState.spreadMode
}
const viewerContainer = document.getElementById('viewerContainer')!
if (typeof prevState.scrollTop === 'number' && viewerContainer.scrollTop !== prevState.scrollTop) {
viewerContainer.scrollTop = prevState.scrollTop
}
if (typeof prevState.scrollLeft === 'number' && viewerContainer.scrollLeft !== prevState.scrollLeft) {
viewerContainer.scrollLeft = prevState.scrollLeft
}
}
async function restoreDefault() {
const params = await (await fetch('config.json')).json() as PdfViewerParams
if (params.trim !== undefined) {
setTrimValue(params.trim)
}
// By setting the scale, scaling will be invoked if necessary.
// The scale can be a non-number one.
if (params.scale !== undefined) {
PDFViewerApplication.pdfViewer.currentScaleValue = params.scale
}
if (params.scrollMode !== undefined) {
PDFViewerApplication.pdfViewer.scrollMode = params.scrollMode
}
if (params.spreadMode !== undefined) {
PDFViewerApplication.pdfViewer.spreadMode = params.spreadMode
}
if (!utils.isEmbedded()) {
return
}
await viewerStatePromise
const viewerContainer = document.getElementById('viewerContainer')!
if (typeof viewerState.scrollTop === 'number' && viewerContainer.scrollTop !== viewerState.scrollTop) {
viewerContainer.scrollTop = viewerState.scrollTop
}
if (typeof viewerState.scrollLeft === 'number' && viewerContainer.scrollLeft !== viewerState.scrollLeft) {
viewerContainer.scrollLeft = viewerState.scrollLeft
}
function addMasks() {
const viewerDom = document.getElementById('viewer')!
const viewerContainer = document.getElementById('viewerContainer')!
const masks: HTMLDivElement[] = []
if (!viewerContainer || !viewerDom) {
return masks
}
const visiblePages = PDFViewerApplication.pdfViewer._getVisiblePages()
for (const visiblePage of visiblePages.views) {
const canvas = visiblePage.view.canvas
if (!canvas) {
continue
}
const viewerBound = viewerDom.getBoundingClientRect()
const pageBound = visiblePage.view.div.getBoundingClientRect()
const canvasBound = canvas.getBoundingClientRect()
const div = document.createElement('div')
div.className = 'page-loading-mask'
masks.push(div)
div.style.display = 'none'
div.style.left = pageBound.x - viewerBound.x + 'px'
div.style.top = pageBound.y - viewerBound.y + 'px'
div.style.width = pageBound.width + 'px'
div.style.height = pageBound.height + 'px'
const img = new Image()
img.src = canvas.toDataURL() ?? ''
img.style.left = canvasBound.x - pageBound.x + 'px'
img.style.top = canvasBound.y - pageBound.y + 'px'
img.style.width = canvasBound.width + 'px'
img.style.height = canvasBound.height + 'px'
div.appendChild(img)
viewerContainer.appendChild(div)
div.style.display = 'inherit'
// This workaround is for the last page of the document.
const anchor = document.createElement('div')
anchor.className = 'page-loading-anchor'
masks.push(anchor)
anchor.style.display = 'inherit'
anchor.style.position = 'absolute'
anchor.style.left = pageBound.x - viewerBound.x + 'px'
anchor.style.top = pageBound.y - viewerBound.y + pageBound.height + 'px'
anchor.style.width = '10px'
anchor.style.height = '10px'
viewerContainer.appendChild(anchor)
}
return masks
}
function allPagesRendered() {
return PDFViewerApplication.pdfViewer._getVisiblePages().views.every(view => view.view.renderingState === RenderingStates.FINISHED)
}
function removeMasks(masks: HTMLDivElement[]) {
for (const mask of masks) {
mask.classList.add('remove')
}
setTimeout(() => {
for (const mask of masks) {
mask.remove()
}
}, 1000)