@@ -20,8 +20,6 @@ interface DocumentLoadSuccess {
2020 numPages : number ;
2121}
2222
23- const PAGE_INIT_DELAY = 800 ;
24-
2523const PDFViewer = ( ) => {
2624 const [ numPages , setNumPages ] = useState < number | null > ( null ) ;
2725 const [ pageNumber , setPageNumber ] = useState ( 1 ) ;
@@ -45,13 +43,13 @@ const PDFViewer = () => {
4543 const pageRefs = useRef < Record < number , HTMLDivElement | null > > ( { } ) ;
4644 const prevGuidRef = useRef < string | null > ( null ) ;
4745 const isFetchingRef = useRef ( false ) ;
46+ const isAutoScrollingRef = useRef ( false ) ;
4847
4948 const location = useLocation ( ) ;
5049 const navigate = useNavigate ( ) ;
5150 const params = new URLSearchParams ( location . search ) ;
5251 const guid = params . get ( "guid" ) ;
5352 const pageParam = params . get ( "page" ) ;
54-
5553 const baseURL = import . meta. env . VITE_API_BASE_URL as string | undefined ;
5654
5755 const pdfUrl = useMemo ( ( ) => {
@@ -65,28 +63,45 @@ const PDFViewer = () => {
6563 const guidChanged = guid !== prevGuidRef . current ;
6664
6765 if ( guidChanged ) {
68- pageRefs . current = { } ;
6966 setIsDocumentLoaded ( false ) ;
7067 setNumPages ( null ) ;
7168 setPdfData ( null ) ;
72- setPageNumber ( 1 ) ;
69+ setTargetPageAfterLoad ( null ) ;
70+ const validPage = ! isNaN ( nextPage ) && nextPage > 0 ? nextPage : 1 ;
71+ setPageNumber ( validPage ) ;
72+ setTargetPageAfterLoad ( validPage ) ;
73+ prevGuidRef . current = guid ;
74+ return ;
75+ }
76+
77+ const desired = ! isNaN ( nextPage ) && nextPage > 0 ? nextPage : 1 ;
78+ if ( pageNumber !== desired ) {
79+ if ( isDocumentLoaded && numPages ) {
80+ const clampedPage = Math . max ( 1 , Math . min ( desired , numPages ) ) ;
81+ setPageNumber ( clampedPage ) ;
82+ scrollToPage ( clampedPage ) ;
83+ } else {
84+ setPageNumber ( desired ) ;
85+ setTargetPageAfterLoad ( desired ) ;
86+ }
7387 }
7488
75- setTargetPageAfterLoad ( ! isNaN ( nextPage ) && nextPage > 0 ? nextPage : 1 ) ;
7689 prevGuidRef . current = guid ;
77- } , [ guid , pageParam , location . pathname , location . search ] ) ;
90+ } , [ guid , pageParam , pageNumber , isDocumentLoaded , numPages ] ) ;
7891
7992 const updateCurrentPageFromScroll = useCallback ( ( ) => {
8093 if ( ! numPages || ! contentRef . current ) return ;
8194
95+ if ( isAutoScrollingRef . current ) return ;
96+
8297 const container = contentRef . current ;
8398 const containerRectTop = container . getBoundingClientRect ( ) . top ;
8499 const containerCenter = containerRectTop + container . clientHeight / 2 ;
85100
86101 let bestPage = 1 ;
87102 let bestDist = Infinity ;
88103
89- for ( let i = 1 ; i <= ( numPages ?? 0 ) ; i ++ ) {
104+ for ( let i = 1 ; i <= numPages ; i ++ ) {
90105 const el = pageRefs . current [ i ] ;
91106 if ( ! el ) continue ;
92107 const r = el . getBoundingClientRect ( ) ;
@@ -99,6 +114,9 @@ const PDFViewer = () => {
99114 }
100115
101116 if ( bestPage !== pageNumber ) {
117+ console . log (
118+ `Scroll detected: updating page from ${ pageNumber } to ${ bestPage } `
119+ ) ;
102120 setPageNumber ( bestPage ) ;
103121 const newParams = new URLSearchParams ( location . search ) ;
104122 newParams . set ( "page" , String ( bestPage ) ) ;
@@ -126,16 +144,6 @@ const PDFViewer = () => {
126144 return ( ) => container . removeEventListener ( "scroll" , onScroll ) ;
127145 } , [ updateCurrentPageFromScroll ] ) ;
128146
129- useEffect ( ( ) => {
130- updateCurrentPageFromScroll ( ) ;
131- } , [
132- numPages ,
133- deferredScale ,
134- containerSize . width ,
135- containerSize . height ,
136- updateCurrentPageFromScroll ,
137- ] ) ;
138-
139147 const scrollToPage = useCallback (
140148 ( page : number ) => {
141149 if ( ! numPages || page < 1 || page > numPages ) return ;
@@ -146,35 +154,47 @@ const PDFViewer = () => {
146154 return ;
147155 }
148156
157+ isAutoScrollingRef . current = true ;
149158 targetRef . scrollIntoView ( {
150159 behavior : "smooth" ,
151160 block : "start" ,
152161 inline : "nearest" ,
153162 } ) ;
154163
155164 const newParams = new URLSearchParams ( location . search ) ;
156- const oldPage = newParams . get ( "page" ) ;
157- if ( oldPage !== String ( page ) ) {
165+ if ( newParams . get ( "page" ) !== String ( page ) ) {
158166 newParams . set ( "page" , String ( page ) ) ;
159167 navigate ( `${ location . pathname } ?${ newParams . toString ( ) } ` , {
160168 replace : true ,
161169 } ) ;
162170 }
163171
164- setPageNumber ( page ) ;
172+ setTimeout ( ( ) => {
173+ isAutoScrollingRef . current = false ;
174+ updateCurrentPageFromScroll ( ) ;
175+ } , 500 ) ;
165176 } ,
166- [ numPages , location . pathname , location . search , navigate ]
177+ [
178+ numPages ,
179+ location . pathname ,
180+ location . search ,
181+ navigate ,
182+ updateCurrentPageFromScroll ,
183+ ]
167184 ) ;
168185
169186 const goToPage = useCallback (
170187 ( page : number ) => {
171188 if ( typeof page !== "number" || isNaN ( page ) ) return ;
172189
173190 const clamped = Math . max ( 1 , numPages ? Math . min ( page , numPages ) : page ) ;
191+
174192 if ( ! isDocumentLoaded || ! numPages ) {
175193 setTargetPageAfterLoad ( clamped ) ;
194+ setPageNumber ( clamped ) ;
176195 return ;
177196 }
197+
178198 if ( clamped === pageNumber ) return ;
179199
180200 setPageNumber ( clamped ) ;
@@ -197,16 +217,19 @@ const PDFViewer = () => {
197217 } , [ goToPage ] ) ;
198218
199219 useEffect ( ( ) => {
200- if ( isDocumentLoaded && numPages && targetPageAfterLoad ) {
201- const validPage = Math . min ( Math . max ( 1 , targetPageAfterLoad ) , numPages ) ;
202- setPageNumber ( validPage ) ;
220+ if ( isDocumentLoaded && numPages && targetPageAfterLoad !== null ) {
221+ const validPage = Math . max ( 1 , Math . min ( targetPageAfterLoad , numPages ) ) ;
203222
204- const timer = setTimeout ( ( ) => {
223+ console . log ( `Navigating to page ${ validPage } after document load` ) ;
224+ const timeoutId = setTimeout ( ( ) => {
205225 scrollToPage ( validPage ) ;
206- setTargetPageAfterLoad ( null ) ;
207- } , PAGE_INIT_DELAY ) ;
208226
209- return ( ) => clearTimeout ( timer ) ;
227+ setTimeout ( ( ) => {
228+ setTargetPageAfterLoad ( null ) ;
229+ } , 600 ) ;
230+ } , 100 ) ;
231+
232+ return ( ) => clearTimeout ( timeoutId ) ;
210233 }
211234 } , [ isDocumentLoaded , numPages , targetPageAfterLoad , scrollToPage ] ) ;
212235
@@ -301,6 +324,7 @@ const PDFViewer = () => {
301324
302325 const onDocumentLoadSuccess = useCallback (
303326 ( { numPages } : DocumentLoadSuccess ) => {
327+ console . log ( `Document loaded with ${ numPages } pages` ) ;
304328 setNumPages ( numPages ) ;
305329 setError ( null ) ;
306330 setIsDocumentLoaded ( true ) ;
@@ -441,7 +465,7 @@ const PDFViewer = () => {
441465 data-page = { pageNum }
442466 >
443467 < Page
444- key = { ` ${ guid } - ${ pageNum } ` }
468+ key = { pageNum }
445469 pageNumber = { pageNum }
446470 width = { baseWidth }
447471 scale = { deferredScale }
0 commit comments