diff --git a/scripts/pb-init.sh b/scripts/pb-init.sh index 1bb82b4..f84c78e 100755 --- a/scripts/pb-init.sh +++ b/scripts/pb-init.sh @@ -181,9 +181,24 @@ create_collection "app_users" '{ ] }' +create_collection "user_settings" '{ + "name": "user_settings", + "type": "base", + "fields": [ + {"name": "session_id", "type": "text", "required": true}, + {"name": "user_id", "type": "text"}, + {"name": "auto_next", "type": "bool"}, + {"name": "voice", "type": "text"}, + {"name": "speed", "type": "number"}, + {"name": "updated", "type": "date"} + ] +}' + # ─── 5. Schema migrations (idempotent field additions) ─────────────────────── # Ensures fields added after initial deploy are present in existing instances. ensure_field "progress" "user_id" "text" +ensure_field "progress" "audio_time" "number" +ensure_field "user_settings" "user_id" "text" log "all collections ready" diff --git a/ui/src/lib/components/AudioPlayer.svelte b/ui/src/lib/components/AudioPlayer.svelte index 97fadf6..e6ad0be 100644 --- a/ui/src/lib/components/AudioPlayer.svelte +++ b/ui/src/lib/components/AudioPlayer.svelte @@ -138,6 +138,8 @@ if (url) { audioStore.audioUrl = url; audioStore.status = 'ready'; + // Restore last saved position after the audio element loads + restoreSavedAudioTime(); return; } @@ -158,6 +160,7 @@ if (!url2) throw new Error('Audio generated but presign returned 404'); audioStore.audioUrl = url2; audioStore.status = 'ready'; + // Don't restore time for freshly generated audio — position is 0 } catch (e) { stopProgress(); audioStore.progress = 0; @@ -166,6 +169,27 @@ } } + /** + * Fetch the saved audio time for this chapter and seek to it after a short + * delay (to allow the audio element to load the source). + */ + async function restoreSavedAudioTime() { + try { + const params = new URLSearchParams({ slug, chapter: String(chapter) }); + const res = await fetch(`/api/progress/audio-time?${params}`); + if (!res.ok) return; + const data = (await res.json()) as { audioTime: number | null }; + if (data.audioTime && data.audioTime > 5) { + // Small delay to let the