0.4.11: slider margini rimossi dalle Impostazioni (resta il dialog nel lettore); margini alto/basso strutturali — finestra di lettura dentro i margini, identici su ogni pagina

This commit is contained in:
2026-09-07 17:47:57 +02:00
parent 9500c353a3
commit 6fcf05a289
5 changed files with 101 additions and 184 deletions
+31 -71
View File
@@ -41,24 +41,10 @@ Page {
allowedOrientations: Orientation.All
// Sfondo di lettura UNIFORME (invece del gradiente di sistema): le fasce
// dei margini usano questo stesso colore, quindi margine e sfondo sono
// indistinguibili su ogni pagina (niente bande visibili, niente testo
// "coperto" percepibile: le righe spariscono nel margine).
property color readerBgColor: Theme.colorScheme === Theme.LightOnDark
? "#FF0E0E0E" : "#FFFFFFFF"
EpubBook {
id: book
}
// sfondo pieno del lettore, dietro tutto il resto
Rectangle {
anchors.fill: parent
z: -1
color: page.readerBgColor
}
SilicaFlickable {
id: outerFlick
anchors.fill: parent
@@ -156,10 +142,18 @@ Page {
}
}
// contenuto: Flickable NON interattivo (lo scroll è solo programmatico)
// contenuto: Flickable NON interattivo (lo scroll è solo programmatico).
// La finestra di lettura VIVE DENTRO i margini verticali (top/bottom
// margin): il testo non puo' fisicamente uscire dai bordi, quindi i
// margini alto/basso sono identici su OGNI pagina (non solo a inizio
// capitolo) e si aggiornano live con l'anteprima del dialog.
Flickable {
id: innerFlick
anchors.fill: parent
anchors.topMargin: page.previewMarginT >= 0
? page.previewMarginT : appSettings.readerMarginV
anchors.bottomMargin: page.previewMarginT >= 0
? page.previewMarginT : appSettings.readerMarginV
contentHeight: readerContent.height
interactive: false
clip: true
@@ -167,16 +161,25 @@ Page {
Item {
id: readerContent
width: parent.width
// Il contenitore ha il padding verticale (margine) + il "deficit"
// dell'ultima pagina: cosi' max-scroll = k*step e l'ultima pagina
// e' allineata (niente testo ripetuto tra penultima e ultima).
height: Math.max(parent.height,
textItem.height + 2 * page.marginV() + page.lastPagePad())
// Altezza = testo + "deficit" dell'ultima pagina: max-scroll
// diventa k*step esatto e l'ultima pagina e' allineata (niente
// testo ripetuto tra penultima e ultima). Calcolo INLINE nel
// binding: si rivaluta quando cambia la finestra (rotazione,
// anteprima margini) o l'altezza del testo (reflow).
height: {
var step = Math.max(1, parent.height)
var t = textItem.height
var pad = 0
if (t > 0) {
var r = t % step
pad = r === 0 ? 0 : step - r
}
return Math.max(parent.height, t + pad)
}
Text {
id: textItem
x: page.previewMarginL >= 0 ? page.previewMarginL : appSettings.readerMargin
y: page.previewMarginT >= 0 ? page.previewMarginT : appSettings.readerMarginV
width: parent.width - 2 * (page.previewMarginL >= 0
? page.previewMarginL
: appSettings.readerMargin)
@@ -190,31 +193,6 @@ Page {
}
}
// Margini verticali VISTI su ogni schermata: due fasce opache (colore di
// sfondo) coprono il testo a cavallo dei bordi della viewport. Il testo
// scorre tra le fasce con passo = viewport - 2*margine: ogni pagina
// mostra esattamente un blocco di testo con margine sopra e sotto.
Rectangle {
id: topBand
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
height: page.marginV()
visible: height > 0
z: 5
color: page.readerBgColor
}
Rectangle {
id: bottomBand
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: page.marginV()
visible: height > 0
z: 5
color: page.readerBgColor
}
// 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:
@@ -309,9 +287,9 @@ Page {
function readScrollPosition() {
if (!page.ready)
return
// passo di pagina = viewport - 2*margine verticale: ogni pagina mostra
// il testo DENTRO i margini (niente righe a filo del bordo)
var step = Math.max(1, innerFlick.height - 2 * page.marginV())
// passo di pagina = altezza della finestra di lettura (i margini
// alto/basso sono FUORI dal Flickable: nessun testo li attraversa)
var step = Math.max(1, innerFlick.height)
var max = Math.max(0, innerFlick.contentHeight - innerFlick.height)
var y = Math.max(0, Math.min(max, innerFlick.contentY))
var len = book.chapterTextLength(page.currentChapter)
@@ -323,23 +301,6 @@ Page {
maybeSave(false)
}
// margine verticale effettivo (anteprima dialog oppure impostazioni)
function marginV() {
return page.previewMarginT >= 0 ? page.previewMarginT : appSettings.readerMarginV
}
// deficit dell'ultima pagina: porta max-scroll a un multiplo esatto del
// passo, cosi' l'ultima pagina mostra il testo residuo SENZA sovrapporsi
// alla penultima (niente righe ripetute) e con il margine sotto
function lastPagePad() {
var step = Math.max(1, innerFlick.height - 2 * page.marginV())
var t = textItem.height
if (t <= 0)
return 0
var r = t % step
return r === 0 ? 0 : step - r
}
function maybeSave(force) {
if (bookId <= 0)
return
@@ -385,13 +346,12 @@ Page {
restoreTimer.start()
}
// pagina successiva: una pagina di testo = viewport meno i margini verticali
// (così ogni pagina ha il testo dentro i margini, non a filo del bordo);
// a fine capitolo passa al successivo
// pagina successiva: una pagina di testo = altezza della finestra di
// lettura; a fine capitolo passa al successivo
function nextPage() {
if (!page.ready)
return
var step = Math.max(1, innerFlick.height - 2 * page.marginV())
var step = Math.max(1, innerFlick.height)
var max = Math.max(0, innerFlick.contentHeight - innerFlick.height)
var y = innerFlick.contentY
if (y >= max - 2) {
@@ -410,7 +370,7 @@ Page {
function prevPage() {
if (!page.ready)
return
var step = Math.max(1, innerFlick.height - 2 * page.marginV())
var step = Math.max(1, innerFlick.height)
var y = innerFlick.contentY
if (y > 1) {
innerFlick.contentY = Math.max(0, y - step)