Lettore 0.4.1: snap alle pagine, niente preventStealing (menu pulley ok)

preventStealing sulla MouseArea rubava il drag al PushUpMenu (il gesto si
bloccava appena il dito entrava nella zona centrale) e senza di esso il
contenuto scrollava libero. Ora: il drag e' permesso ma lo snap (250ms dopo
l'ultimo movimento) riallinea contentY alla pagina piu' vicina (soglia 70%,
zona finale parziale -> fondo). I pulley menu funzionano normalmente.
This commit is contained in:
2026-08-21 11:46:50 +02:00
parent 60f53ab4e4
commit 47f949c3fb
3 changed files with 55 additions and 11 deletions
+46 -8
View File
@@ -48,9 +48,13 @@ Page {
id: readerFlick
anchors.fill: parent
contentHeight: readerContent.height
// ogni movimento del contenuto (drag/flick) riavvia lo snap: il testo
// può essere trascinato ma torna sempre alla pagina (paginazione a tap)
onContentYChanged: snapTimer.restart()
// il PullDownMenu va DENTRO una vista Silica, non a livello di Page
PullDownMenu {
id: pullMenu
MenuItem {
text: qsTr("Table of contents")
onClicked: showChapterList()
@@ -165,17 +169,16 @@ Page {
}
}
// Paginazione a tap: niente scroll libero. La meta' destra va avanti di
// una pagina, la sinistra indietro. Le fasce superiore e inferiore sono
// lasciate ai menu (PullDown in alto, PushUp in basso).
// preventStealing: i drag nella zona centrale NON scrollano (paginazione
// a tap come richiesto), i pulley menu restano raggiungibili dai bordi.
// Paginazione a tap: la meta' destra va avanti di una pagina, la
// sinistra indietro. Le fasce superiore e inferiore sono lasciate ai
// menu (PullDown in alto, PushUp in basso). NIENTE preventStealing:
// ruba il gesto ai pulley menu. Lo scroll libero è neutralizzato dallo
// snap alle pagine (snapTimer), non bloccando i gesti.
MouseArea {
id: tapZone
anchors.fill: parent
anchors.topMargin: Theme.itemSizeLarge
anchors.bottomMargin: Theme.itemSizeLarge + Theme.paddingLarge
preventStealing: true
onClicked: {
if (mouse.x > width / 2)
page.nextPage()
@@ -221,6 +224,41 @@ Page {
onTriggered: readScrollPosition()
}
// snap alle pagine: 250 ms dopo l'ultimo movimento, riallinea contentY al
// multiplo di viewport più vicino (neutralizza lo scroll libero senza
// bloccare i gesti dei pulley menu)
Timer {
id: snapTimer
interval: 250
onTriggered: snapToPage()
}
function snapToPage() {
if (!page.ready || page.pendingRestore)
return
// menu aperti: il contenuto è spostato apposta, niente snap
if (pullMenu.open || readerMenu.open)
return
var vh = Math.max(1, readerFlick.height)
var max = Math.max(0, readerFlick.contentHeight - vh)
var y = readerFlick.contentY
var target
// ultima pagina "piena" allineata alla viewport
var last = Math.floor(max / vh) * vh
if (y > last + 2) {
// zona finale parziale: snap al fondo (evita il loop round->indietro)
target = max
} else {
// soglia al 70% della pagina: trascinamenti piccoli tornano alla
// pagina corrente, oltre metà vanno alla pagina dopo
target = Math.round(y / vh - 0.2) * vh
}
target = Math.max(0, Math.min(max, target))
if (Math.abs(target - y) > 2)
readerFlick.contentY = target
readScrollPosition()
}
function overallProgress() {
if (book.chapterCount <= 0)
return 0
@@ -314,7 +352,7 @@ Page {
}
// pagina successiva: una viewport avanti (contentY nativo, affidabile);
// a fine capitolo (o capitolo non scrollabile) passa al successivo
// a fine capitolo (y a fondo, con lo snap allineato) passa al successivo
function nextPage() {
if (!page.ready)
return
@@ -322,7 +360,7 @@ Page {
var max = Math.max(0, readerFlick.contentHeight - vh)
var y = readerFlick.contentY
if (y >= max - 2) {
// fine capitolo: segna la coda come letta e passa avanti
// fine capitolo (o capitolo non scrollabile): segna la coda e passa
page.charOffset = Math.max(0, book.chapterTextLength(page.currentChapter) - 1)
maybeSave(true)
gotoChapter(page.currentChapter + 1)