mirror of
				https://github.com/janeczku/calibre-web
				synced 2025-10-31 15:23:02 +00:00 
			
		
		
		
	Refactor epub reader progress calculation
The code in epub-progress.js was causing the epub file to be loaded twice over the network, because it created a second instance of the epub.js library. I moved all the progress percentage display code into epub.js. Only the locationchange polyfill code was left in the separate file, renamed to locationchange-polyfill.js. I rewrote the percentage progress code to use epub.js events, giving more succinct and readable code. Also, I added localStorage caching of the epub location calculations, required for displaying percentage progress, which can take up to 60-90 seconds to calculate on longer ebooks. This localStorage caching approach is recommended by epub.js in the `locations.html` example in their repo. Signed-off-by: Ross Williams <ross@ross-williams.net>
This commit is contained in:
		| @@ -831,4 +831,5 @@ input:-moz-placeholder { color: #454545; } | ||||
|     bottom: 4rem; | ||||
|     width: fit-content; | ||||
|     position: absolute; | ||||
|     visibility: hidden; | ||||
| } | ||||
|   | ||||
| @@ -1,54 +0,0 @@ | ||||
| /** | ||||
|  * waits until queue is finished, meaning the book is done loading | ||||
|  * @param callback | ||||
|  */ | ||||
| function qFinished(callback){ | ||||
|     let timeout=setInterval(()=>{ | ||||
|         if(reader.rendition.q.running===undefined) | ||||
|             clearInterval(timeout); | ||||
|             callback(); | ||||
|         },300 | ||||
|     ) | ||||
| } | ||||
|  | ||||
| function calculateProgress(){ | ||||
|     let data=reader.rendition.location.end; | ||||
|     return Math.round(epub.locations.percentageFromCfi(data.cfi)*100); | ||||
| } | ||||
|  | ||||
| // register new event emitter locationchange that fires on urlchange | ||||
| // source: https://stackoverflow.com/a/52809105/21941129 | ||||
| (() => { | ||||
|     let oldPushState = history.pushState; | ||||
|     history.pushState = function pushState() { | ||||
|         let ret = oldPushState.apply(this, arguments); | ||||
|         window.dispatchEvent(new Event('locationchange')); | ||||
|         return ret; | ||||
|     }; | ||||
|  | ||||
|     let oldReplaceState = history.replaceState; | ||||
|     history.replaceState = function replaceState() { | ||||
|         let ret = oldReplaceState.apply(this, arguments); | ||||
|         window.dispatchEvent(new Event('locationchange')); | ||||
|         return ret; | ||||
|     }; | ||||
|  | ||||
|     window.addEventListener('popstate', () => { | ||||
|         window.dispatchEvent(new Event('locationchange')); | ||||
|     }); | ||||
| })(); | ||||
|  | ||||
| window.addEventListener('locationchange',()=>{ | ||||
|     let newPos=calculateProgress(); | ||||
|     progressDiv.textContent=newPos+"%"; | ||||
| }); | ||||
|  | ||||
| var epub=ePub(calibre.bookUrl) | ||||
|  | ||||
| let progressDiv=document.getElementById("progress"); | ||||
|  | ||||
| qFinished(()=>{ | ||||
|     epub.locations.generate().then(()=> { | ||||
|     window.dispatchEvent(new Event('locationchange')) | ||||
| }); | ||||
| }) | ||||
| @@ -52,6 +52,32 @@ var reader; | ||||
|         } | ||||
|     }); | ||||
|  | ||||
|     // Update progress percentage | ||||
|     let progressDiv = document.getElementById("progress"); | ||||
|     reader.book.ready.then((()=>{ | ||||
|         let locations_key = reader.book.key()+'-locations'; | ||||
|         let stored_locations = localStorage.getItem(locations_key); | ||||
|         let make_locations, save_locations; | ||||
|         if (stored_locations) { | ||||
|             make_locations = Promise.resolve(reader.book.locations.load(stored_locations)); | ||||
|             // No-op because locations are already saved | ||||
|             save_locations = ()=>{}; | ||||
|         } else { | ||||
|             make_locations = reader.book.locations.generate(); | ||||
|             save_locations = ()=>{ | ||||
|                 localStorage.setItem(locations_key, reader.book.locations.save()); | ||||
|             }; | ||||
|         } | ||||
|         make_locations.then(()=>{ | ||||
|             reader.rendition.on('relocated', (location)=>{ | ||||
|                 let percentage = Math.round(location.end.percentage*100); | ||||
|                 progressDiv.textContent=percentage+"%"; | ||||
|             }); | ||||
|             reader.rendition.reportLocation(); | ||||
|             progressDiv.style.visibility = "visible"; | ||||
|         }).then(save_locations); | ||||
|     })); | ||||
|  | ||||
|     /** | ||||
|      * @param {string} action - Add or remove bookmark | ||||
|      * @param {string|int} location - Location or zero | ||||
|   | ||||
							
								
								
									
										21
									
								
								cps/static/js/reading/locationchange-polyfill.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								cps/static/js/reading/locationchange-polyfill.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| // register new event emitter locationchange that fires on urlchange | ||||
| // source: https://stackoverflow.com/a/52809105/21941129 | ||||
| (() => { | ||||
|     let oldPushState = history.pushState; | ||||
|     history.pushState = function pushState() { | ||||
|         let ret = oldPushState.apply(this, arguments); | ||||
|         window.dispatchEvent(new Event('locationchange')); | ||||
|         return ret; | ||||
|     }; | ||||
|  | ||||
|     let oldReplaceState = history.replaceState; | ||||
|     history.replaceState = function replaceState() { | ||||
|         let ret = oldReplaceState.apply(this, arguments); | ||||
|         window.dispatchEvent(new Event('locationchange')); | ||||
|         return ret; | ||||
|     }; | ||||
|  | ||||
|     window.addEventListener('popstate', () => { | ||||
|         window.dispatchEvent(new Event('locationchange')); | ||||
|     }); | ||||
| })(); | ||||
| @@ -215,6 +215,6 @@ | ||||
|       <script src="{{ url_for('static', filename='js/libs/screenfull.min.js') }}"></script> | ||||
|       <script src="{{ url_for('static', filename='js/libs/reader.min.js') }}"></script> | ||||
|       <script src="{{ url_for('static', filename='js/reading/epub.js') }}"></script> | ||||
|       <script src="{{ url_for('static', filename='js/reading/epub-progress.js') }}"></script>       | ||||
|       <script src="{{ url_for('static', filename='js/reading/locationchange-polyfill.js') }}"></script>       | ||||
|     </body> | ||||
| </html> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Ross Williams
					Ross Williams