Add:Click timestamp in listening sessions table to open playback at timestamp #798, add confirm prompt

This commit is contained in:
advplyr 2022-07-30 11:36:04 -05:00
parent f1421f351b
commit bcc2f847f9
4 changed files with 155 additions and 3 deletions

View File

@ -0,0 +1,106 @@
<template>
<div ref="wrapper" class="modal modal-bg w-full h-full fixed top-0 left-0 bg-primary bg-opacity-75 flex items-center justify-center z-50 opacity-0">
<div class="absolute top-0 left-0 right-0 w-full h-36 bg-gradient-to-t from-transparent via-black-500 to-black-700 opacity-90 pointer-events-none" />
<div ref="content" style="min-width: 400px; min-height: 200px" class="relative text-white" :style="{ height: modalHeight, width: modalWidth }" v-click-outside="clickedOutside">
<div class="px-4 w-full text-sm py-6 rounded-lg bg-bg shadow-lg border border-black-300">
<p class="text-base mb-8 mt-2 px-1">{{ message }}</p>
<div class="flex px-1 items-center">
<ui-btn v-if="isYesNo" color="primary" @click="nevermind">Cancel</ui-btn>
<div class="flex-grow" />
<ui-btn v-if="isYesNo" color="success" @click="confirm">Yes</ui-btn>
<ui-btn v-else color="primary" @click="confirm">Ok</ui-btn>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {},
data() {
return {
el: null,
content: null
}
},
watch: {
show(newVal) {
if (newVal) {
this.setShow()
} else {
this.setHide()
}
}
},
computed: {
show: {
get() {
return this.$store.state.globals.showConfirmPrompt
},
set(val) {
this.$store.commit('globals/setShowConfirmPrompt', val)
}
},
confirmPromptOptions() {
return this.$store.state.globals.confirmPromptOptions || {}
},
message() {
return this.confirmPromptOptions.message || ''
},
callback() {
return this.confirmPromptOptions.callback
},
type() {
return this.confirmPromptOptions.type || 'ok'
},
persistent() {
return !!this.confirmPromptOptions.persistent
},
isYesNo() {
return this.type === 'yesNo'
},
modalHeight() {
return 'unset'
},
modalWidth() {
return '500px'
}
},
methods: {
clickedOutside() {
if (this.persistent) return
if (this.callback) this.callback(false)
this.show = false
},
nevermind() {
if (this.callback) this.callback(false)
this.show = false
},
confirm() {
if (this.callback) this.callback(true)
this.show = false
},
setShow() {
document.body.appendChild(this.el)
setTimeout(() => {
this.content.style.transform = 'scale(1)'
}, 10)
document.documentElement.classList.add('modal-open')
},
setHide() {
this.content.style.transform = 'scale(0)'
this.el.remove()
document.documentElement.classList.remove('modal-open')
}
},
mounted() {
this.el = this.$refs.wrapper
this.content = this.$refs.content
this.content.style.transform = 'scale(0)'
this.content.style.transition = 'transform 0.25s cubic-bezier(0.16, 1, 0.3, 1)'
this.el.style.opacity = 1
this.el.remove()
}
}
</script>

View File

@ -15,6 +15,7 @@
<modals-podcast-edit-episode />
<modals-podcast-view-episode />
<modals-authors-edit-modal />
<prompt-confirm />
<readers-reader />
</div>
</template>

View File

@ -39,7 +39,7 @@
<td class="text-center">
<p class="text-xs font-mono">{{ $elapsedPretty(session.timeListening) }}</p>
</td>
<td class="text-center">
<td class="text-center hover:underline" @click.stop="clickCurrentTime(session)">
<p class="text-xs font-mono">{{ $secondsToTimestamp(session.currentTime) }}</p>
</td>
<td class="text-center hidden sm:table-cell">
@ -57,7 +57,7 @@
</div>
<p v-else class="text-white text-opacity-50">No sessions yet...</p>
</div>
<modals-listening-session-modal v-model="showSessionModal" :session="selectedSession" />
</div>
</template>
@ -89,7 +89,8 @@ export default {
total: 0,
currentPage: 0,
userFilter: null,
selectedUser: ''
selectedUser: '',
processingGoToTimestamp: false
}
},
computed: {
@ -110,6 +111,41 @@ export default {
}
},
methods: {
async clickCurrentTime(session) {
if (this.processingGoToTimestamp) return
this.processingGoToTimestamp = true
const libraryItem = await this.$axios.$get(`/api/items/${session.libraryItemId}`).catch((error) => {
console.error('Failed to get library item', error)
return null
})
if (!libraryItem) {
this.$toast.error('Failed to get library item')
this.processingGoToTimestamp = false
return
}
if (session.episodeId && !libraryItem.media.episodes.find((ep) => ep.id === session.episodeId)) {
this.$toast.error('Failed to get podcast episode')
this.processingGoToTimestamp = false
return
}
const payload = {
message: `Start playback for "${session.displayTitle}" at ${this.$secondsToTimestamp(session.currentTime)}?`,
callback: (confirmed) => {
if (confirmed) {
this.$eventBus.$emit('play-item', {
libraryItemId: libraryItem.id,
episodeId: session.episodeId || null,
startTime: session.currentTime
})
}
this.processingGoToTimestamp = false
},
type: 'yesNo'
}
this.$store.commit('globals/setConfirmPrompt', payload)
},
updateUserFilter() {
this.loadSessions(0)
},

View File

@ -6,6 +6,8 @@ export const state = () => ({
showEditCollectionModal: false,
showEditPodcastEpisode: false,
showViewPodcastEpisodeModal: false,
showConfirmPrompt: false,
confirmPromptOptions: null,
showEditAuthorModal: false,
selectedEpisode: null,
selectedCollection: null,
@ -69,6 +71,13 @@ export const mutations = {
setShowViewPodcastEpisodeModal(state, val) {
state.showViewPodcastEpisodeModal = val
},
setShowConfirmPrompt(state, val) {
state.showConfirmPrompt = val
},
setConfirmPrompt(state, options) {
state.confirmPromptOptions = options
state.showConfirmPrompt = true
},
setEditCollection(state, collection) {
state.selectedCollection = collection
state.showEditCollectionModal = true