diff --git a/qml/pages/ReaderPage.qml b/qml/pages/ReaderPage.qml index b07fed1..b725045 100644 --- a/qml/pages/ReaderPage.qml +++ b/qml/pages/ReaderPage.qml @@ -145,10 +145,8 @@ Page { if (off >= book.chapterTextLength(page.currentChapter)) { // oltre la fine = vai all'ultima pagina (usato da // prevPage per non saltare la coda del capitolo) - web.runJavaScript( - "window.scrollTo(0,Math.max(1," - + "document.documentElement.scrollHeight-window.innerHeight));true", - function() { readScrollPosition() }) + web.scrollPosition = Qt.point(0, Math.max(1, web.contentHeight - web.height)) + readScrollPosition() } else { web.runJavaScript(page.scrollToCharJs(off), function() { readScrollPosition() @@ -255,16 +253,12 @@ Page { + "return true;})()" } - // JS che legge la posizione: {o: caratteri di testo sopra la viewport, - // f: frazione di scroll, p: pagina corrente, pc: pagine totali}. - // Il conteggio cammina i text node del DOM: stabile al variare di font e - // margini (a differenza della frazione di scroll). + // JS che conta i caratteri di testo sopra la viewport (per il bookmark). + // Lo scroll NON è gestito qui: pagina/frazione si leggono dalle proprietà + // native del WebView (contentHeight/scrollPosition), sempre affidabili. function positionJs() { return "(function(){" - + "var de=document.documentElement,b=document.body;" - + "var max=Math.max(1,Math.max(de.scrollHeight,b.scrollHeight)-window.innerHeight);" - + "var y=Math.max(0,Math.min(max,window.scrollY));" - + "var vh=window.innerHeight;" + + "var b=document.body;" + "var o=0;" + "var it=document.createTreeWalker(b,NodeFilter.SHOW_TEXT);" + "var n;" @@ -278,8 +272,7 @@ Page { + "var h=rect.bottom-rect.top;" + "if(h>0)o+=Math.round(n.data.length*(0-rect.top)/h);" + "break;}" - + "return JSON.stringify({o:o,f:y/max,p:Math.floor(y/vh)+1," - + "pc:Math.max(1,Math.floor(max/vh)+1)});})()" + + "return o;})()" } // JS che porta in cima alla viewport il carattere 'off' del capitolo @@ -303,12 +296,16 @@ Page { function readScrollPosition() { if (!web.loaded) return - web.runJavaScript(page.positionJs(), function(res) { - var r = JSON.parse(res) - page.charOffset = r.o - page.chapterFraction = r.f - page.pageIndex = r.p - page.pageCount = r.pc + // posizione letta dalle proprietà NATIVE del WebView (affidabili), + // il JS serve solo a contare i caratteri per il bookmark + var vh = Math.max(1, web.height) + var max = Math.max(1, web.contentHeight - vh) + var y = Math.max(0, Math.min(max, web.scrollPosition.y)) + page.chapterFraction = y / max + page.pageIndex = Math.floor(y / vh) + 1 + page.pageCount = Math.max(1, Math.floor(max / vh) + 1) + web.runJavaScript(page.positionJs(), function(o) { + page.charOffset = o || 0 maybeSave(false) }) } @@ -349,70 +346,46 @@ Page { loadChapter() } - // pagina successiva: una viewport avanti. Lo scroll avviene con scrollBy e - // la verifica è "lo scroll si è MOSSO?" — non un confronto con max calcolato - // (innerHeight/scrollHeight del WebView non sempre corrispondono allo scroll - // reale: con max sovrastimato scrollY non lo raggiungeva mai e il passaggio - // al capitolo successivo non scattava). Se non si muove: unlock CSS e riprova; - // se ancora fermo, siamo a fine capitolo (o capitolo non scrollabile) -> avanti. + // pagina successiva: una viewport avanti, usando le proprietà native del + // WebView (contentHeight/scrollPosition) — niente JS di navigazione, quindi + // nessuna dipendenza da runJavaScript/scrollY per il cambio capitolo. + // A fine capitolo (y >= max-2) passa al capitolo successivo. function nextPage() { if (!web.loaded || !page.ready) return - web.runJavaScript( - "(function(){" - + "var de=document.documentElement,b=document.body;" - + "var vh=window.innerHeight;" - + "var before=window.scrollY;" - + "window.scrollBy(0,vh);" - + "if(window.scrollY>before+1)" - + "return JSON.stringify({ok:true,atEnd:false});" - + "de.style.setProperty('overflow','visible','important');" - + "b.style.setProperty('overflow','visible','important');" - + "de.style.setProperty('height','auto','important');" - + "b.style.setProperty('height','auto','important');" - + "window.scrollBy(0,vh);" - + "if(window.scrollY>before+1)" - + "return JSON.stringify({ok:true,atEnd:false});" - + "return JSON.stringify({ok:false,atEnd:true});})()", - function(res) { - var r = JSON.parse(res) - if (r.ok) { - readScrollPosition() - } else if (r.atEnd) { - gotoChapter(page.currentChapter + 1) - } - }) + var vh = Math.max(1, web.height) + var max = Math.max(1, web.contentHeight - vh) + var y = web.scrollPosition.y + if (y >= max - 2) { + // fine capitolo (o capitolo non scrollabile) -> avanti + gotoChapter(page.currentChapter + 1) + return + } + web.scrollPosition = Qt.point(0, Math.min(max, y + vh)) + readScrollPosition() } - // pagina precedente: una viewport indietro; se lo scroll non si muove siamo - // all'inizio -> capitolo prima SULL'ULTIMA PAGINA (non salta la coda) + // pagina precedente: una viewport indietro; all'inizio -> capitolo prima + // SULL'ULTIMA PAGINA (non salta la coda del capitolo) function prevPage() { if (!web.loaded || !page.ready) return - web.runJavaScript( - "(function(){" - + "var vh=window.innerHeight;" - + "var before=window.scrollY;" - + "window.scrollBy(0,-vh);" - + "if(window.scrollY 0) { - maybeSave(true) - page.currentChapter -= 1 - page.chapterFraction = 0 - page.charOffset = 0 - // sentinella "fine capitolo": va oltre la lunghezza, così - // onLoadedChanged porta all'ultima pagina - page.restoreCharOffset = book.chapterTextLength(page.currentChapter) + 1 - page.lastSavedAbs = -1 - loadChapter() - } - }) + var vh = Math.max(1, web.height) + var y = web.scrollPosition.y + if (y > 1) { + web.scrollPosition = Qt.point(0, Math.max(0, y - vh)) + readScrollPosition() + } else if (page.currentChapter > 0) { + maybeSave(true) + page.currentChapter -= 1 + page.chapterFraction = 0 + page.charOffset = 0 + // sentinella "fine capitolo": va oltre la lunghezza, così + // onLoadedChanged porta all'ultima pagina + page.restoreCharOffset = book.chapterTextLength(page.currentChapter) + 1 + page.lastSavedAbs = -1 + loadChapter() + } } function fontPx() { diff --git a/rpm/harbour-calibreweb.spec b/rpm/harbour-calibreweb.spec index 4265d9f..9bcc052 100644 --- a/rpm/harbour-calibreweb.spec +++ b/rpm/harbour-calibreweb.spec @@ -1,6 +1,6 @@ Name: harbour-calibreweb Summary: Client OPDS per Calibre Web -Version: 0.3.1 +Version: 0.3.2 Release: 1 Group: Qt/Qt License: MIT @@ -24,6 +24,12 @@ reflow del testo, margini configurabili e posizione salvata in locale. %changelog +* Fri Aug 21 2026 Carlo Baratto - 0.3.2-1 +- Fix definitivo cambio capitolo: la navigazione non usa piu' window.scrollY/ + scrollBy via runJavaScript (lo scroll reale del WebView Sailfish non e' sempre + riflesso in window.scrollY: la posizione non arrivava mai a fine documento e + il cambio capitolo non scattava). Ora paginazione con le proprieta' NATIVE + del WebView (contentHeight/scrollPosition): aritmetica QML pura, affidabile * Fri Aug 21 2026 Carlo Baratto - 0.3.1-1 - Fix passaggio di capitolo: il tap avanti/indietro usava un confronto con max calcolato (scrollHeight - innerHeight), che sul WebView di Sailfish può essere