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 @@