mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2024-12-20 19:06:06 +01:00
Merge pull request #3117 from mikiher/show-subtitles
New feature: Show Subtitles
This commit is contained in:
commit
10cb8ebf3b
@ -170,13 +170,13 @@ export default {
|
|||||||
|
|
||||||
if (!this.isPodcastLibrary && this.selectedMediaItemsArePlayable) {
|
if (!this.isPodcastLibrary && this.selectedMediaItemsArePlayable) {
|
||||||
options.push({
|
options.push({
|
||||||
text: 'Quick Embed Metadata',
|
text: this.$strings.ButtonQuickEmbedMetadata,
|
||||||
action: 'quick-embed'
|
action: 'quick-embed'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
options.push({
|
options.push({
|
||||||
text: 'Re-Scan',
|
text: this.$strings.ButtonReScan,
|
||||||
action: 'rescan'
|
action: 'rescan'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -53,7 +53,6 @@
|
|||||||
<span class="font-mono">{{ numShowing }}</span>
|
<span class="font-mono">{{ numShowing }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-grow" />
|
<div class="flex-grow" />
|
||||||
<ui-checkbox v-if="!isBatchSelecting" v-model="settings.collapseBookSeries" :label="$strings.LabelCollapseSeries" checkbox-bg="bg" check-color="white" small class="mr-2" @input="updateCollapseBookSeries" />
|
|
||||||
|
|
||||||
<!-- RSS feed -->
|
<!-- RSS feed -->
|
||||||
<ui-tooltip v-if="seriesRssFeed" :text="$strings.LabelOpenRSSFeed" direction="top">
|
<ui-tooltip v-if="seriesRssFeed" :text="$strings.LabelOpenRSSFeed" direction="top">
|
||||||
@ -68,9 +67,6 @@
|
|||||||
|
|
||||||
<div class="flex-grow hidden sm:inline-block" />
|
<div class="flex-grow hidden sm:inline-block" />
|
||||||
|
|
||||||
<!-- collapse series checkbox -->
|
|
||||||
<ui-checkbox v-if="isLibraryPage && isBookLibrary && !isBatchSelecting" v-model="settings.collapseSeries" :label="$strings.LabelCollapseSeries" checkbox-bg="bg" check-color="white" small class="mr-2" @input="updateCollapseSeries" />
|
|
||||||
|
|
||||||
<!-- library filter select -->
|
<!-- library filter select -->
|
||||||
<controls-library-filter-select v-if="isLibraryPage && !isBatchSelecting" v-model="settings.filterBy" class="w-36 sm:w-44 md:w-48 h-7.5 ml-1 sm:ml-4" @change="updateFilter" />
|
<controls-library-filter-select v-if="isLibraryPage && !isBatchSelecting" v-model="settings.filterBy" class="w-36 sm:w-44 md:w-48 h-7.5 ml-1 sm:ml-4" @change="updateFilter" />
|
||||||
|
|
||||||
@ -88,11 +84,17 @@
|
|||||||
|
|
||||||
<ui-context-menu-dropdown v-if="contextMenuItems.length" :items="contextMenuItems" :menu-width="110" class="ml-2" @action="contextMenuAction" />
|
<ui-context-menu-dropdown v-if="contextMenuItems.length" :items="contextMenuItems" :menu-width="110" class="ml-2" @action="contextMenuAction" />
|
||||||
</template>
|
</template>
|
||||||
|
<!-- home page -->
|
||||||
|
<template v-else-if="isHome">
|
||||||
|
<div class="flex-grow" />
|
||||||
|
<ui-context-menu-dropdown v-if="contextMenuItems.length" :items="contextMenuItems" :menu-width="110" class="ml-2" @action="contextMenuAction" />
|
||||||
|
</template>
|
||||||
<!-- search page -->
|
<!-- search page -->
|
||||||
<template v-else-if="page === 'search'">
|
<template v-else-if="page === 'search'">
|
||||||
<div class="flex-grow" />
|
<div class="flex-grow" />
|
||||||
<p>{{ $strings.MessageSearchResultsFor }} "{{ searchQuery }}"</p>
|
<p>{{ $strings.MessageSearchResultsFor }} "{{ searchQuery }}"</p>
|
||||||
<div class="flex-grow" />
|
<div class="flex-grow" />
|
||||||
|
<ui-context-menu-dropdown v-if="contextMenuItems.length" :items="contextMenuItems" :menu-width="110" class="ml-2" @action="contextMenuAction" />
|
||||||
</template>
|
</template>
|
||||||
<!-- authors page -->
|
<!-- authors page -->
|
||||||
<template v-else-if="page === 'authors'">
|
<template v-else-if="page === 'authors'">
|
||||||
@ -151,11 +153,13 @@ export default {
|
|||||||
|
|
||||||
if (this.isSeriesRemovedFromContinueListening) {
|
if (this.isSeriesRemovedFromContinueListening) {
|
||||||
items.push({
|
items.push({
|
||||||
text: 'Re-Add Series to Continue Listening',
|
text: this.$strings.LabelReAddSeriesToContinueListening,
|
||||||
action: 're-add-to-continue-listening'
|
action: 're-add-to-continue-listening'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.addSubtitlesMenuItem(items)
|
||||||
|
|
||||||
return items
|
return items
|
||||||
},
|
},
|
||||||
seriesSortItems() {
|
seriesSortItems() {
|
||||||
@ -318,11 +322,14 @@ export default {
|
|||||||
|
|
||||||
if (this.isPodcastLibrary && this.isLibraryPage && this.userCanDownload) {
|
if (this.isPodcastLibrary && this.isLibraryPage && this.userCanDownload) {
|
||||||
items.push({
|
items.push({
|
||||||
text: 'Export OPML',
|
text: this.$strings.LabelExportOPML,
|
||||||
action: 'export-opml'
|
action: 'export-opml'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.addSubtitlesMenuItem(items)
|
||||||
|
this.addCollapseSeriesMenuItem(items)
|
||||||
|
|
||||||
return items
|
return items
|
||||||
},
|
},
|
||||||
showPlaylists() {
|
showPlaylists() {
|
||||||
@ -330,9 +337,70 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
addSubtitlesMenuItem(items) {
|
||||||
|
if (this.isBookLibrary && (!this.page || this.page === 'search')) {
|
||||||
|
if (this.settings.showSubtitles) {
|
||||||
|
items.push({
|
||||||
|
text: this.$strings.LabelHideSubtitles,
|
||||||
|
action: 'hide-subtitles'
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
items.push({
|
||||||
|
text: this.$strings.LabelShowSubtitles,
|
||||||
|
action: 'show-subtitles'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
addCollapseSeriesMenuItem(items) {
|
||||||
|
if (this.isLibraryPage && this.isBookLibrary && !this.isBatchSelecting) {
|
||||||
|
if (this.settings.collapseSeries) {
|
||||||
|
items.push({
|
||||||
|
text: this.$strings.LabelExpandSeries,
|
||||||
|
action: 'expand-series'
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
items.push({
|
||||||
|
text: this.$strings.LabelCollapseSeries,
|
||||||
|
action: 'collapse-series'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleSubtitlesAction(action) {
|
||||||
|
if (action === 'show-subtitles') {
|
||||||
|
this.settings.showSubtitles = true
|
||||||
|
this.updateShowSubtitles()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (action === 'hide-subtitles') {
|
||||||
|
this.settings.showSubtitles = false
|
||||||
|
this.updateShowSubtitles()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
handleCollapseSeriesAction(action) {
|
||||||
|
if (action === 'collapse-series') {
|
||||||
|
this.settings.collapseSeries = true
|
||||||
|
this.updateCollapseSeries()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if (action === 'expand-series') {
|
||||||
|
this.settings.collapseSeries = false
|
||||||
|
this.updateCollapseSeries()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
},
|
||||||
contextMenuAction({ action }) {
|
contextMenuAction({ action }) {
|
||||||
if (action === 'export-opml') {
|
if (action === 'export-opml') {
|
||||||
this.exportOPML()
|
this.exportOPML()
|
||||||
|
return
|
||||||
|
} else if (this.handleSubtitlesAction(action)) {
|
||||||
|
return
|
||||||
|
} else if (this.handleCollapseSeriesAction(action)) {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
exportOPML() {
|
exportOPML() {
|
||||||
@ -353,6 +421,8 @@ export default {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.markSeriesFinished()
|
this.markSeriesFinished()
|
||||||
|
} else if (this.handleSubtitlesAction(action)) {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
showOpenSeriesRSSFeed() {
|
showOpenSeriesRSSFeed() {
|
||||||
@ -482,6 +552,9 @@ export default {
|
|||||||
updateCollapseBookSeries() {
|
updateCollapseBookSeries() {
|
||||||
this.saveSettings()
|
this.saveSettings()
|
||||||
},
|
},
|
||||||
|
updateShowSubtitles() {
|
||||||
|
this.saveSettings()
|
||||||
|
},
|
||||||
updateAuthorSort() {
|
updateAuthorSort() {
|
||||||
this.saveSettings()
|
this.saveSettings()
|
||||||
},
|
},
|
||||||
|
@ -132,6 +132,9 @@
|
|||||||
<widgets-explicit-indicator cy-id="explicitIndicator" v-if="isExplicit" />
|
<widgets-explicit-indicator cy-id="explicitIndicator" v-if="isExplicit" />
|
||||||
</ui-tooltip>
|
</ui-tooltip>
|
||||||
</div>
|
</div>
|
||||||
|
<ui-tooltip v-if="showSubtitles" :text="displaySubtitle" :disabled="!displaySubtitleTruncated" direction="bottom" :delayOnShow="500" class="flex items-center">
|
||||||
|
<p cy-id="subtitle" class="truncate" ref="displaySubtitle" :style="{ fontSize: 0.6 + 'em' }">{{ displaySubtitle }}</p>
|
||||||
|
</ui-tooltip>
|
||||||
<p cy-id="line2" class="truncate text-gray-400" :style="{ fontSize: 0.8 + 'em' }">{{ displayLineTwo || ' ' }}</p>
|
<p cy-id="line2" class="truncate text-gray-400" :style="{ fontSize: 0.8 + 'em' }">{{ displayLineTwo || ' ' }}</p>
|
||||||
<p cy-id="line3" v-if="displaySortLine" class="truncate text-gray-400" :style="{ fontSize: 0.8 + 'em' }">{{ displaySortLine }}</p>
|
<p cy-id="line3" v-if="displaySortLine" class="truncate text-gray-400" :style="{ fontSize: 0.8 + 'em' }">{{ displaySortLine }}</p>
|
||||||
</div>
|
</div>
|
||||||
@ -171,6 +174,7 @@ export default {
|
|||||||
selected: false,
|
selected: false,
|
||||||
isSelectionMode: false,
|
isSelectionMode: false,
|
||||||
displayTitleTruncated: false,
|
displayTitleTruncated: false,
|
||||||
|
displaySubtitleTruncated: false,
|
||||||
showCoverBg: false
|
showCoverBg: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -237,7 +241,7 @@ export default {
|
|||||||
return this._libraryItem.mediaType
|
return this._libraryItem.mediaType
|
||||||
},
|
},
|
||||||
isPodcast() {
|
isPodcast() {
|
||||||
return this.mediaType === 'podcast'
|
return this.mediaType === 'podcast' || this.store.getters['libraries/getCurrentLibraryMediaType'] === 'podcast'
|
||||||
},
|
},
|
||||||
isMusic() {
|
isMusic() {
|
||||||
return this.mediaType === 'music'
|
return this.mediaType === 'music'
|
||||||
@ -339,6 +343,13 @@ export default {
|
|||||||
if (this.collapsedSeries) return ignorePrefix ? this.collapsedSeries.nameIgnorePrefix : this.collapsedSeries.name
|
if (this.collapsedSeries) return ignorePrefix ? this.collapsedSeries.nameIgnorePrefix : this.collapsedSeries.name
|
||||||
return ignorePrefix ? this.mediaMetadata.titleIgnorePrefix || '\u00A0' : this.title || '\u00A0'
|
return ignorePrefix ? this.mediaMetadata.titleIgnorePrefix || '\u00A0' : this.title || '\u00A0'
|
||||||
},
|
},
|
||||||
|
displaySubtitle() {
|
||||||
|
if (!this.libraryItem) return '\u00A0'
|
||||||
|
if (this.collapsedSeries) return this.collapsedSeries.numBooks === 1 ? '1 book' : `${this.collapsedSeries.numBooks} books`
|
||||||
|
if (this.mediaMetadata.subtitle) return this.mediaMetadata.subtitle
|
||||||
|
if (this.mediaMetadata.seriesName) return this.mediaMetadata.seriesName
|
||||||
|
return ''
|
||||||
|
},
|
||||||
displayLineTwo() {
|
displayLineTwo() {
|
||||||
if (this.recentEpisode) return this.title
|
if (this.recentEpisode) return this.title
|
||||||
if (this.isPodcast) return this.author
|
if (this.isPodcast) return this.author
|
||||||
@ -644,6 +655,9 @@ export default {
|
|||||||
},
|
},
|
||||||
mediaItemShare() {
|
mediaItemShare() {
|
||||||
return this._libraryItem.mediaItemShare || null
|
return this._libraryItem.mediaItemShare || null
|
||||||
|
},
|
||||||
|
showSubtitles() {
|
||||||
|
return !this.isPodcast && this.store.getters['user/getUserSetting']('showSubtitles')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -685,6 +699,9 @@ export default {
|
|||||||
if (this.$refs.displayTitle) {
|
if (this.$refs.displayTitle) {
|
||||||
this.displayTitleTruncated = this.$refs.displayTitle.scrollWidth > this.$refs.displayTitle.clientWidth
|
this.displayTitleTruncated = this.$refs.displayTitle.scrollWidth > this.$refs.displayTitle.clientWidth
|
||||||
}
|
}
|
||||||
|
if (this.$refs.displaySubtitle) {
|
||||||
|
this.displaySubtitleTruncated = this.$refs.displaySubtitle.scrollWidth > this.$refs.displaySubtitle.clientWidth
|
||||||
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
clickCard(e) {
|
clickCard(e) {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -11,7 +11,7 @@ function createMountOptions() {
|
|||||||
mediaType: 'book',
|
mediaType: 'book',
|
||||||
media: {
|
media: {
|
||||||
id: 'book1',
|
id: 'book1',
|
||||||
metadata: { title: 'The Fellowship of the Ring', titleIgnorePrefix: 'Fellowship of the Ring', authorName: 'J. R. R. Tolkien' },
|
metadata: { title: 'The Fellowship of the Ring', titleIgnorePrefix: 'Fellowship of the Ring', authorName: 'J. R. R. Tolkien', subtitle: 'The Lord of the Rings, Book 1' },
|
||||||
numTracks: 1
|
numTracks: 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -138,6 +138,16 @@ describe('LazyBookCard', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('shows subtitle when showSubtitles settings is true', () => {
|
||||||
|
mountOptions.mocks.$store.getters['user/getUserSetting'] = (settingName) => {
|
||||||
|
if (settingName === 'showSubtitles') return true
|
||||||
|
}
|
||||||
|
cy.mount(LazyBookCard, mountOptions)
|
||||||
|
|
||||||
|
cy.get('&titleImageNotReady').should('be.hidden')
|
||||||
|
cy.get('&subtitle').should('be.visible').and('have.text', 'The Lord of the Rings, Book 1')
|
||||||
|
})
|
||||||
|
|
||||||
it('shows overlay on mouseover', () => {
|
it('shows overlay on mouseover', () => {
|
||||||
cy.mount(LazyBookCard, mountOptions)
|
cy.mount(LazyBookCard, mountOptions)
|
||||||
cy.get('#book-card-0').trigger('mouseover')
|
cy.get('#book-card-0').trigger('mouseover')
|
||||||
|
@ -8,6 +8,7 @@ export const state = () => ({
|
|||||||
bookshelfCoverSize: 120,
|
bookshelfCoverSize: 120,
|
||||||
collapseSeries: false,
|
collapseSeries: false,
|
||||||
collapseBookSeries: false,
|
collapseBookSeries: false,
|
||||||
|
showSubtitles: false,
|
||||||
useChapterTrack: false,
|
useChapterTrack: false,
|
||||||
seriesSortBy: 'name',
|
seriesSortBy: 'name',
|
||||||
seriesSortDesc: false,
|
seriesSortDesc: false,
|
||||||
|
@ -59,6 +59,7 @@
|
|||||||
"ButtonPurgeItemsCache": "Purge Items Cache",
|
"ButtonPurgeItemsCache": "Purge Items Cache",
|
||||||
"ButtonQueueAddItem": "Add to queue",
|
"ButtonQueueAddItem": "Add to queue",
|
||||||
"ButtonQueueRemoveItem": "Remove from queue",
|
"ButtonQueueRemoveItem": "Remove from queue",
|
||||||
|
"ButtonQuickEmbedMetadata": "Quick Embed Metadata",
|
||||||
"ButtonQuickMatch": "Quick Match",
|
"ButtonQuickMatch": "Quick Match",
|
||||||
"ButtonReScan": "Re-Scan",
|
"ButtonReScan": "Re-Scan",
|
||||||
"ButtonRead": "Read",
|
"ButtonRead": "Read",
|
||||||
@ -293,9 +294,11 @@
|
|||||||
"LabelEpisodeTitle": "Episode Title",
|
"LabelEpisodeTitle": "Episode Title",
|
||||||
"LabelEpisodeType": "Episode Type",
|
"LabelEpisodeType": "Episode Type",
|
||||||
"LabelExample": "Example",
|
"LabelExample": "Example",
|
||||||
|
"LabelExpandSeries": "Expand Series",
|
||||||
"LabelExplicit": "Explicit",
|
"LabelExplicit": "Explicit",
|
||||||
"LabelExplicitChecked": "Explicit (checked)",
|
"LabelExplicitChecked": "Explicit (checked)",
|
||||||
"LabelExplicitUnchecked": "Not Explicit (unchecked)",
|
"LabelExplicitUnchecked": "Not Explicit (unchecked)",
|
||||||
|
"LabelExportOPML": "Export OPML",
|
||||||
"LabelFeedURL": "Feed URL",
|
"LabelFeedURL": "Feed URL",
|
||||||
"LabelFetchingMetadata": "Fetching Metadata",
|
"LabelFetchingMetadata": "Fetching Metadata",
|
||||||
"LabelFile": "File",
|
"LabelFile": "File",
|
||||||
@ -319,6 +322,7 @@
|
|||||||
"LabelHardDeleteFile": "Hard delete file",
|
"LabelHardDeleteFile": "Hard delete file",
|
||||||
"LabelHasEbook": "Has ebook",
|
"LabelHasEbook": "Has ebook",
|
||||||
"LabelHasSupplementaryEbook": "Has supplementary ebook",
|
"LabelHasSupplementaryEbook": "Has supplementary ebook",
|
||||||
|
"LabelHideSubtitles": "Hide Subtitles",
|
||||||
"LabelHighestPriority": "Highest priority",
|
"LabelHighestPriority": "Highest priority",
|
||||||
"LabelHost": "Host",
|
"LabelHost": "Host",
|
||||||
"LabelHour": "Hour",
|
"LabelHour": "Hour",
|
||||||
@ -446,6 +450,7 @@
|
|||||||
"LabelRSSFeedPreventIndexing": "Prevent Indexing",
|
"LabelRSSFeedPreventIndexing": "Prevent Indexing",
|
||||||
"LabelRSSFeedSlug": "RSS Feed Slug",
|
"LabelRSSFeedSlug": "RSS Feed Slug",
|
||||||
"LabelRSSFeedURL": "RSS Feed URL",
|
"LabelRSSFeedURL": "RSS Feed URL",
|
||||||
|
"LabelReAddSeriesToContinueListening": "Re-add series to Continue Listening",
|
||||||
"LabelRead": "Read",
|
"LabelRead": "Read",
|
||||||
"LabelReadAgain": "Read Again",
|
"LabelReadAgain": "Read Again",
|
||||||
"LabelReadEbookWithoutProgress": "Read ebook without keeping progress",
|
"LabelReadEbookWithoutProgress": "Read ebook without keeping progress",
|
||||||
@ -516,6 +521,7 @@
|
|||||||
"LabelShareURL": "Share URL",
|
"LabelShareURL": "Share URL",
|
||||||
"LabelShowAll": "Show All",
|
"LabelShowAll": "Show All",
|
||||||
"LabelShowSeconds": "Show seconds",
|
"LabelShowSeconds": "Show seconds",
|
||||||
|
"LabelShowSubtitles": "Show Subtitles",
|
||||||
"LabelSize": "Size",
|
"LabelSize": "Size",
|
||||||
"LabelSleepTimer": "Sleep timer",
|
"LabelSleepTimer": "Sleep timer",
|
||||||
"LabelSlug": "Slug",
|
"LabelSlug": "Slug",
|
||||||
|
Loading…
Reference in New Issue
Block a user