Reordonner morceaux selon PDF, paroles dans les pages, sync player↔chapitres

- Reordonne les songs dans le config YAML selon l'ordre du PDF (01→09, 06 en dernier)
- Met à jour les titres avec les noms du PDF et la numérotation correcte
- Remplace le contenu des 11 pages markdown par les paroles des chansons associées
- Ajoute getChapterForSong() dans useBookData pour la recherche inverse
- Ajoute un watcher dans BookPlayer qui navigue au chapitre quand le morceau change
- Flag _skipSongWatch pour éviter les boucles infinies player↔navigation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Yvv
2026-02-22 23:21:29 +01:00
parent ac2b8040b1
commit b29fc77c60
14 changed files with 892 additions and 631 deletions

View File

@@ -190,7 +190,7 @@ function onViewportScroll() {
scrollPercent.value = max > 0 ? Math.round((el.scrollTop / max) * 100) : 0
}
const { init: initBookData, getSongs, getPrimarySong, getPlaylistOrder } = useBookData()
const { init: initBookData, getSongs, getPrimarySong, getChapterForSong, getPlaylistOrder } = useBookData()
const audioPlayer = useAudioPlayer()
const playerStore = usePlayerStore()
@@ -300,6 +300,8 @@ async function initReading() {
}
// ── Navigation ──
let _skipSongWatch = false
function goToChapter(idx: number) {
chapterIdx.value = idx
currentPage.value = 0
@@ -308,9 +310,12 @@ function goToChapter(idx: number) {
if (isScrollMode.value && viewportEl.value) {
viewportEl.value.scrollTop = 0
}
// Play chapter song
// Play chapter song (skip watcher to avoid loop)
const song = getPrimarySong(chapters[idx].slug)
if (song) audioPlayer.loadAndPlay(song)
if (song) {
_skipSongWatch = true
audioPlayer.loadAndPlay(song)
}
}
function nextChapter() {
@@ -347,7 +352,10 @@ function prevPage() {
currentPage.value = 0
showSommaire.value = false
const song = getPrimarySong(chapters[chapterIdx.value].slug)
if (song) audioPlayer.loadAndPlay(song)
if (song) {
_skipSongWatch = true
audioPlayer.loadAndPlay(song)
}
// After content loads, go to last page
watch(activeChapter, async () => {
await nextTick()
@@ -417,7 +425,10 @@ watch(isOpen, async (open) => {
const playlist = getPlaylistOrder()
if (playlist.length) playerStore.setPlaylist(playlist)
const first = getSongs().find(s => s.id === 'chanson-01')
if (first) audioPlayer.loadAndPlay(first)
if (first) {
_skipSongWatch = true
audioPlayer.loadAndPlay(first)
}
// Start reading directly
await initReading()
}
@@ -428,6 +439,25 @@ watch(isOpen, async (open) => {
}
})
// ── Sync: when song changes in player, navigate to matching chapter ──
watch(() => playerStore.currentSong, (song) => {
if (!song || !isOpen.value) return
if (_skipSongWatch) {
_skipSongWatch = false
return
}
const slug = getChapterForSong(song.id)
if (!slug) return
const idx = chapters.findIndex(ch => ch.slug === slug)
if (idx !== -1 && idx !== chapterIdx.value) {
chapterIdx.value = idx
currentPage.value = 0
if (isScrollMode.value && viewportEl.value) {
viewportEl.value.scrollTop = 0
}
}
})
watch(isOpen, (open) => {
if (import.meta.client) document.body.style.overflow = open ? 'hidden' : ''
})