From 37218bce593be9d6548ee8fbb66b8fea1a560231 Mon Sep 17 00:00:00 2001 From: Alf Eaton Date: Wed, 27 Apr 2022 11:32:11 +0100 Subject: [PATCH] Attach PDF highlights to the viewer element (#7728) GitOrigin-RevId: 918dfd8c43dfea4e64fbb5a1437ea8532cbac7ec --- .../pdf-preview/components/pdf-js-viewer.js | 47 ++++++++++++++++--- .../features/pdf-preview/util/highlights.js | 15 ++---- 2 files changed, 45 insertions(+), 17 deletions(-) diff --git a/services/web/frontend/js/features/pdf-preview/components/pdf-js-viewer.js b/services/web/frontend/js/features/pdf-preview/components/pdf-js-viewer.js index e54fa96570..56e1838a50 100644 --- a/services/web/frontend/js/features/pdf-preview/components/pdf-js-viewer.js +++ b/services/web/frontend/js/features/pdf-preview/components/pdf-js-viewer.js @@ -178,29 +178,64 @@ function PdfJsViewer({ url }) { // when highlights are created, build the highlight elements useEffect(() => { + const timers = [] + let intersectionObserver + if (pdfJsWrapper && highlights?.length) { + // watch for the highlight elements to scroll into view + intersectionObserver = new IntersectionObserver( + entries => { + for (const entry of entries) { + if (entry.isIntersecting) { + intersectionObserver.unobserve(entry.target) + + // fade the element in and out + entry.target.style.opacity = '0.5' + + timers.push( + window.setTimeout(() => { + entry.target.style.opacity = '0' + }, 1000) + ) + } + } + }, + { + threshold: 1.0, // the whole element must be visible + } + ) + const elements = [] for (const highlight of highlights) { try { const element = buildHighlightElement(highlight, pdfJsWrapper) elements.push(element) + intersectionObserver.observe(element) } catch (error) { // ignore invalid highlights } } - // scroll to the first highlighted element - elements[0]?.scrollIntoView({ - block: 'nearest', - inline: 'start', - behavior: 'smooth', - }) + const [firstElement] = elements + + if (firstElement) { + // scroll to the first highlighted element + firstElement.scrollIntoView({ + block: 'center', + inline: 'start', + behavior: 'smooth', + }) + } return () => { + for (const timer of timers) { + window.clearTimeout(timer) + } for (const element of elements) { element.remove() } + intersectionObserver?.disconnect() } } }, [highlights, pdfJsWrapper]) diff --git a/services/web/frontend/js/features/pdf-preview/util/highlights.js b/services/web/frontend/js/features/pdf-preview/util/highlights.js index e5203b8f84..3c0db30b3a 100644 --- a/services/web/frontend/js/features/pdf-preview/util/highlights.js +++ b/services/web/frontend/js/features/pdf-preview/util/highlights.js @@ -15,8 +15,8 @@ export function buildHighlightElement(highlight, wrapper) { const [left, top, right, bottom] = wrapper.PDFJS.Util.normalizeRect(rect) const element = document.createElement('div') - element.style.left = Math.floor(left) + 'px' - element.style.top = Math.floor(top) + 'px' + element.style.left = Math.floor(pageView.div.offsetLeft + left) + 'px' + element.style.top = Math.floor(pageView.div.offsetTop + top + 10) + 'px' element.style.width = Math.ceil(right - left) + 'px' element.style.height = Math.ceil(bottom - top) + 'px' element.style.backgroundColor = 'rgba(255,255,0)' @@ -25,16 +25,9 @@ export function buildHighlightElement(highlight, wrapper) { element.style.scrollMargin = '72px' element.style.pointerEvents = 'none' element.style.opacity = '0' - element.style.transition = 'opacity 0.5s' - pageView.div.appendChild(element) + element.style.transition = 'opacity 1s' - window.setTimeout(() => { - element.style.opacity = '0.3' - - window.setTimeout(() => { - element.style.opacity = '0' - }, 1000) - }, 0) + wrapper.viewer.viewer.append(element) return element }