mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2025-09-29 17:51:19 +02:00
Allow clicking on elapsedTime to adjust chapter start
This commit is contained in:
parent
c41bdb951c
commit
9da0be6d36
@ -123,9 +123,9 @@
|
|||||||
<span v-else class="material-symbols text-base">play_arrow</span>
|
<span v-else class="material-symbols text-base">play_arrow</span>
|
||||||
</button>
|
</button>
|
||||||
</ui-tooltip>
|
</ui-tooltip>
|
||||||
|
<ui-tooltip v-if="selectedChapterId === chapter.id && (isPlayingChapter || isLoadingChapter)" :text="$strings.TooltipAdjustChapterStart" direction="bottom">
|
||||||
<!-- Elapsed time display -->
|
<div class="ml-2 text-xs text-gray-300 font-mono min-w-10 cursor-pointer hover:text-white transition-colors duration-150" @click="adjustChapterStartTime(chapter)">{{ elapsedTime }}s</div>
|
||||||
<div v-if="selectedChapterId === chapter.id && (isPlayingChapter || isLoadingChapter)" class="ml-2 text-xs text-gray-300 font-mono min-w-10">{{ elapsedTime }}s</div>
|
</ui-tooltip>
|
||||||
<ui-tooltip v-if="chapter.error" :text="chapter.error" direction="left">
|
<ui-tooltip v-if="chapter.error" :text="chapter.error" direction="left">
|
||||||
<button class="w-7 h-7 rounded-full flex items-center justify-center text-error">
|
<button class="w-7 h-7 rounded-full flex items-center justify-center text-error">
|
||||||
<span class="material-symbols text-lg">error_outline</span>
|
<span class="material-symbols text-lg">error_outline</span>
|
||||||
@ -456,30 +456,30 @@ export default {
|
|||||||
this.checkChapters()
|
this.checkChapters()
|
||||||
},
|
},
|
||||||
incrementChapterTime(chapter, amount) {
|
incrementChapterTime(chapter, amount) {
|
||||||
// Don't allow incrementing first chapter below 0
|
|
||||||
if (chapter.id === 0 && chapter.start + amount < 0) {
|
if (chapter.id === 0 && chapter.start + amount < 0) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't allow incrementing beyond media duration
|
|
||||||
if (chapter.start + amount >= this.mediaDuration) {
|
if (chapter.start + amount >= this.mediaDuration) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.lockedChapters.has(chapter.id)) {
|
|
||||||
this.$toast.warning(this.$strings.ToastChapterLocked)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
chapter.start = Math.max(0, chapter.start + amount)
|
chapter.start = Math.max(0, chapter.start + amount)
|
||||||
this.checkChapters()
|
this.checkChapters()
|
||||||
},
|
},
|
||||||
|
adjustChapterStartTime(chapter) {
|
||||||
|
const newStartTime = chapter.start + this.elapsedTime
|
||||||
|
chapter.start = newStartTime
|
||||||
|
this.checkChapters()
|
||||||
|
this.$toast.success(this.$strings.ToastChapterStartTimeAdjusted.replace('{0}', this.elapsedTime))
|
||||||
|
|
||||||
|
this.destroyAudioEl()
|
||||||
|
},
|
||||||
startElapsedTimeTracking() {
|
startElapsedTimeTracking() {
|
||||||
this.elapsedTime = 0
|
this.elapsedTime = 0
|
||||||
this.playStartTime = Date.now()
|
this.playStartTime = Date.now()
|
||||||
this.elapsedTimeInterval = setInterval(() => {
|
this.elapsedTimeInterval = setInterval(() => {
|
||||||
this.elapsedTime = Math.floor((Date.now() - this.playStartTime) / 1000)
|
this.elapsedTime = Math.floor((Date.now() - this.playStartTime) / 1000)
|
||||||
}, 100) // Update every 100ms for smooth display
|
}, 100)
|
||||||
},
|
},
|
||||||
stopElapsedTimeTracking() {
|
stopElapsedTimeTracking() {
|
||||||
if (this.elapsedTimeInterval) {
|
if (this.elapsedTimeInterval) {
|
||||||
@ -492,12 +492,9 @@ export default {
|
|||||||
toggleChapterLock(chapter, event) {
|
toggleChapterLock(chapter, event) {
|
||||||
const chapterId = chapter.id
|
const chapterId = chapter.id
|
||||||
|
|
||||||
// Handle shift-click for range selection
|
|
||||||
if (event.shiftKey && this.lastSelectedLockIndex !== null) {
|
if (event.shiftKey && this.lastSelectedLockIndex !== null) {
|
||||||
const startIndex = Math.min(this.lastSelectedLockIndex, chapterId)
|
const startIndex = Math.min(this.lastSelectedLockIndex, chapterId)
|
||||||
const endIndex = Math.max(this.lastSelectedLockIndex, chapterId)
|
const endIndex = Math.max(this.lastSelectedLockIndex, chapterId)
|
||||||
|
|
||||||
// Determine if we should lock or unlock based on the target chapter's current state
|
|
||||||
const shouldLock = !this.lockedChapters.has(chapterId)
|
const shouldLock = !this.lockedChapters.has(chapterId)
|
||||||
|
|
||||||
for (let i = startIndex; i <= endIndex; i++) {
|
for (let i = startIndex; i <= endIndex; i++) {
|
||||||
@ -508,7 +505,6 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Single chapter toggle
|
|
||||||
if (this.lockedChapters.has(chapterId)) {
|
if (this.lockedChapters.has(chapterId)) {
|
||||||
this.lockedChapters.delete(chapterId)
|
this.lockedChapters.delete(chapterId)
|
||||||
} else {
|
} else {
|
||||||
@ -517,8 +513,6 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.lastSelectedLockIndex = chapterId
|
this.lastSelectedLockIndex = chapterId
|
||||||
|
|
||||||
// Force reactivity update
|
|
||||||
this.lockedChapters = new Set(this.lockedChapters)
|
this.lockedChapters = new Set(this.lockedChapters)
|
||||||
},
|
},
|
||||||
lockAllChapters() {
|
lockAllChapters() {
|
||||||
@ -873,7 +867,6 @@ export default {
|
|||||||
const input = this.bulkChapterInput.trim()
|
const input = this.bulkChapterInput.trim()
|
||||||
if (!input) return
|
if (!input) return
|
||||||
|
|
||||||
// Check if input contains any numbers and extract pattern info
|
|
||||||
const numberMatch = input.match(/(\d+)/)
|
const numberMatch = input.match(/(\d+)/)
|
||||||
|
|
||||||
if (numberMatch) {
|
if (numberMatch) {
|
||||||
@ -884,7 +877,6 @@ export default {
|
|||||||
const beforeNumber = input.substring(0, numberIndex)
|
const beforeNumber = input.substring(0, numberIndex)
|
||||||
const afterNumber = input.substring(numberIndex + originalNumberString.length)
|
const afterNumber = input.substring(numberIndex + originalNumberString.length)
|
||||||
|
|
||||||
// Store pattern info for bulk creation, preserving padding
|
|
||||||
this.detectedPattern = {
|
this.detectedPattern = {
|
||||||
before: beforeNumber,
|
before: beforeNumber,
|
||||||
after: afterNumber,
|
after: afterNumber,
|
||||||
@ -893,11 +885,9 @@ export default {
|
|||||||
hasLeadingZeros: originalNumberString.length > 1 && originalNumberString.startsWith('0')
|
hasLeadingZeros: originalNumberString.length > 1 && originalNumberString.startsWith('0')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show modal to ask for number of chapters
|
|
||||||
this.bulkChapterCount = 1
|
this.bulkChapterCount = 1
|
||||||
this.showBulkChapterModal = true
|
this.showBulkChapterModal = true
|
||||||
} else {
|
} else {
|
||||||
// Add single chapter with the entered title
|
|
||||||
this.addSingleChapterFromInput(input)
|
this.addSingleChapterFromInput(input)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -905,7 +895,7 @@ export default {
|
|||||||
// Find the last chapter to determine where to add the new one
|
// Find the last chapter to determine where to add the new one
|
||||||
const lastChapter = this.newChapters[this.newChapters.length - 1]
|
const lastChapter = this.newChapters[this.newChapters.length - 1]
|
||||||
const newStart = lastChapter ? lastChapter.end : 0
|
const newStart = lastChapter ? lastChapter.end : 0
|
||||||
const newEnd = Math.min(newStart + 300, this.mediaDuration) // Default 5 minutes or media duration
|
const newEnd = Math.min(newStart + 300, this.mediaDuration)
|
||||||
|
|
||||||
const newChapter = {
|
const newChapter = {
|
||||||
id: this.newChapters.length,
|
id: this.newChapters.length,
|
||||||
|
@ -983,6 +983,7 @@
|
|||||||
"ToastCachePurgeSuccess": "Cache purged successfully",
|
"ToastCachePurgeSuccess": "Cache purged successfully",
|
||||||
"ToastChapterInvalidShiftAmount": "Invalid shift amount. First chapter would have zero or negative length.",
|
"ToastChapterInvalidShiftAmount": "Invalid shift amount. First chapter would have zero or negative length.",
|
||||||
"ToastChapterLocked": "Chapter is locked.",
|
"ToastChapterLocked": "Chapter is locked.",
|
||||||
|
"ToastChapterStartTimeAdjusted": "Chapter start time adjusted by {0} seconds",
|
||||||
"ToastChaptersAllLocked": "All chapters are locked. Unlock some chapters to shift their times.",
|
"ToastChaptersAllLocked": "All chapters are locked. Unlock some chapters to shift their times.",
|
||||||
"ToastChaptersHaveErrors": "Chapters have errors",
|
"ToastChaptersHaveErrors": "Chapters have errors",
|
||||||
"ToastChaptersInvalidShiftAmountLast": "Invalid shift amount. The last chapter start time would extend beyond the duration of this audiobook.",
|
"ToastChaptersInvalidShiftAmountLast": "Invalid shift amount. The last chapter start time would extend beyond the duration of this audiobook.",
|
||||||
@ -1116,6 +1117,7 @@
|
|||||||
"ToastUserRootRequireName": "Must enter a root username",
|
"ToastUserRootRequireName": "Must enter a root username",
|
||||||
"TooltipAddChapters": "Add chapter(s)",
|
"TooltipAddChapters": "Add chapter(s)",
|
||||||
"TooltipAddOneSecond": "Add 1 second",
|
"TooltipAddOneSecond": "Add 1 second",
|
||||||
|
"TooltipAdjustChapterStart": "Click to adjust start time",
|
||||||
"TooltipLockAllChapters": "Lock all chapters",
|
"TooltipLockAllChapters": "Lock all chapters",
|
||||||
"TooltipLockChapter": "Lock chapter (Shift+click for range)",
|
"TooltipLockChapter": "Lock chapter (Shift+click for range)",
|
||||||
"TooltipSubtractOneSecond": "Subtract 1 second",
|
"TooltipSubtractOneSecond": "Subtract 1 second",
|
||||||
|
Loading…
Reference in New Issue
Block a user