mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-01-17 00:08:55 +01:00
Add:Click timestamp in listening sessions table to open playback at timestamp #798, add confirm prompt
This commit is contained in:
parent
f1421f351b
commit
bcc2f847f9
106
client/components/prompt/Confirm.vue
Normal file
106
client/components/prompt/Confirm.vue
Normal 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>
|
@ -15,6 +15,7 @@
|
|||||||
<modals-podcast-edit-episode />
|
<modals-podcast-edit-episode />
|
||||||
<modals-podcast-view-episode />
|
<modals-podcast-view-episode />
|
||||||
<modals-authors-edit-modal />
|
<modals-authors-edit-modal />
|
||||||
|
<prompt-confirm />
|
||||||
<readers-reader />
|
<readers-reader />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
<p class="text-xs font-mono">{{ $elapsedPretty(session.timeListening) }}</p>
|
<p class="text-xs font-mono">{{ $elapsedPretty(session.timeListening) }}</p>
|
||||||
</td>
|
</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>
|
<p class="text-xs font-mono">{{ $secondsToTimestamp(session.currentTime) }}</p>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center hidden sm:table-cell">
|
<td class="text-center hidden sm:table-cell">
|
||||||
@ -89,7 +89,8 @@ export default {
|
|||||||
total: 0,
|
total: 0,
|
||||||
currentPage: 0,
|
currentPage: 0,
|
||||||
userFilter: null,
|
userFilter: null,
|
||||||
selectedUser: ''
|
selectedUser: '',
|
||||||
|
processingGoToTimestamp: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -110,6 +111,41 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
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() {
|
updateUserFilter() {
|
||||||
this.loadSessions(0)
|
this.loadSessions(0)
|
||||||
},
|
},
|
||||||
|
@ -6,6 +6,8 @@ export const state = () => ({
|
|||||||
showEditCollectionModal: false,
|
showEditCollectionModal: false,
|
||||||
showEditPodcastEpisode: false,
|
showEditPodcastEpisode: false,
|
||||||
showViewPodcastEpisodeModal: false,
|
showViewPodcastEpisodeModal: false,
|
||||||
|
showConfirmPrompt: false,
|
||||||
|
confirmPromptOptions: null,
|
||||||
showEditAuthorModal: false,
|
showEditAuthorModal: false,
|
||||||
selectedEpisode: null,
|
selectedEpisode: null,
|
||||||
selectedCollection: null,
|
selectedCollection: null,
|
||||||
@ -69,6 +71,13 @@ export const mutations = {
|
|||||||
setShowViewPodcastEpisodeModal(state, val) {
|
setShowViewPodcastEpisodeModal(state, val) {
|
||||||
state.showViewPodcastEpisodeModal = val
|
state.showViewPodcastEpisodeModal = val
|
||||||
},
|
},
|
||||||
|
setShowConfirmPrompt(state, val) {
|
||||||
|
state.showConfirmPrompt = val
|
||||||
|
},
|
||||||
|
setConfirmPrompt(state, options) {
|
||||||
|
state.confirmPromptOptions = options
|
||||||
|
state.showConfirmPrompt = true
|
||||||
|
},
|
||||||
setEditCollection(state, collection) {
|
setEditCollection(state, collection) {
|
||||||
state.selectedCollection = collection
|
state.selectedCollection = collection
|
||||||
state.showEditCollectionModal = true
|
state.showEditCollectionModal = true
|
||||||
|
Loading…
Reference in New Issue
Block a user