diff --git a/Dockerfile b/Dockerfile index 43ee4eb42..47aced8a9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,5 +25,5 @@ HEALTHCHECK \ --interval=30s \ --timeout=3s \ --start-period=10s \ - CMD curl -f http://127.0.0.1/ping || exit 1 + CMD curl -f http://127.0.0.1/healthcheck || exit 1 CMD ["npm", "start"] diff --git a/client/assets/app.css b/client/assets/app.css index 5d67df53c..f9999c7aa 100644 --- a/client/assets/app.css +++ b/client/assets/app.css @@ -225,4 +225,18 @@ Bookshelf Label -webkit-line-clamp: 2; /* number of lines to show */ -webkit-box-orient: vertical; +} + + +/* Padding for toastification toasts in the top right to not cover appbar/toolbar */ +.app-bar-and-toolbar .Vue-Toastification__container.top-right { + padding-top: 104px; +} + +.app-bar .Vue-Toastification__container.top-right { + padding-top: 64px; +} + +.no-bars .Vue-Toastification__container.top-right { + padding-top: 8px; } \ No newline at end of file diff --git a/client/assets/draggable.css b/client/assets/draggable.css index 48dca6b80..31271e675 100644 --- a/client/assets/draggable.css +++ b/client/assets/draggable.css @@ -1,34 +1,40 @@ .flip-list-move { transition: transform 0.5s; } + .no-move { transition: transform 0s; } + .ghost { opacity: 0.5; background-color: rgba(255, 255, 255, 0.25); } + .list-group { min-height: 30px; } -#librariesTable .item { - cursor: n-resize; -} + .drag-handle { cursor: n-resize; } + .list-group-item:not(.exclude) { cursor: n-resize; } + .list-group-item.exclude { cursor: not-allowed; } + .list-group-item:not(.ghost):not(.exclude):hover { background-color: rgba(0, 0, 0, 0.1); } + .list-group-item:nth-child(even):not(.ghost):not(.exclude) { background-color: rgba(0, 0, 0, 0.25); } + .list-group-item:nth-child(even):not(.ghost):not(.exclude):hover { background-color: rgba(0, 0, 0, 0.1); } @@ -36,6 +42,7 @@ .list-group-item.exclude:not(.ghost) { background-color: rgba(255, 0, 0, 0.25); } + .list-group-item.exclude:not(.ghost):hover { background-color: rgba(223, 0, 0, 0.25); } \ No newline at end of file diff --git a/client/assets/fonts.css b/client/assets/fonts.css index b7e75d0ca..46e007aa2 100644 --- a/client/assets/fonts.css +++ b/client/assets/fonts.css @@ -74,7 +74,7 @@ font-style: normal; font-weight: 300; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -84,7 +84,7 @@ font-style: normal; font-weight: 300; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -94,7 +94,7 @@ font-style: normal; font-weight: 300; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); unicode-range: U+1F00-1FFF; } @@ -104,7 +104,7 @@ font-style: normal; font-weight: 300; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); unicode-range: U+0370-03FF; } @@ -114,7 +114,7 @@ font-style: normal; font-weight: 300; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; } @@ -124,7 +124,7 @@ font-style: normal; font-weight: 300; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -134,7 +134,7 @@ font-style: normal; font-weight: 300; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf) format('truetype'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -154,7 +154,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('truetype'); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -164,7 +164,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('truetype'); unicode-range: U+1F00-1FFF; } @@ -174,7 +174,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('truetype'); unicode-range: U+0370-03FF; } @@ -184,7 +184,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('truetype'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; } @@ -194,7 +194,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('truetype'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -204,7 +204,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf) format('truetype'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -214,7 +214,7 @@ font-style: normal; font-weight: 600; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -224,7 +224,7 @@ font-style: normal; font-weight: 600; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -234,7 +234,7 @@ font-style: normal; font-weight: 600; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); unicode-range: U+1F00-1FFF; } @@ -244,7 +244,7 @@ font-style: normal; font-weight: 600; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); unicode-range: U+0370-03FF; } @@ -254,7 +254,7 @@ font-style: normal; font-weight: 600; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; } @@ -264,7 +264,7 @@ font-style: normal; font-weight: 600; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -274,7 +274,7 @@ font-style: normal; font-weight: 600; font-display: swap; - src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('ttf'); + src: url(/fonts/Source_Sans_Pro/SourceSansPro-SemiBold.ttf) format('truetype'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } @@ -284,7 +284,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('ttf'); + src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('truetype'); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } @@ -294,7 +294,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('ttf'); + src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('truetype'); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } @@ -304,7 +304,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('ttf'); + src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('truetype'); unicode-range: U+1F00-1FFF; } @@ -314,7 +314,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('ttf'); + src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('truetype'); unicode-range: U+0370-03FF; } @@ -324,7 +324,7 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('ttf'); + src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('truetype'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } @@ -334,6 +334,6 @@ font-style: normal; font-weight: 400; font-display: swap; - src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('ttf'); + src: url(/fonts/Ubuntu_Mono/UbuntuMono-Regular.ttf) format('truetype'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } \ No newline at end of file diff --git a/client/components/app/Appbar.vue b/client/components/app/Appbar.vue index cfc1c9949..0d63eccce 100644 --- a/client/components/app/Appbar.vue +++ b/client/components/app/Appbar.vue @@ -3,14 +3,14 @@
- +

audiobookshelf

- +
diff --git a/client/components/app/BookShelfCategorized.vue b/client/components/app/BookShelfCategorized.vue index 3322677f5..ceb792374 100644 --- a/client/components/app/BookShelfCategorized.vue +++ b/client/components/app/BookShelfCategorized.vue @@ -33,7 +33,7 @@
@@ -70,11 +70,8 @@ export default { libraryName() { return this.$store.getters['libraries/getCurrentLibraryName'] }, - bookshelfView() { - return this.$store.getters['getServerSetting']('bookshelfView') - }, isAlternativeBookshelfView() { - return this.bookshelfView === this.$constants.BookshelfView.TITLES + return this.$store.getters['getHomeBookshelfView'] === this.$constants.BookshelfView.TITLES }, bookCoverWidth() { var coverSize = this.$store.getters['user/getUserSetting']('bookshelfCoverSize') @@ -82,13 +79,10 @@ export default { return coverSize }, coverAspectRatio() { - return this.$store.getters['getServerSetting']('coverAspectRatio') + return this.$store.getters['libraries/getBookCoverAspectRatio'] }, isCoverSquareAspectRatio() { - return this.coverAspectRatio === this.$constants.BookCoverAspectRatio.SQUARE - }, - bookCoverAspectRatio() { - return this.isCoverSquareAspectRatio ? 1 : 1.6 + return this.coverAspectRatio == 1 }, sizeMultiplier() { var baseSize = this.isCoverSquareAspectRatio ? 192 : 120 diff --git a/client/components/app/ConfigSideNav.vue b/client/components/app/ConfigSideNav.vue index bbadecc31..50cec860c 100644 --- a/client/components/app/ConfigSideNav.vue +++ b/client/components/app/ConfigSideNav.vue @@ -11,12 +11,14 @@
-

v{{ $config.version }}

+

v{{ $config.version }}

{{ Source }}

Latest: {{ latestVersion }}
+ +
@@ -26,7 +28,9 @@ export default { isOpen: Boolean }, data() { - return {} + return { + showChangelogModal: false + } }, computed: { Source() { @@ -129,18 +133,24 @@ export default { githubTagUrl() { return this.versionData.githubTagUrl }, + currentVersionChangelog() { + return this.versionData.currentVersionChangelog || 'No Changelog Available' + }, streamLibraryItem() { return this.$store.state.streamLibraryItem } }, methods: { + clickChangelog(){ + this.showChangelogModal = true + }, clickOutside() { if (!this.isOpen) return this.closeDrawer() }, closeDrawer() { this.$emit('update:isOpen', false) - } + }, } } \ No newline at end of file diff --git a/client/components/app/LazyBookshelf.vue b/client/components/app/LazyBookshelf.vue index 0a4e0c5bd..384123644 100644 --- a/client/components/app/LazyBookshelf.vue +++ b/client/components/app/LazyBookshelf.vue @@ -88,6 +88,7 @@ export default { if (this.page === 'collections') return "You haven't made any collections yet" if (this.hasFilter) { if (this.filterName === 'Issues') return 'No Issues' + else if (this.filterName === 'Feed-open') return 'No RSS feeds are open' return `No Results for filter "${this.filterName}: ${this.filterValue}"` } return 'No results' @@ -109,24 +110,20 @@ export default { return this.$store.getters['user/getUserSetting']('collapseSeries') }, coverAspectRatio() { - return this.$store.getters['getServerSetting']('coverAspectRatio') - }, - bookshelfView() { - return this.$store.getters['getServerSetting']('bookshelfView') + return this.$store.getters['libraries/getBookCoverAspectRatio'] }, sortingIgnorePrefix() { return this.$store.getters['getServerSetting']('sortingIgnorePrefix') }, isCoverSquareAspectRatio() { - return this.coverAspectRatio === this.$constants.BookCoverAspectRatio.SQUARE + return this.coverAspectRatio == 1 + }, + bookshelfView() { + return this.$store.getters['getBookshelfView'] }, isAlternativeBookshelfView() { - // if (!this.isEntityBook) return false // Only used for bookshelf showing books return this.bookshelfView === this.$constants.BookshelfView.TITLES }, - bookCoverAspectRatio() { - return this.isCoverSquareAspectRatio ? 1 : 1.6 - }, hasFilter() { return this.filterBy && this.filterBy !== 'all' }, diff --git a/client/components/app/SideRail.vue b/client/components/app/SideRail.vue index 0fbe56787..4e0f6e7f8 100644 --- a/client/components/app/SideRail.vue +++ b/client/components/app/SideRail.vue @@ -83,17 +83,21 @@
-

v{{ $config.version }}

+

v{{ $config.version }}

Update

{{ Source }}

+ +
\ No newline at end of file diff --git a/client/components/app/StreamContainer.vue b/client/components/app/StreamContainer.vue index 5775cf275..bce083fad 100644 --- a/client/components/app/StreamContainer.vue +++ b/client/components/app/StreamContainer.vue @@ -2,7 +2,7 @@
- +
@@ -77,16 +77,13 @@ export default { }, computed: { coverAspectRatio() { - return this.$store.getters['getServerSetting']('coverAspectRatio') - }, - bookCoverAspectRatio() { - return this.coverAspectRatio === this.$constants.BookCoverAspectRatio.SQUARE ? 1 : 1.6 + return this.$store.getters['libraries/getBookCoverAspectRatio'] }, bookCoverWidth() { return 88 }, bookCoverPosTop() { - if (this.bookCoverAspectRatio === 1) return -10 + if (this.coverAspectRatio == 1) return -10 return -64 }, cover() { @@ -364,7 +361,11 @@ export default { var episodeId = payload.episodeId || null if (this.playerHandler.libraryItemId == libraryItemId && this.playerHandler.episodeId == episodeId) { - this.playerHandler.play() + if (payload.startTime !== null && !isNaN(payload.startTime)) { + this.seek(payload.startTime) + } else { + this.playerHandler.play() + } return } @@ -377,7 +378,11 @@ export default { libraryItem, episodeId }) - this.playerHandler.load(libraryItem, episodeId, true, this.initialPlaybackRate) + this.$nextTick(() => { + if (this.$refs.audioPlayer) this.$refs.audioPlayer.checkUpdateChapterTrack() + }) + + this.playerHandler.load(libraryItem, episodeId, true, this.initialPlaybackRate, payload.startTime) }, pauseItem() { this.playerHandler.pause() @@ -389,11 +394,13 @@ export default { }, mounted() { this.$eventBus.$on('cast-session-active', this.castSessionActive) + this.$eventBus.$on('playback-seek', this.seek) this.$eventBus.$on('play-item', this.playLibraryItem) this.$eventBus.$on('pause-item', this.pauseItem) }, beforeDestroy() { this.$eventBus.$off('cast-session-active', this.castSessionActive) + this.$eventBus.$off('playback-seek', this.seek) this.$eventBus.$off('play-item', this.playLibraryItem) this.$eventBus.$off('pause-item', this.pauseItem) } diff --git a/client/components/cards/BookMatchCard.vue b/client/components/cards/BookMatchCard.vue index d404d1b73..3a34af685 100644 --- a/client/components/cards/BookMatchCard.vue +++ b/client/components/cards/BookMatchCard.vue @@ -1,16 +1,20 @@ @@ -39,7 +39,8 @@ export default { seriesMount: { type: Object, default: () => null - } + }, + sortingIgnorePrefix: Boolean }, data() { return { @@ -65,6 +66,13 @@ export default { title() { return this.series ? this.series.name : '' }, + nameIgnorePrefix() { + return this.series ? this.series.nameIgnorePrefix : '' + }, + displayTitle() { + if (this.sortingIgnorePrefix) return this.nameIgnorePrefix || this.title + return this.title + }, books() { return this.series ? this.series.books || [] : [] }, diff --git a/client/components/cards/SeriesSearchCard.vue b/client/components/cards/SeriesSearchCard.vue index 8ca6b620b..7f22d02eb 100644 --- a/client/components/cards/SeriesSearchCard.vue +++ b/client/components/cards/SeriesSearchCard.vue @@ -24,7 +24,7 @@ export default { }, computed: { bookCoverAspectRatio() { - return this.$store.getters['getBookCoverAspectRatio'] + return this.$store.getters['libraries/getBookCoverAspectRatio'] }, name() { return this.series.name diff --git a/client/components/controls/FilterSelect.vue b/client/components/controls/FilterSelect.vue index f7ed2c186..3a92f9a11 100644 --- a/client/components/controls/FilterSelect.vue +++ b/client/components/controls/FilterSelect.vue @@ -116,6 +116,11 @@ export default { text: 'Issues', value: 'issues', sublist: false + }, + { + text: 'RSS Feed Open', + value: 'feed-open', + sublist: false } ], podcastItems: [ diff --git a/client/components/controls/GlobalSearch.vue b/client/components/controls/GlobalSearch.vue index f9a0b40b3..095902996 100644 --- a/client/components/controls/GlobalSearch.vue +++ b/client/components/controls/GlobalSearch.vue @@ -1,5 +1,5 @@