mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-05-31 12:15:49 -04:00
WIP: Add adjustable skip amount (#3113)
* Add playback settings string to en-us * Add playback settings UI for jump forwards and jump backwards * Remove jump forwards and jump backwards settings * Remove jump forwards and jump backwards en-us strings * Update player UI to include player settings button * Add label view player settings string * Add PlayerSettingsModal component Includes a toggle switch for enabling/disabling the chapter track feature. * Add player settings modal component to MediaPlayerContainer * Handle useChapterTrack changes in PlayerUI * Add jump forwards and jump backwards settings to user store * Add jump forwards and jump backwards label strings * Add jump forwards and jump backwards settings to PlayerSettingsModal * Update jump forwards and jump backwards to handle user state values in PlayerHandler * Update jump backwards icon in PlayerPlaybackControls * Add playback settings string to en-us * Add playback settings UI for jump forwards and jump backwards * Remove jump forwards and jump backwards settings * Remove jump forwards and jump backwards en-us strings * Update player UI to include player settings button * Add label view player settings string * Add PlayerSettingsModal component Includes a toggle switch for enabling/disabling the chapter track feature. * Add player settings modal component to MediaPlayerContainer * Handle useChapterTrack changes in PlayerUI * Add jump forwards and jump backwards settings to user store * Add jump forwards and jump backwards label strings * Add jump forwards and jump backwards settings to PlayerSettingsModal * Update jump forwards and jump backwards to handle user state values in PlayerHandler * Update jump backwards icon in PlayerPlaybackControls * Add jump amounts to playback controls tooltips * Fix merge issues and add new Material Symbols to player ui * Alphabetize strings in en-us.json * Update dropdown component with SelectInput to support menu overflowing modal * Update localization for player settings * Update en-us strings order --------- Co-authored-by: advplyr <advplyr@protonmail.com>
This commit is contained in:
parent
b6875a44cf
commit
43b7ccd61a
@ -51,6 +51,7 @@
|
|||||||
@showBookmarks="showBookmarks"
|
@showBookmarks="showBookmarks"
|
||||||
@showSleepTimer="showSleepTimerModal = true"
|
@showSleepTimer="showSleepTimerModal = true"
|
||||||
@showPlayerQueueItems="showPlayerQueueItemsModal = true"
|
@showPlayerQueueItems="showPlayerQueueItemsModal = true"
|
||||||
|
@showPlayerSettings="showPlayerSettingsModal = true"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<modals-bookmarks-modal v-model="showBookmarksModal" :bookmarks="bookmarks" :current-time="bookmarkCurrentTime" :library-item-id="libraryItemId" @select="selectBookmark" />
|
<modals-bookmarks-modal v-model="showBookmarksModal" :bookmarks="bookmarks" :current-time="bookmarkCurrentTime" :library-item-id="libraryItemId" @select="selectBookmark" />
|
||||||
@ -58,6 +59,8 @@
|
|||||||
<modals-sleep-timer-modal v-model="showSleepTimerModal" :timer-set="sleepTimerSet" :timer-time="sleepTimerTime" :remaining="sleepTimerRemaining" @set="setSleepTimer" @cancel="cancelSleepTimer" @increment="incrementSleepTimer" @decrement="decrementSleepTimer" />
|
<modals-sleep-timer-modal v-model="showSleepTimerModal" :timer-set="sleepTimerSet" :timer-time="sleepTimerTime" :remaining="sleepTimerRemaining" @set="setSleepTimer" @cancel="cancelSleepTimer" @increment="incrementSleepTimer" @decrement="decrementSleepTimer" />
|
||||||
|
|
||||||
<modals-player-queue-items-modal v-model="showPlayerQueueItemsModal" :library-item-id="libraryItemId" />
|
<modals-player-queue-items-modal v-model="showPlayerQueueItemsModal" :library-item-id="libraryItemId" />
|
||||||
|
|
||||||
|
<modals-player-settings-modal v-model="showPlayerSettingsModal" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -76,6 +79,7 @@ export default {
|
|||||||
currentTime: 0,
|
currentTime: 0,
|
||||||
showSleepTimerModal: false,
|
showSleepTimerModal: false,
|
||||||
showPlayerQueueItemsModal: false,
|
showPlayerQueueItemsModal: false,
|
||||||
|
showPlayerSettingsModal: false,
|
||||||
sleepTimerSet: false,
|
sleepTimerSet: false,
|
||||||
sleepTimerTime: 0,
|
sleepTimerTime: 0,
|
||||||
sleepTimerRemaining: 0,
|
sleepTimerRemaining: 0,
|
||||||
|
70
client/components/modals/PlayerSettingsModal.vue
Normal file
70
client/components/modals/PlayerSettingsModal.vue
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<template>
|
||||||
|
<modals-modal v-model="show" name="player-settings" :width="500" :height="'unset'">
|
||||||
|
<div ref="container" class="w-full rounded-lg bg-bg box-shadow-md overflow-y-auto overflow-x-hidden p-4" style="max-height: 80vh; min-height: 40vh">
|
||||||
|
<h3 class="text-xl font-semibold mb-8">{{ $strings.HeaderPlayerSettings }}</h3>
|
||||||
|
<div class="flex items-center mb-4">
|
||||||
|
<ui-toggle-switch v-model="useChapterTrack" @input="setUseChapterTrack" />
|
||||||
|
<div class="pl-4">
|
||||||
|
<span>{{ $strings.LabelUseChapterTrack }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center mb-4">
|
||||||
|
<ui-select-input v-model="jumpForwardAmount" :label="$strings.LabelJumpForwardAmount" menuMaxHeight="250px" :items="jumpValues" @input="setJumpForwardAmount" />
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<ui-select-input v-model="jumpBackwardAmount" :label="$strings.LabelJumpBackwardAmount" menuMaxHeight="250px" :items="jumpValues" @input="setJumpBackwardAmount" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</modals-modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
value: Boolean
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
useChapterTrack: false,
|
||||||
|
jumpValues: [
|
||||||
|
{ text: this.$getString('LabelJumpAmountSeconds', ['10']), value: 10 },
|
||||||
|
{ text: this.$getString('LabelJumpAmountSeconds', ['15']), value: 15 },
|
||||||
|
{ text: this.$getString('LabelJumpAmountSeconds', ['30']), value: 30 },
|
||||||
|
{ text: this.$getString('LabelJumpAmountSeconds', ['60']), value: 60 },
|
||||||
|
{ text: this.$getString('LabelJumpAmountMinutes', ['2']), value: 120 },
|
||||||
|
{ text: this.$getString('LabelJumpAmountMinutes', ['5']), value: 300 }
|
||||||
|
],
|
||||||
|
jumpForwardAmount: 10,
|
||||||
|
jumpBackwardAmount: 10
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
show: {
|
||||||
|
get() {
|
||||||
|
return this.value
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
this.$emit('input', val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setUseChapterTrack() {
|
||||||
|
this.$store.dispatch('user/updateUserSettings', { useChapterTrack: this.useChapterTrack })
|
||||||
|
},
|
||||||
|
setJumpForwardAmount(val) {
|
||||||
|
this.jumpForwardAmount = val
|
||||||
|
this.$store.dispatch('user/updateUserSettings', { jumpForwardAmount: val })
|
||||||
|
},
|
||||||
|
setJumpBackwardAmount(val) {
|
||||||
|
this.jumpBackwardAmount = val
|
||||||
|
this.$store.dispatch('user/updateUserSettings', { jumpBackwardAmount: val })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.useChapterTrack = this.$store.getters['user/getUserSetting']('useChapterTrack')
|
||||||
|
this.jumpForwardAmount = this.$store.getters['user/getUserSetting']('jumpForwardAmount')
|
||||||
|
this.jumpBackwardAmount = this.$store.getters['user/getUserSetting']('jumpBackwardAmount')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
@ -7,17 +7,17 @@
|
|||||||
<span class="material-symbols text-2xl sm:text-3xl">first_page</span>
|
<span class="material-symbols text-2xl sm:text-3xl">first_page</span>
|
||||||
</button>
|
</button>
|
||||||
</ui-tooltip>
|
</ui-tooltip>
|
||||||
<ui-tooltip direction="top" :text="$strings.ButtonJumpBackward">
|
<ui-tooltip direction="top" :text="jumpBackwardText">
|
||||||
<button :aria-label="$strings.ButtonJumpBackward" class="text-gray-300" @mousedown.prevent @mouseup.prevent @click.stop="jumpBackward">
|
<button :aria-label="jumpForwardText" class="text-gray-300" @mousedown.prevent @mouseup.prevent @click.stop="jumpBackward">
|
||||||
<span class="material-symbols text-2xl sm:text-3xl">replay_10</span>
|
<span class="material-symbols text-2xl sm:text-3xl">replay</span>
|
||||||
</button>
|
</button>
|
||||||
</ui-tooltip>
|
</ui-tooltip>
|
||||||
<button :aria-label="paused ? $strings.ButtonPlay : $strings.ButtonPause" class="p-2 shadow-sm bg-accent flex items-center justify-center rounded-full text-primary mx-4 lg:mx-8" :class="seekLoading ? 'animate-spin' : ''" @mousedown.prevent @mouseup.prevent @click.stop="playPause">
|
<button :aria-label="paused ? $strings.ButtonPlay : $strings.ButtonPause" class="p-2 shadow-sm bg-accent flex items-center justify-center rounded-full text-primary mx-4 lg:mx-8" :class="seekLoading ? 'animate-spin' : ''" @mousedown.prevent @mouseup.prevent @click.stop="playPause">
|
||||||
<span class="material-symbols fill text-2xl">{{ seekLoading ? 'autorenew' : paused ? 'play_arrow' : 'pause' }}</span>
|
<span class="material-symbols fill text-2xl">{{ seekLoading ? 'autorenew' : paused ? 'play_arrow' : 'pause' }}</span>
|
||||||
</button>
|
</button>
|
||||||
<ui-tooltip direction="top" :text="$strings.ButtonJumpForward">
|
<ui-tooltip direction="top" :text="jumpForwardText">
|
||||||
<button :aria-label="$strings.ButtonJumpForward" class="text-gray-300" @mousedown.prevent @mouseup.prevent @click.stop="jumpForward">
|
<button :aria-label="jumpForwardText" class="text-gray-300" @mousedown.prevent @mouseup.prevent @click.stop="jumpForward">
|
||||||
<span class="material-symbols text-2xl sm:text-3xl">forward_10</span>
|
<span class="material-symbols text-2xl sm:text-3xl">forward_media</span>
|
||||||
</button>
|
</button>
|
||||||
</ui-tooltip>
|
</ui-tooltip>
|
||||||
<ui-tooltip direction="top" :text="$strings.ButtonNextChapter" class="ml-4 lg:ml-8">
|
<ui-tooltip direction="top" :text="$strings.ButtonNextChapter" class="ml-4 lg:ml-8">
|
||||||
@ -56,6 +56,12 @@ export default {
|
|||||||
set(val) {
|
set(val) {
|
||||||
this.$emit('update:playbackRate', val)
|
this.$emit('update:playbackRate', val)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
jumpForwardText() {
|
||||||
|
return this.getJumpText('jumpForwardAmount', this.$strings.ButtonJumpForward)
|
||||||
|
},
|
||||||
|
jumpBackwardText() {
|
||||||
|
return this.getJumpText('jumpBackwardAmount', this.$strings.ButtonJumpBackward)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -83,8 +89,22 @@ export default {
|
|||||||
this.$store.dispatch('user/updateUserSettings', { playbackRate }).catch((err) => {
|
this.$store.dispatch('user/updateUserSettings', { playbackRate }).catch((err) => {
|
||||||
console.error('Failed to update settings', err)
|
console.error('Failed to update settings', err)
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
getJumpText(setting, prefix) {
|
||||||
|
const amount = this.$store.getters['user/getUserSetting'](setting)
|
||||||
|
if (!amount) return prefix
|
||||||
|
|
||||||
|
let formattedTime = ''
|
||||||
|
if (amount <= 60) {
|
||||||
|
formattedTime = this.$getString('LabelJumpAmountSeconds', [amount])
|
||||||
|
} else {
|
||||||
|
const minutes = Math.floor(amount / 60)
|
||||||
|
formattedTime = this.$getString('LabelJumpAmountMinutes', [minutes])
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${prefix} - ${formattedTime}`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {}
|
mounted() {}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -36,9 +36,9 @@
|
|||||||
</button>
|
</button>
|
||||||
</ui-tooltip>
|
</ui-tooltip>
|
||||||
|
|
||||||
<ui-tooltip v-if="chapters.length" direction="top" :text="useChapterTrack ? $strings.LabelUseFullTrack : $strings.LabelUseChapterTrack">
|
<ui-tooltip direction="top" :text="$strings.LabelViewPlayerSettings">
|
||||||
<button :aria-label="useChapterTrack ? $strings.LabelUseFullTrack : $strings.LabelUseChapterTrack" class="text-gray-300 mx-1 lg:mx-2 hover:text-white" @mousedown.prevent @mouseup.prevent @click.stop="setUseChapterTrack">
|
<button :aria-label="$strings.LabelViewPlayerSettings" class="outline-none text-gray-300 mx-1 lg:mx-2 hover:text-white" @mousedown.prevent @mouseup.prevent @click.stop="$emit('showPlayerSettings')">
|
||||||
<span class="material-symbols text-2xl sm:text-3xl transform transition-transform" :class="useChapterTrack ? 'rotate-180' : ''">timelapse</span>
|
<span class="material-symbols text-2xl sm:text-2.5xl">settings_slow_motion</span>
|
||||||
</button>
|
</button>
|
||||||
</ui-tooltip>
|
</ui-tooltip>
|
||||||
</div>
|
</div>
|
||||||
@ -90,13 +90,16 @@ export default {
|
|||||||
seekLoading: false,
|
seekLoading: false,
|
||||||
showChaptersModal: false,
|
showChaptersModal: false,
|
||||||
currentTime: 0,
|
currentTime: 0,
|
||||||
duration: 0,
|
duration: 0
|
||||||
useChapterTrack: false
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
playbackRate() {
|
playbackRate() {
|
||||||
this.updateTimestamp()
|
this.updateTimestamp()
|
||||||
|
},
|
||||||
|
useChapterTrack() {
|
||||||
|
if (this.$refs.trackbar) this.$refs.trackbar.setUseChapterTrack(this.useChapterTrack)
|
||||||
|
this.updateTimestamp()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -162,6 +165,10 @@ export default {
|
|||||||
},
|
},
|
||||||
playerQueueItems() {
|
playerQueueItems() {
|
||||||
return this.$store.state.playerQueueItems || []
|
return this.$store.state.playerQueueItems || []
|
||||||
|
},
|
||||||
|
useChapterTrack() {
|
||||||
|
const _useChapterTrack = this.$store.getters['user/getUserSetting']('useChapterTrack') || false
|
||||||
|
return this.chapters.length ? _useChapterTrack : false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -310,9 +317,6 @@ export default {
|
|||||||
init() {
|
init() {
|
||||||
this.playbackRate = this.$store.getters['user/getUserSetting']('playbackRate') || 1
|
this.playbackRate = this.$store.getters['user/getUserSetting']('playbackRate') || 1
|
||||||
|
|
||||||
const _useChapterTrack = this.$store.getters['user/getUserSetting']('useChapterTrack') || false
|
|
||||||
this.useChapterTrack = this.chapters.length ? _useChapterTrack : false
|
|
||||||
|
|
||||||
if (this.$refs.trackbar) this.$refs.trackbar.setUseChapterTrack(this.useChapterTrack)
|
if (this.$refs.trackbar) this.$refs.trackbar.setUseChapterTrack(this.useChapterTrack)
|
||||||
this.setPlaybackRate(this.playbackRate)
|
this.setPlaybackRate(this.playbackRate)
|
||||||
},
|
},
|
||||||
|
151
client/components/ui/SelectInput.vue
Normal file
151
client/components/ui/SelectInput.vue
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
<template>
|
||||||
|
<div class="relative w-full">
|
||||||
|
<p v-if="label" class="text-sm font-semibold px-1" :class="disabled ? 'text-gray-300' : ''">{{ label }}</p>
|
||||||
|
<button ref="buttonWrapper" type="button" :aria-label="longLabel" :disabled="disabled" class="relative w-full border rounded shadow-sm pl-3 pr-8 py-2 text-left sm:text-sm" :class="buttonClass" aria-haspopup="listbox" aria-expanded="true" @click.stop.prevent="clickShowMenu">
|
||||||
|
<span class="flex items-center">
|
||||||
|
<span class="block truncate font-sans" :class="{ 'font-semibold': selectedSubtext, 'text-sm': small }">{{ selectedText }}</span>
|
||||||
|
<span v-if="selectedSubtext">: </span>
|
||||||
|
<span v-if="selectedSubtext" class="font-normal block truncate font-sans text-sm text-gray-400">{{ selectedSubtext }}</span>
|
||||||
|
</span>
|
||||||
|
<span class="ml-3 absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
|
||||||
|
<span class="material-symbols text-2xl">expand_more</span>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<transition name="menu">
|
||||||
|
<ul ref="menu" v-show="showMenu" class="absolute z-60 -mt-px w-full bg-primary border border-black-200 shadow-lg rounded-md py-1 ring-1 ring-black ring-opacity-5 overflow-auto sm:text-sm" tabindex="-1" role="listbox" :style="{ maxHeight: menuMaxHeight }" v-click-outside="clickOutsideObj">
|
||||||
|
<template v-for="item in itemsToShow">
|
||||||
|
<li :key="item.value" class="text-gray-100 relative py-2 cursor-pointer hover:bg-black-400" :id="'listbox-option-' + item.value" role="option" tabindex="0" @keyup.enter="clickedOption(item.value)" @click.stop.prevent="clickedOption(item.value)">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<span class="ml-3 block truncate font-sans text-sm" :class="{ 'font-semibold': item.subtext }">{{ item.text }}</span>
|
||||||
|
<span v-if="item.subtext">: </span>
|
||||||
|
<span v-if="item.subtext" class="font-normal block truncate font-sans text-sm text-gray-400">{{ item.subtext }}</span>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</template>
|
||||||
|
</ul>
|
||||||
|
</transition>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
value: [String, Number],
|
||||||
|
label: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
items: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
disabled: Boolean,
|
||||||
|
small: Boolean,
|
||||||
|
menuMaxHeight: {
|
||||||
|
type: String,
|
||||||
|
default: '224px'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
clickOutsideObj: {
|
||||||
|
handler: this.clickedOutside,
|
||||||
|
events: ['click'],
|
||||||
|
isActive: true
|
||||||
|
},
|
||||||
|
menu: null,
|
||||||
|
showMenu: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
selected: {
|
||||||
|
get() {
|
||||||
|
return this.value
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
this.$emit('input', val)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
itemsToShow() {
|
||||||
|
return this.items.map((i) => {
|
||||||
|
if (typeof i === 'string' || typeof i === 'number') {
|
||||||
|
return {
|
||||||
|
text: i,
|
||||||
|
value: i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return i
|
||||||
|
})
|
||||||
|
},
|
||||||
|
selectedItem() {
|
||||||
|
return this.itemsToShow.find((i) => i.value === this.selected)
|
||||||
|
},
|
||||||
|
selectedText() {
|
||||||
|
return this.selectedItem ? this.selectedItem.text : ''
|
||||||
|
},
|
||||||
|
selectedSubtext() {
|
||||||
|
return this.selectedItem ? this.selectedItem.subtext : ''
|
||||||
|
},
|
||||||
|
buttonClass() {
|
||||||
|
var classes = []
|
||||||
|
if (this.small) classes.push('h-9')
|
||||||
|
else classes.push('h-10')
|
||||||
|
|
||||||
|
if (this.disabled) classes.push('cursor-not-allowed border-gray-600 bg-primary bg-opacity-70 border-opacity-70 text-gray-400')
|
||||||
|
else classes.push('cursor-pointer border-gray-600 bg-primary text-gray-100')
|
||||||
|
|
||||||
|
return classes.join(' ')
|
||||||
|
},
|
||||||
|
longLabel() {
|
||||||
|
let result = ''
|
||||||
|
if (this.label) result += this.label + ': '
|
||||||
|
if (this.selectedText) result += this.selectedText
|
||||||
|
if (this.selectedSubtext) result += ' ' + this.selectedSubtext
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
recalcMenuPos() {
|
||||||
|
if (!this.menu || !this.$refs.buttonWrapper) return
|
||||||
|
const boundingBox = this.$refs.buttonWrapper.getBoundingClientRect()
|
||||||
|
this.menu.style.top = boundingBox.y + boundingBox.height - 4 + 'px'
|
||||||
|
this.menu.style.left = boundingBox.x + 'px'
|
||||||
|
this.menu.style.width = boundingBox.width + 'px'
|
||||||
|
},
|
||||||
|
unmountMountMenu() {
|
||||||
|
if (!this.$refs.menu || !this.$refs.buttonWrapper) return
|
||||||
|
this.menu = this.$refs.menu
|
||||||
|
this.menu.remove()
|
||||||
|
},
|
||||||
|
clickShowMenu() {
|
||||||
|
if (this.disabled) return
|
||||||
|
if (!this.showMenu) this.handleShowMenu()
|
||||||
|
else this.handleCloseMenu()
|
||||||
|
},
|
||||||
|
handleShowMenu() {
|
||||||
|
if (!this.menu) {
|
||||||
|
this.unmountMountMenu()
|
||||||
|
}
|
||||||
|
document.body.appendChild(this.menu)
|
||||||
|
this.recalcMenuPos()
|
||||||
|
this.showMenu = true
|
||||||
|
},
|
||||||
|
handleCloseMenu() {
|
||||||
|
this.showMenu = false
|
||||||
|
if (this.menu) this.menu.remove()
|
||||||
|
},
|
||||||
|
clickedOutside() {
|
||||||
|
this.handleCloseMenu()
|
||||||
|
},
|
||||||
|
clickedOption(itemValue) {
|
||||||
|
this.selected = itemValue
|
||||||
|
this.handleCloseMenu()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {},
|
||||||
|
beforeDestroy() {
|
||||||
|
if (this.menu) this.menu.remove()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
@ -51,6 +51,12 @@ export default class PlayerHandler {
|
|||||||
if (!this.episodeId) return null
|
if (!this.episodeId) return null
|
||||||
return this.libraryItem.media.episodes.find(ep => ep.id === this.episodeId)
|
return this.libraryItem.media.episodes.find(ep => ep.id === this.episodeId)
|
||||||
}
|
}
|
||||||
|
get jumpForwardAmount() {
|
||||||
|
return this.ctx.$store.getters['user/getUserSetting']('jumpForwardAmount')
|
||||||
|
}
|
||||||
|
get jumpBackwardAmount() {
|
||||||
|
return this.ctx.$store.getters['user/getUserSetting']('jumpBackwardAmount')
|
||||||
|
}
|
||||||
|
|
||||||
setSessionId(sessionId) {
|
setSessionId(sessionId) {
|
||||||
this.currentSessionId = sessionId
|
this.currentSessionId = sessionId
|
||||||
@ -381,13 +387,15 @@ export default class PlayerHandler {
|
|||||||
jumpBackward() {
|
jumpBackward() {
|
||||||
if (!this.player) return
|
if (!this.player) return
|
||||||
var currentTime = this.getCurrentTime()
|
var currentTime = this.getCurrentTime()
|
||||||
this.seek(Math.max(0, currentTime - 10))
|
const jumpAmount = this.jumpBackwardAmount
|
||||||
|
this.seek(Math.max(0, currentTime - jumpAmount))
|
||||||
}
|
}
|
||||||
|
|
||||||
jumpForward() {
|
jumpForward() {
|
||||||
if (!this.player) return
|
if (!this.player) return
|
||||||
var currentTime = this.getCurrentTime()
|
var currentTime = this.getCurrentTime()
|
||||||
this.seek(Math.min(currentTime + 10, this.getDuration()))
|
const jumpAmount = this.jumpForwardAmount
|
||||||
|
this.seek(Math.min(currentTime + jumpAmount, this.getDuration()))
|
||||||
}
|
}
|
||||||
|
|
||||||
setVolume(volume) {
|
setVolume(volume) {
|
||||||
|
@ -14,7 +14,9 @@ export const state = () => ({
|
|||||||
seriesSortDesc: false,
|
seriesSortDesc: false,
|
||||||
seriesFilterBy: 'all',
|
seriesFilterBy: 'all',
|
||||||
authorSortBy: 'name',
|
authorSortBy: 'name',
|
||||||
authorSortDesc: false
|
authorSortDesc: false,
|
||||||
|
jumpForwardAmount: 10,
|
||||||
|
jumpBackwardAmount: 10,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -155,6 +155,7 @@
|
|||||||
"HeaderPasswordAuthentication": "Password Authentication",
|
"HeaderPasswordAuthentication": "Password Authentication",
|
||||||
"HeaderPermissions": "Permissions",
|
"HeaderPermissions": "Permissions",
|
||||||
"HeaderPlayerQueue": "Player Queue",
|
"HeaderPlayerQueue": "Player Queue",
|
||||||
|
"HeaderPlayerSettings": "Player Settings",
|
||||||
"HeaderPlaylist": "Playlist",
|
"HeaderPlaylist": "Playlist",
|
||||||
"HeaderPlaylistItems": "Playlist Items",
|
"HeaderPlaylistItems": "Playlist Items",
|
||||||
"HeaderPodcastsToAdd": "Podcasts to Add",
|
"HeaderPodcastsToAdd": "Podcasts to Add",
|
||||||
@ -343,6 +344,10 @@
|
|||||||
"LabelIntervalEveryHour": "Every hour",
|
"LabelIntervalEveryHour": "Every hour",
|
||||||
"LabelInvert": "Invert",
|
"LabelInvert": "Invert",
|
||||||
"LabelItem": "Item",
|
"LabelItem": "Item",
|
||||||
|
"LabelJumpAmountMinutes": "{0} minutes",
|
||||||
|
"LabelJumpAmountSeconds": "{0} seconds",
|
||||||
|
"LabelJumpBackwardAmount": "Jump backward amount",
|
||||||
|
"LabelJumpForwardAmount": "Jump forward amount",
|
||||||
"LabelLanguage": "Language",
|
"LabelLanguage": "Language",
|
||||||
"LabelLanguageDefaultServer": "Default Server Language",
|
"LabelLanguageDefaultServer": "Default Server Language",
|
||||||
"LabelLanguages": "Languages",
|
"LabelLanguages": "Languages",
|
||||||
@ -598,6 +603,7 @@
|
|||||||
"LabelVersion": "Version",
|
"LabelVersion": "Version",
|
||||||
"LabelViewBookmarks": "View bookmarks",
|
"LabelViewBookmarks": "View bookmarks",
|
||||||
"LabelViewChapters": "View chapters",
|
"LabelViewChapters": "View chapters",
|
||||||
|
"LabelViewPlayerSettings": "View player settings",
|
||||||
"LabelViewQueue": "View player queue",
|
"LabelViewQueue": "View player queue",
|
||||||
"LabelVolume": "Volume",
|
"LabelVolume": "Volume",
|
||||||
"LabelWeekdaysToRun": "Weekdays to run",
|
"LabelWeekdaysToRun": "Weekdays to run",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user