Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix pdf flickering on page change with iframe #363

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ VITE_IPFS_UPLOAD_PROXY='https://ipfsproxy.teia.rocks'
VITE_IPFS_DEFAULT_GATEWAY='CDN'

VITE_TEZOS_RPC='https://mainnet.teia.rocks'
VITE_IFRAME_URL='https://iframe.teia.art'
466 changes: 325 additions & 141 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@
"prettier": "^2.8.4",
"process": "^0.11.10",
"prop-types": "^15.8.1",
"react-pdf": "^6.2.2",
"react-pdf": "^7.5.1",
"rollup-plugin-node-polyfills": "^0.2.1",
"rollup-plugin-polyfill-node": "^0.12.0",
"sass": "^1.58.1",
Expand Down
5 changes: 4 additions & 1 deletion src/components/media-types/html/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,10 @@ export const HTMLComponent = (props) => {
<iframe
ref={iframeRef}
title={`interactive object ${nft.token_id}`}
src={`https://iframe.teia.art/html/?uid=${uid}&creator=${_creator_}&viewer=${_viewer_}&objkt=${_objectId_}`}
src={
import.meta.env.VITE_IFRAME_URL +
`/html/?uid=${uid}&creator=${_creator_}&viewer=${_viewer_}&objkt=${_objectId_}`
}
sandbox={sandbox_features}
allow={allowed_features}
/>
Expand Down
17 changes: 17 additions & 0 deletions src/components/media-types/pdf/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.tag-view .vector {
position: absolute;
top: 50%;
left: 50%;
width: 100%;
height: 100%;
transform: translateX(-50%) translateY(-50%);
border: none;
min-height: 0;
min-width: 0;
}

.objktview .vector-container {
pointer-events: all;
width: 50%;
}

57 changes: 30 additions & 27 deletions src/components/media-types/pdf/index.module.scss
Original file line number Diff line number Diff line change
@@ -1,39 +1,42 @@
@import '@styles/layout.scss';
@import '@styles/variables.scss';
@import '@styles/mixins.scss';

.vector {
@include embedObjktViewSizes;
}

.display {
width: 100%;
display: block;
margin: 0 auto;
border: none;
pointer-events: none;
}

.container {
position: relative;
display: block;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-grow: 1;
min-height: 60vh;
max-height: $max-token-height;
// overflow: hidden;
pointer-events: none;
overflow: hidden;

.pdfNav {
position: relative;
margin: 6px;
text-align: center;
font-size: 0.8em;
display: flex;
align-items: center;
justify-content: center;
p {
margin: 6px 12px;
}
&:after {
content: '';
display: block;
padding-bottom: 100%;
}
}

.previous_page {
position: absolute !important;
z-index: 50;
top: 0;
left: 0;
// border: 10px solid pink;
opacity: 1;
}
&.interactive {
pointer-events: all;
}

.page {
height: 100%;
iframe {
position: absolute;
width: 100%;
height: 100%;
border: none;
}
}
167 changes: 14 additions & 153 deletions src/components/media-types/pdf/index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,8 @@
import { memo, useMemo, useRef, useState } from 'react'
import styles from '@style'
import { Document, Page } from 'react-pdf/dist/esm/entry.vite'
import 'react-pdf/dist/esm/Page/TextLayer.css'
import 'react-pdf/dist/esm/Page/AnnotationLayer.css'

import { ImageComponent } from '../image'
import { Button } from '@atoms/button'
import { memo, } from 'react'
import { MediaTypeProps } from '@types'
// pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`
// pdfjs.GlobalWorkerOptions.workerSrc = 'pdf.worker.min.js'
const options = {
cMapUrl: 'cmaps/',
cMapPacked: true,
standardFontDataUrl: 'standard_fonts/',
}
import { ImageComponent } from '../image'
import classnames from 'classnames'
import styles from '@style'

export const PdfComponent = memo(function ({
artifactUri,
Expand All @@ -22,80 +11,13 @@ export const PdfComponent = memo(function ({
displayView,
nft,
}: MediaTypeProps) {
const [numPages, setNumPages] = useState<number>()
const [pageNumber, setPageNumber] = useState(1)
const [renderedPageNumber, setRenderedPageNumber] = useState<number>()
const [loading, setLoading] = useState(displayView)
const [showDocument, setShowDocument] = useState(true)

const [height, setHeight] = useState<number>()

// const [loading, setLoading] = useState(displayView)

const container = useRef<HTMLDivElement>(null)

const file = useMemo(
() => (previewUri ? previewUri : artifactUri),
[previewUri, artifactUri]
)

function onDocumentLoadSuccess({ numPages }: { numPages: number }) {
setNumPages(numPages)
}
const classes = classnames({
[styles.container]: true,
[styles.interactive]: displayView,
[styles.display]: displayView,
})

function onDocumentLoadError(e: Error) {
console.error(`PDF Error: ${e.message}`)
}

function changePage(offset: number) {
setPageNumber((prevPageNumber) => prevPageNumber + offset)
}

function previousPage() {
changePage(-1)
}

function nextPage() {
changePage(1)
}

// function onItemClick(item) {
// setPageNumber(item.pageNumber)
// }

const onRender = () => {
if (loading) {
setLoading(false)
setHeight(container.current?.clientHeight)
}
setRenderedPageNumber(pageNumber)
}

function onPassword(callback, reason) {
function callbackProxy(password) {
// Cancel button handler
if (password === null) {
// password will be null if user clicks on cancel
setShowDocument(false)
return
}
callback(password)
}

switch (reason) {
case 1: {
const password = prompt('Enter the password to open this PDF file.')
callbackProxy(password)
break
}
case 2: {
const password = prompt('Invalid password. Please try again.')
callbackProxy(password)
break
}
default:
}
}

const cover = (
<>
Expand All @@ -107,76 +29,15 @@ export const PdfComponent = memo(function ({
displayView={false}
nft={nft}
/>
{loading && (
<p
key={`loading-${nft.token_id}`}
style={{ textAlign: 'center', margin: '1em' }}
>
Loading PDF...
</p>
)}
</>
)
// console.log({
// pageNumber,
// renderedPageNumber,
// })
// const loading = renderedPageNumber !== pageNumber
if (!displayView) return cover

return (
<div ref={container} className={styles.container}>
{!showDocument ? (
<Button
onClick={() => {
setShowDocument(true)
}}
>
Reload PDF with password
</Button>
) : (
<Document
file={file}
loading={cover}
onPassword={onPassword}
onLoadSuccess={onDocumentLoadSuccess}
onLoadError={onDocumentLoadError}
title={`PDF object ${nft.token_id}`}
options={options}
>
{renderedPageNumber && renderedPageNumber !== pageNumber && (
<Page
key={`${renderedPageNumber}`}
className={styles.previous_page}
pageNumber={renderedPageNumber}
height={height}
/>
)}
<Page
key={pageNumber}
className={styles.page}
pageNumber={pageNumber}
onRenderSuccess={onRender}
height={height}
/>
</Document>
)}
{!loading && showDocument && (
<div className={styles.pdfNav}>
<Button disabled={pageNumber <= 1} onClick={previousPage}>
{'Prev «'}
</Button>
<p>
Page {pageNumber || (numPages ? 1 : '--')} of {numPages || '--'}
</p>
<Button
disabled={numPages ? pageNumber >= numPages : false}
onClick={nextPage}
>
{'>» Next'}
</Button>
</div>
)}
<div className={classes}>
<iframe
title={`PDF ${nft.token_id}`}
src={import.meta.env.VITE_IFRAME_URL + `/pdf/?pdfSrc=${artifactUri}`}
/>
</div>
)
})
Expand Down
2 changes: 1 addition & 1 deletion src/components/media-types/vector/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,6 @@ export const VectorComponent = ({
)
}
// svg version: src={`${src}?author=${_creator_}&viewer=${_viewer_}`}
// iframe version: src={`https://iframe.teia.art/svg/?src=${src}&creator=${_creator_}&viewer=${_viewer_}`}
// iframe version: src={import.meta.env.VITE_IFRAME_URL + `/svg/?src=${src}&creator=${_creator_}&viewer=${_viewer_}`}

export default VectorComponent
Loading