diff --git a/komga-webui/src/App.vue b/komga-webui/src/App.vue index 58c31c103..2fdd0cf5f 100644 --- a/komga-webui/src/App.vue +++ b/komga-webui/src/App.vue @@ -6,6 +6,8 @@ diff --git a/komga-webui/src/components/Dialogs.vue b/komga-webui/src/components/Dialogs.vue index 2f1f04e6d..a2465b8cb 100644 --- a/komga-webui/src/components/Dialogs.vue +++ b/komga-webui/src/components/Dialogs.vue @@ -3,39 +3,31 @@ @@ -72,27 +61,11 @@ import EditBooksDialog from '@/components/dialogs/EditBooksDialog.vue' import EditSeriesDialog from '@/components/dialogs/EditSeriesDialog.vue' import LibraryDeleteDialog from '@/components/dialogs/LibraryDeleteDialog.vue' import LibraryEditDialog from '@/components/dialogs/LibraryEditDialog.vue' -import { - BOOK_CHANGED, - bookToEventBookChanged, - COLLECTION_CHANGED, - COLLECTION_DELETED, - collectionToEventCollectionChanged, - collectionToEventCollectionDeleted, - LIBRARY_DELETED, - libraryToEventLibraryDeleted, - READLIST_CHANGED, - READLIST_DELETED, - readListToEventReadListChanged, - readListToEventReadListDeleted, - SERIES_CHANGED, - seriesToEventSeriesChanged, -} from '@/types/events' import Vue from 'vue' import ReadListAddToDialog from '@/components/dialogs/ReadListAddToDialog.vue' import ReadListDeleteDialog from '@/components/dialogs/ReadListDeleteDialog.vue' import ReadListEditDialog from '@/components/dialogs/ReadListEditDialog.vue' -import { BookDto } from '@/types/komga-books' +import {BookDto} from '@/types/komga-books' import {SeriesDto} from "@/types/komga-series"; export default Vue.extend({ @@ -226,49 +199,6 @@ export default Vue.extend({ return this.$store.state.updateSeries }, }, - methods: { - collectionAdded (collection: CollectionDto) { - if (Array.isArray(this.addToCollectionSeries)) { - this.addToCollectionSeries.forEach(s => { - this.$eventHub.$emit(SERIES_CHANGED, seriesToEventSeriesChanged(s)) - }) - } else { - this.$eventHub.$emit(SERIES_CHANGED, seriesToEventSeriesChanged(this.addToCollectionSeries)) - } - this.$eventHub.$emit(COLLECTION_CHANGED, collectionToEventCollectionChanged(collection)) - }, - collectionUpdated () { - this.$eventHub.$emit(COLLECTION_CHANGED, collectionToEventCollectionChanged(this.editCollection)) - }, - collectionDeleted () { - this.$eventHub.$emit(COLLECTION_DELETED, collectionToEventCollectionDeleted(this.deleteCollection)) - }, - readListAdded (readList: ReadListDto) { - if (Array.isArray(this.addToReadListBooks)) { - this.addToReadListBooks.forEach(b => { - this.$eventHub.$emit(BOOK_CHANGED, bookToEventBookChanged(b)) - }) - } else { - this.$eventHub.$emit(BOOK_CHANGED, bookToEventBookChanged(this.addToReadListBooks)) - } - this.$eventHub.$emit(READLIST_CHANGED, readListToEventReadListChanged(readList)) - }, - readListUpdated () { - this.$eventHub.$emit(READLIST_CHANGED, readListToEventReadListChanged(this.editReadList)) - }, - readListDeleted () { - this.$eventHub.$emit(READLIST_DELETED, readListToEventReadListDeleted(this.deleteReadList)) - }, - libraryDeleted () { - this.$eventHub.$emit(LIBRARY_DELETED, libraryToEventLibraryDeleted(this.deleteLibrary)) - }, - bookUpdated (book: BookDto) { - this.$eventHub.$emit(BOOK_CHANGED, bookToEventBookChanged(book)) - }, - seriesUpdated (series: SeriesDto) { - this.$eventHub.$emit(SERIES_CHANGED, seriesToEventSeriesChanged(series)) - }, - }, }) diff --git a/komga-webui/src/components/ItemCard.vue b/komga-webui/src/components/ItemCard.vue index d43710504..c793519cb 100644 --- a/komga-webui/src/components/ItemCard.vue +++ b/komga-webui/src/components/ItemCard.vue @@ -13,6 +13,7 @@ lazy-src="../assets/cover.svg" aspect-ratio="0.7071" contain + @error="thumbnailError = true" >
@@ -39,7 +40,8 @@ :style="'position: absolute; top: 5px; ' + ($vuetify.rtl ? 'right' : 'left') + ': 10px'" @click.stop="selectItem" > - {{ selected || (preselect && hover) ? 'mdi-checkbox-marked-circle' : 'mdi-checkbox-blank-circle-outline' + {{ + selected || (preselect && hover) ? 'mdi-checkbox-marked-circle' : 'mdi-checkbox-blank-circle-outline' }} @@ -126,10 +128,12 @@ import {RawLocation} from 'vue-router' import ReadListActionsMenu from '@/components/menus/ReadListActionsMenu.vue' import {BookDto} from '@/types/komga-books' import {SeriesDto} from "@/types/komga-series"; +import {THUMBNAILBOOK_ADDED, THUMBNAILSERIES_ADDED} from "@/types/events"; +import {ThumbnailBookSseDto, ThumbnailSeriesSseDto} from "@/types/komga-sse"; export default Vue.extend({ name: 'ItemCard', - components: { BookActionsMenu, SeriesActionsMenu, CollectionActionsMenu, ReadListActionsMenu }, + components: {BookActionsMenu, SeriesActionsMenu, CollectionActionsMenu, ReadListActionsMenu}, props: { item: { type: Object as () => BookDto | SeriesDto | CollectionDto | ReadListDto, @@ -182,79 +186,101 @@ export default Vue.extend({ return { ItemTypes, actionMenuState: false, + thumbnailError: false, + thumbnailCacheBust: '', } }, + created() { + this.$eventHub.$on(THUMBNAILBOOK_ADDED, this.thumbnailBookAdded) + this.$eventHub.$on(THUMBNAILSERIES_ADDED, this.thumbnailSeriesAdded) + }, + beforeDestroy() { + this.$eventHub.$off(THUMBNAILBOOK_ADDED, this.thumbnailBookAdded) + this.$eventHub.$off(THUMBNAILSERIES_ADDED, this.thumbnailSeriesAdded) + }, computed: { - canReadPages (): boolean { + canReadPages(): boolean { return this.$store.getters.mePageStreaming && this.computedItem.type() === ItemTypes.BOOK }, - overlay (): boolean { + overlay(): boolean { return this.onEdit !== undefined || this.onSelected !== undefined || this.bookReady || this.canReadPages || this.actionMenu }, - computedItem (): Item { + computedItem(): Item { return createItem(this.item) }, - disableHover (): boolean { + disableHover(): boolean { return !this.overlay }, - thumbnailUrl (): string { - return this.computedItem.thumbnailUrl() + thumbnailUrl(): string { + return this.computedItem.thumbnailUrl() + this.thumbnailCacheBust }, - title (): string { + title(): string { return this.computedItem.title() }, - subtitleProps (): Object { + subtitleProps(): Object { return this.computedItem.subtitleProps() }, - body (): string { + body(): string { return this.computedItem.body() }, - isInProgress (): boolean { + isInProgress(): boolean { if (this.computedItem.type() === ItemTypes.BOOK) return getReadProgress(this.item as BookDto) === ReadStatus.IN_PROGRESS return false }, - isUnread (): boolean { + isUnread(): boolean { if (this.computedItem.type() === ItemTypes.BOOK) return getReadProgress(this.item as BookDto) === ReadStatus.UNREAD return false }, - unreadCount (): number | undefined { + unreadCount(): number | undefined { if (this.computedItem.type() === ItemTypes.SERIES) return (this.item as SeriesDto).booksUnreadCount + (this.item as SeriesDto).booksInProgressCount return undefined }, - readProgressPercentage (): number { + readProgressPercentage(): number { if (this.computedItem.type() === ItemTypes.BOOK) return getReadProgressPercentage(this.item as BookDto) return 0 }, - bookReady (): boolean { + bookReady(): boolean { if (this.computedItem.type() === ItemTypes.BOOK) { return (this.item as BookDto).media.status === 'READY' } return false }, - to (): RawLocation { + to(): RawLocation { return this.computedItem.to() }, - fabTo (): RawLocation { + fabTo(): RawLocation { return this.computedItem.fabTo() }, }, methods: { - onClick () { + thumbnailBookAdded(event: ThumbnailBookSseDto) { + if (this.thumbnailError && + ((this.computedItem.type() === ItemTypes.BOOK && event.bookId === this.item.id) || (this.computedItem.type() === ItemTypes.SERIES && event.seriesId === this.item.id)) + ) { + this.thumbnailCacheBust = '?' + this.$_.random(1000) + } + }, + thumbnailSeriesAdded(event: ThumbnailSeriesSseDto) { + if (this.thumbnailError && (this.computedItem.type() === ItemTypes.SERIES && event.seriesId === this.item.id)) { + this.thumbnailCacheBust = '?' + this.$_.random(1000) + } + }, + onClick() { if (this.preselect && this.onSelected !== undefined) { this.selectItem() } else if (!this.noLink) { this.goto() } }, - goto () { + goto() { this.$router.push(this.computedItem.to()) }, - selectItem () { + selectItem() { if (this.onSelected !== undefined) { this.onSelected() } }, - editItem () { + editItem() { if (this.onEdit !== undefined) { this.onEdit(this.item) } diff --git a/komga-webui/src/components/LibraryNavigation.vue b/komga-webui/src/components/LibraryNavigation.vue index f0558c0bd..5509a4159 100644 --- a/komga-webui/src/components/LibraryNavigation.vue +++ b/komga-webui/src/components/LibraryNavigation.vue @@ -77,7 +77,7 @@ + + diff --git a/komga-webui/src/components/dialogs/CollectionAddToDialog.vue b/komga-webui/src/components/dialogs/CollectionAddToDialog.vue index 374e377f2..6080b9d81 100644 --- a/komga-webui/src/components/dialogs/CollectionAddToDialog.vue +++ b/komga-webui/src/components/dialogs/CollectionAddToDialog.vue @@ -155,7 +155,6 @@ export default Vue.extend({ try { await this.$komgaCollections.patchCollection(collection.id, toUpdate) - this.$emit('added', collection) this.dialogClose() } catch (e) { this.showSnack(e.message) @@ -170,7 +169,6 @@ export default Vue.extend({ try { const created = await this.$komgaCollections.postCollection(toCreate) - this.$emit('created', created) this.dialogClose() } catch (e) { this.showSnack(e.message) diff --git a/komga-webui/src/components/dialogs/CollectionDeleteDialog.vue b/komga-webui/src/components/dialogs/CollectionDeleteDialog.vue index 1ecc104de..011873be1 100644 --- a/komga-webui/src/components/dialogs/CollectionDeleteDialog.vue +++ b/komga-webui/src/components/dialogs/CollectionDeleteDialog.vue @@ -95,7 +95,6 @@ export default Vue.extend({ async deleteCollection() { try { await this.$komgaCollections.deleteCollection(this.collection.id) - this.$emit('deleted', true) } catch (e) { this.showSnack(e.message) } diff --git a/komga-webui/src/components/dialogs/CollectionEditDialog.vue b/komga-webui/src/components/dialogs/CollectionEditDialog.vue index 63f1a617d..cfdd7b4fd 100644 --- a/komga-webui/src/components/dialogs/CollectionEditDialog.vue +++ b/komga-webui/src/components/dialogs/CollectionEditDialog.vue @@ -138,7 +138,6 @@ export default Vue.extend({ } as CollectionUpdateDto await this.$komgaCollections.patchCollection(this.collection.id, update) - this.$emit('updated', true) } catch (e) { this.showSnack(e.message) } diff --git a/komga-webui/src/components/dialogs/EditBooksDialog.vue b/komga-webui/src/components/dialogs/EditBooksDialog.vue index 5def7d935..50c1a1a5a 100644 --- a/komga-webui/src/components/dialogs/EditBooksDialog.vue +++ b/komga-webui/src/components/dialogs/EditBooksDialog.vue @@ -532,7 +532,6 @@ export default Vue.extend({ for (const b of toUpdate) { try { await this.$komgaBooks.updateMetadata(b.id, metadata) - this.$emit('updated', b) } catch (e) { this.showSnack(e.message) } diff --git a/komga-webui/src/components/dialogs/EditSeriesDialog.vue b/komga-webui/src/components/dialogs/EditSeriesDialog.vue index c346844c8..9369369e5 100644 --- a/komga-webui/src/components/dialogs/EditSeriesDialog.vue +++ b/komga-webui/src/components/dialogs/EditSeriesDialog.vue @@ -591,7 +591,6 @@ export default Vue.extend({ for (const s of toUpdate) { try { await this.$komgaSeries.updateMetadata(s.id, metadata) - this.$emit('updated', s) } catch (e) { this.showSnack(e.message) } diff --git a/komga-webui/src/components/dialogs/LibraryDeleteDialog.vue b/komga-webui/src/components/dialogs/LibraryDeleteDialog.vue index 0d487cac8..ef9536576 100644 --- a/komga-webui/src/components/dialogs/LibraryDeleteDialog.vue +++ b/komga-webui/src/components/dialogs/LibraryDeleteDialog.vue @@ -94,7 +94,6 @@ export default Vue.extend({ async deleteLibrary() { try { await this.$store.dispatch('deleteLibrary', this.library) - this.$emit('deleted', true) } catch (e) { this.showSnack(e.message) } diff --git a/komga-webui/src/components/dialogs/LibraryEditDialog.vue b/komga-webui/src/components/dialogs/LibraryEditDialog.vue index 9206bde5e..67e120ee1 100644 --- a/komga-webui/src/components/dialogs/LibraryEditDialog.vue +++ b/komga-webui/src/components/dialogs/LibraryEditDialog.vue @@ -245,7 +245,6 @@