Add functionality for 'end of chapter' sleep timer

This commit is contained in:
Greg Lorenzen 2024-07-11 17:37:02 +00:00
parent 41e3965467
commit cd902c0636
3 changed files with 61 additions and 24 deletions

View file

@ -35,6 +35,7 @@
<player-ui <player-ui
ref="audioPlayer" ref="audioPlayer"
:chapters="chapters" :chapters="chapters"
:current-chapter="currentChapter"
:paused="!isPlaying" :paused="!isPlaying"
:loading="playerLoading" :loading="playerLoading"
:bookmarks="bookmarks" :bookmarks="bookmarks"
@ -79,6 +80,7 @@ export default {
sleepTimerSet: false, sleepTimerSet: false,
sleepTimerTime: 0, sleepTimerTime: 0,
sleepTimerRemaining: 0, sleepTimerRemaining: 0,
sleepTimerType: null,
sleepTimer: null, sleepTimer: null,
displayTitle: null, displayTitle: null,
currentPlaybackRate: 1, currentPlaybackRate: 1,
@ -86,6 +88,13 @@ export default {
coverAspectRatio: 1 coverAspectRatio: 1
} }
}, },
watch: {
currentTime(newTime) {
if (this.sleepTimerType === this.$constants.SleepTimerTypes.CHAPTER && this.sleepTimerSet) {
this.checkChapterEnd(newTime)
}
}
},
computed: { computed: {
isSquareCover() { isSquareCover() {
return this.coverAspectRatio === 1 return this.coverAspectRatio === 1
@ -145,6 +154,9 @@ export default {
if (this.streamEpisode) return this.streamEpisode.chapters || [] if (this.streamEpisode) return this.streamEpisode.chapters || []
return this.media.chapters || [] return this.media.chapters || []
}, },
currentChapter() {
return this.chapters.find((chapter) => chapter.start <= this.currentTime && this.currentTime < chapter.end)
},
title() { title() {
if (this.playerHandler.displayTitle) return this.playerHandler.displayTitle if (this.playerHandler.displayTitle) return this.playerHandler.displayTitle
return this.mediaMetadata.title || 'No Title' return this.mediaMetadata.title || 'No Title'
@ -204,14 +216,19 @@ export default {
this.$store.commit('setIsPlaying', isPlaying) this.$store.commit('setIsPlaying', isPlaying)
this.updateMediaSessionPlaybackState() this.updateMediaSessionPlaybackState()
}, },
setSleepTimer(seconds) { setSleepTimer(time) {
this.sleepTimerSet = true this.sleepTimerSet = true
this.sleepTimerTime = seconds
this.sleepTimerRemaining = seconds
this.runSleepTimer()
this.showSleepTimerModal = false this.showSleepTimerModal = false
this.sleepTimerType = time.timerType
if (this.sleepTimerType === this.$constants.SleepTimerTypes.COUNTDOWN) {
this.runSleepTimer(time)
}
}, },
runSleepTimer() { runSleepTimer(time) {
this.sleepTimerTime = time.seconds
this.sleepTimerRemaining = time.seconds
var lastTick = Date.now() var lastTick = Date.now()
clearInterval(this.sleepTimer) clearInterval(this.sleepTimer)
this.sleepTimer = setInterval(() => { this.sleepTimer = setInterval(() => {
@ -220,11 +237,22 @@ export default {
this.sleepTimerRemaining -= elapsed / 1000 this.sleepTimerRemaining -= elapsed / 1000
if (this.sleepTimerRemaining <= 0) { if (this.sleepTimerRemaining <= 0) {
this.sleepTimerEnd()
}
}, 1000)
},
checkChapterEnd(time) {
const chapterEndTime = this.currentChapter.end
const tolerance = 0.5
if (time >= chapterEndTime - tolerance) {
console.log('Chapter end reached', time, chapterEndTime)
this.sleepTimerEnd()
}
},
sleepTimerEnd() {
this.clearSleepTimer() this.clearSleepTimer()
this.playerHandler.pause() this.playerHandler.pause()
this.$toast.info('Sleep Timer Done.. zZzzZz') this.$toast.info('Sleep Timer Done.. zZzzZz')
}
}, 1000)
}, },
cancelSleepTimer() { cancelSleepTimer() {
this.showSleepTimerModal = false this.showSleepTimerModal = false
@ -235,6 +263,7 @@ export default {
this.sleepTimerRemaining = 0 this.sleepTimerRemaining = 0
this.sleepTimer = null this.sleepTimer = null
this.sleepTimerSet = false this.sleepTimerSet = false
this.sleepTimerType = null
}, },
incrementSleepTimer(amount) { incrementSleepTimer(amount) {
if (!this.sleepTimerSet) return if (!this.sleepTimerSet) return

View file

@ -9,7 +9,7 @@
<div ref="container" class="w-full rounded-lg bg-primary box-shadow-md overflow-y-auto overflow-x-hidden" style="max-height: 80vh"> <div ref="container" class="w-full rounded-lg bg-primary box-shadow-md overflow-y-auto overflow-x-hidden" style="max-height: 80vh">
<div v-if="!timerSet" class="w-full"> <div v-if="!timerSet" class="w-full">
<template v-for="time in sleepTimes"> <template v-for="time in sleepTimes">
<div :key="time.text" class="flex items-center px-6 py-3 justify-center cursor-pointer hover:bg-bg relative" @click="setTime(time.seconds)"> <div :key="time.text" class="flex items-center px-6 py-3 justify-center cursor-pointer hover:bg-bg relative" @click="setTime(time)">
<p class="text-xl text-center">{{ time.text }}</p> <p class="text-xl text-center">{{ time.text }}</p>
</div> </div>
</template> </template>
@ -48,7 +48,8 @@ export default {
value: Boolean, value: Boolean,
timerSet: Boolean, timerSet: Boolean,
timerTime: Number, timerTime: Number,
remaining: Number remaining: Number,
currentChapter: Object
}, },
data() { data() {
return { return {
@ -56,36 +57,45 @@ export default {
sleepTimes: [ sleepTimes: [
{ {
seconds: 60 * 5, seconds: 60 * 5,
text: '5 minutes' text: '5 minutes',
timerType: this.$constants.SleepTimerTypes.COUNTDOWN
}, },
{ {
seconds: 60 * 15, seconds: 60 * 15,
text: '15 minutes' text: '15 minutes',
timerType: this.$constants.SleepTimerTypes.COUNTDOWN
}, },
{ {
seconds: 60 * 20, seconds: 60 * 20,
text: '20 minutes' text: '20 minutes',
timerType: this.$constants.SleepTimerTypes.COUNTDOWN
}, },
{ {
seconds: 60 * 30, seconds: 60 * 30,
text: '30 minutes' text: '30 minutes',
timerType: this.$constants.SleepTimerTypes.COUNTDOWN
}, },
{ {
seconds: 60 * 45, seconds: 60 * 45,
text: '45 minutes' text: '45 minutes',
timerType: this.$constants.SleepTimerTypes.COUNTDOWN
}, },
{ {
seconds: 60 * 60, seconds: 60 * 60,
text: '60 minutes' text: '60 minutes',
timerType: this.$constants.SleepTimerTypes.COUNTDOWN
}, },
{ {
seconds: 60 * 90, seconds: 60 * 90,
text: '90 minutes' text: '90 minutes',
timerType: this.$constants.SleepTimerTypes.COUNTDOWN
}, },
{ {
seconds: 60 * 120, seconds: 60 * 120,
text: '2 hours' text: '2 hours',
} timerType: this.$constants.SleepTimerTypes.COUNTDOWN
},
{ seconds: -1, text: 'End of chapter', timerType: this.$constants.SleepTimerTypes.CHAPTER }
] ]
} }
}, },
@ -115,8 +125,8 @@ export default {
const timeInSeconds = Math.round(Number(this.customTime) * 60) const timeInSeconds = Math.round(Number(this.customTime) * 60)
this.setTime(timeInSeconds) this.setTime(timeInSeconds)
}, },
setTime(seconds) { setTime(time) {
this.$emit('set', seconds) this.$emit('set', time)
}, },
increment(amount) { increment(amount) {
this.$emit('increment', amount) this.$emit('increment', amount)

View file

@ -72,6 +72,7 @@ export default {
type: Array, type: Array,
default: () => [] default: () => []
}, },
currentChapter: Object,
bookmarks: { bookmarks: {
type: Array, type: Array,
default: () => [] default: () => []
@ -135,9 +136,6 @@ export default {
if (!duration) return 0 if (!duration) return 0
return Math.round((100 * time) / duration) return Math.round((100 * time) / duration)
}, },
currentChapter() {
return this.chapters.find((chapter) => chapter.start <= this.currentTime && this.currentTime < chapter.end)
},
currentChapterName() { currentChapterName() {
return this.currentChapter ? this.currentChapter.title : '' return this.currentChapter ? this.currentChapter.title : ''
}, },