From 9945b20469deaabacbd4003c64f8472cda83777e Mon Sep 17 00:00:00 2001 From: team3 Date: Fri, 9 Oct 2026 18:03:42 +0200 Subject: [PATCH] =?UTF-8?q?Leseposition:=20Buchansicht=20und=20Lesemodus?= =?UTF-8?q?=20teilen=20einen=20Stand,=20nie=20r=C3=BCckw=C3=A4rts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Lesemodus-Schlüssel (03-4:0) wurden in der Buchansicht nicht erkannt. - Es gilt immer die weiter hinten liegende Stelle beider Ansichten. Co-Authored-By: Claude Fable 5.1 --- frontend/src/components/Guide.vue | 15 +++++++++++---- frontend/src/components/Lesemodus.vue | 14 +++++++------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/frontend/src/components/Guide.vue b/frontend/src/components/Guide.vue index 1dc8850..8f18a72 100644 --- a/frontend/src/components/Guide.vue +++ b/frontend/src/components/Guide.vue @@ -21,15 +21,22 @@ function idVonNr(nr) { } // Lesemodus-Schlüssel (vorwort, k3, a03-4:2, ende) → Element-ID der Buchansicht, wenn zuletzt dort gelesen wurde function idVonLesemodus(pos) { - if (pos.zuletzt !== 'lesen' || !pos.lesemodus || !daten.value) return '' + if (!pos.lesemodus || !daten.value) return '' const m = pos.lesemodus if (m === 'vorwort') return 'vorwort' const kap = /^k(\d+)$/.exec(m) if (kap) return 'k' + (daten.value.kapitel[Number(kap[1]) - 1]?.id || '') - const abs = /^(a[\d-]+):/.exec(m) - if (abs) return abs[1] + const abs = /^a?([\d-]+):/.exec(m) + if (abs) return 'a' + abs[1] return '' } +// Von zwei Element-IDs die, die im Buch weiter hinten liegt (Dokumentreihenfolge) +function spaetere(a, b) { + const ea = a && document.getElementById(a), eb = b && document.getElementById(b) + if (!ea) return eb ? b : '' + if (!eb) return a + return ea.compareDocumentPosition(eb) & Node.DOCUMENT_POSITION_FOLLOWING ? b : a +} function nrVonId(id) { if (!id || !daten.value) return '' if (id === 'vorwort') return 'vorwort' @@ -88,7 +95,7 @@ async function laden() { await nextTick() spy() // Gemerkte Position hat Vorrang (die Adresse spiegelt nur den letzten Scrollstand); zuletzt im Lesemodus gelesen → dessen Stelle - const ziel = idVonLesemodus(pos) || pos.abschnitt || idVonNr(props.nr) + const ziel = spaetere(idVonLesemodus(pos), pos.abschnitt) || idVonNr(props.nr) // Der Sprung beim Laden darf die gemerkte Position nicht überschreiben; erst eigenes Scrollen zählt wieder ruhe = true clearTimeout(ruheTimer) diff --git a/frontend/src/components/Lesemodus.vue b/frontend/src/components/Lesemodus.vue index 703e170..29452a1 100644 --- a/frontend/src/components/Lesemodus.vue +++ b/frontend/src/components/Lesemodus.vue @@ -84,14 +84,14 @@ onMounted(async () => { window.addEventListener('keydown', taste) const p = await api.position(props.slug, props.version).catch(() => ({})) const merk = p.lesemodus - // Zuletzt in der Buchansicht gelesen → beim passenden Abschnitt bzw. Kapitel beginnen - let i = -1 - if (p.zuletzt === 'buch' && p.abschnitt) { - const a = p.abschnitt - i = screens.value.findIndex((s) => s.key === a || s.key.startsWith(a + ':') || (s.typ === 'kapitel' && 'k' + s.kap.id === a)) - } // Alte Positionen waren ein Index, neue sind ein key. - if (i < 0) i = typeof merk === 'string' ? screens.value.findIndex((s) => s.key === merk) : Number(merk || 0) + let i = typeof merk === 'string' ? screens.value.findIndex((s) => s.key === merk) : Number(merk || 0) + // Beide Ansichten teilen einen Stand: Liegt die Stelle der Buchansicht weiter hinten, gilt sie; nie zurück. + if (p.abschnitt) { + const a = p.abschnitt.replace(/^a/, '') + const j = screens.value.findIndex((s) => s.key === p.abschnitt || s.key.startsWith(a + ':') || (s.typ === 'kapitel' && 'k' + s.kap.id === p.abschnitt)) + if (j > i) i = j + } pos.value = Math.min(Math.max(i, 0), screens.value.length - 1) }) onUnmounted(() => window.removeEventListener('keydown', taste))