mirror of
https://github.com/gotson/komga.git
synced 2025-12-20 15:34:17 +01:00
fix(webui): dashboard and search results pages would reload entirely upon events
This commit is contained in:
parent
45d4421cd6
commit
043c4d3a73
3 changed files with 98 additions and 49 deletions
|
|
@ -4,26 +4,42 @@ export class PageLoader<T> {
|
|||
|
||||
private currentPage = undefined as unknown as Page<T>
|
||||
private loadedPages: number[] = []
|
||||
private _tick = 0
|
||||
public readonly items: T[] = []
|
||||
|
||||
get page() {
|
||||
return this.currentPage?.number || 0
|
||||
}
|
||||
get hasNextPage() {
|
||||
return !this.currentPage ? false : !this.currentPage.last
|
||||
}
|
||||
|
||||
get tick() {
|
||||
return this._tick
|
||||
}
|
||||
|
||||
constructor(pageable: PageRequest, loader: (pageRequest: PageRequest) => Promise<Page<T>>) {
|
||||
this.pageable = pageable
|
||||
this.loader = loader
|
||||
}
|
||||
|
||||
async reload() {
|
||||
if (!this.currentPage) return this.loadNext()
|
||||
|
||||
const pageable = Object.assign({}, this.pageable,
|
||||
{
|
||||
size: (this.currentPage.number + 1) * (this.pageable.size || 20),
|
||||
page: 0,
|
||||
})
|
||||
const page = await this.loader(pageable)
|
||||
this.items.splice(0, this.items.length, ...page.content)
|
||||
this._tick++
|
||||
}
|
||||
|
||||
async loadNext(): Promise<boolean> {
|
||||
// load first page if nothing has been loaded yet
|
||||
if (!this.currentPage) {
|
||||
this.loadedPages.push(this.pageable.page || 0)
|
||||
this.currentPage = await this.loader(this.pageable)
|
||||
this.items.push(...this.currentPage.content)
|
||||
this._tick++
|
||||
return true
|
||||
}
|
||||
// if the last page has been loaded, do nothing
|
||||
|
|
@ -35,6 +51,7 @@ export class PageLoader<T> {
|
|||
const pageable = Object.assign({}, this.pageable, {page: nextPage})
|
||||
this.currentPage = await this.loader(pageable)
|
||||
this.items.push(...this.currentPage.content)
|
||||
this._tick++
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@
|
|||
<horizontal-scroller
|
||||
v-if="loaderInProgressBooks && loaderInProgressBooks.items.length !== 0"
|
||||
class="mb-4"
|
||||
:tick="loaderInProgressBooks.page"
|
||||
:tick="loaderInProgressBooks.tick"
|
||||
@scroll-changed="(percent) => scrollChanged(loaderInProgressBooks, percent)"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
|
|
@ -72,7 +72,7 @@
|
|||
<horizontal-scroller
|
||||
v-if="loaderOnDeckBooks && loaderOnDeckBooks.items.length !== 0"
|
||||
class="mb-4"
|
||||
:tick="loaderOnDeckBooks.page"
|
||||
:tick="loaderOnDeckBooks.tick"
|
||||
@scroll-changed="(percent) => scrollChanged(loaderOnDeckBooks, percent)"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
|
|
@ -92,7 +92,7 @@
|
|||
<horizontal-scroller
|
||||
v-if="loaderRecentlyReleasedBooks && loaderRecentlyReleasedBooks.items.length !== 0"
|
||||
class="mb-4"
|
||||
:tick="loaderRecentlyReleasedBooks.page"
|
||||
:tick="loaderRecentlyReleasedBooks.tick"
|
||||
@scroll-changed="(percent) => scrollChanged(loaderRecentlyReleasedBooks, percent)"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
|
|
@ -112,7 +112,7 @@
|
|||
<horizontal-scroller
|
||||
v-if="loaderLatestBooks && loaderLatestBooks.items.length !== 0"
|
||||
class="mb-4"
|
||||
:tick="loaderLatestBooks.page"
|
||||
:tick="loaderLatestBooks.tick"
|
||||
@scroll-changed="(percent) => scrollChanged(loaderLatestBooks, percent)"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
|
|
@ -132,7 +132,7 @@
|
|||
<horizontal-scroller
|
||||
v-if="loaderNewSeries && loaderNewSeries.items.length !== 0"
|
||||
class="mb-4"
|
||||
:tick="loaderNewSeries.page"
|
||||
:tick="loaderNewSeries.tick"
|
||||
@scroll-changed="(percent) => scrollChanged(loaderNewSeries, percent)"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
|
|
@ -152,7 +152,7 @@
|
|||
<horizontal-scroller
|
||||
v-if="loaderUpdatedSeries && loaderUpdatedSeries.items.length !== 0"
|
||||
class="mb-4"
|
||||
:tick="loaderUpdatedSeries.page"
|
||||
:tick="loaderUpdatedSeries.tick"
|
||||
@scroll-changed="(percent) => scrollChanged(loaderUpdatedSeries, percent)"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
|
|
@ -172,7 +172,7 @@
|
|||
<horizontal-scroller
|
||||
v-if="loaderRecentlyReadBooks && loaderRecentlyReadBooks.items.length !== 0"
|
||||
class="mb-4"
|
||||
:tick="loaderRecentlyReadBooks.page"
|
||||
:tick="loaderRecentlyReadBooks.tick"
|
||||
@scroll-changed="(percent) => scrollChanged(loaderRecentlyReadBooks, percent)"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
|
|
@ -272,6 +272,7 @@ export default Vue.extend({
|
|||
id: this.libraryId,
|
||||
route: LIBRARY_ROUTE.RECOMMENDED,
|
||||
})
|
||||
this.setupLoaders(this.libraryId)
|
||||
this.loadAll(this.libraryId)
|
||||
},
|
||||
props: {
|
||||
|
|
@ -282,6 +283,7 @@ export default Vue.extend({
|
|||
},
|
||||
watch: {
|
||||
libraryId(val) {
|
||||
this.setupLoaders(val)
|
||||
this.loadAll(val)
|
||||
},
|
||||
'$store.state.komgaLibraries.libraries': {
|
||||
|
|
@ -336,14 +338,9 @@ export default Vue.extend({
|
|||
else if (this.loaderRecentlyReadBooks?.items.some(b => b.id === event.bookId)) this.reload()
|
||||
},
|
||||
reload: throttle(function (this: any) {
|
||||
this.loadAll(this.libraryId)
|
||||
this.loadAll(this.libraryId, true)
|
||||
}, 5000),
|
||||
loadAll(libraryId: string) {
|
||||
this.loading = true
|
||||
this.library = this.getLibraryLazy(libraryId)
|
||||
this.selectedSeries = []
|
||||
this.selectedBooks = []
|
||||
|
||||
setupLoaders(libraryId: string) {
|
||||
this.loaderInProgressBooks = new PageLoader<BookDto>(
|
||||
{sort: ['readProgress.lastModified,desc']},
|
||||
(pageable: PageRequest) => this.$komgaBooks.getBooks(this.getRequestLibraryId(libraryId), pageable, undefined, undefined, [ReadStatus.IN_PROGRESS]),
|
||||
|
|
@ -373,18 +370,38 @@ export default Vue.extend({
|
|||
{},
|
||||
(pageable: PageRequest) => this.$komgaSeries.getUpdatedSeries(this.getRequestLibraryId(libraryId), pageable),
|
||||
)
|
||||
},
|
||||
loadAll(libraryId: string, reload: boolean = false) {
|
||||
this.loading = true
|
||||
this.library = this.getLibraryLazy(libraryId)
|
||||
this.selectedSeries = []
|
||||
this.selectedBooks = []
|
||||
|
||||
Promise.all([
|
||||
this.loaderInProgressBooks.loadNext(),
|
||||
this.loaderOnDeckBooks.loadNext(),
|
||||
this.loaderRecentlyReleasedBooks.loadNext(),
|
||||
this.loaderLatestBooks.loadNext(),
|
||||
this.loaderNewSeries.loadNext(),
|
||||
this.loaderUpdatedSeries.loadNext(),
|
||||
this.loaderRecentlyReadBooks.loadNext(),
|
||||
]).then(() => {
|
||||
this.loading = false
|
||||
})
|
||||
if(reload){
|
||||
Promise.all([
|
||||
this.loaderInProgressBooks.reload(),
|
||||
this.loaderOnDeckBooks.reload(),
|
||||
this.loaderRecentlyReleasedBooks.reload(),
|
||||
this.loaderLatestBooks.reload(),
|
||||
this.loaderNewSeries.reload(),
|
||||
this.loaderUpdatedSeries.reload(),
|
||||
this.loaderRecentlyReadBooks.reload(),
|
||||
]).then(() => {
|
||||
this.loading = false
|
||||
})
|
||||
} else {
|
||||
Promise.all([
|
||||
this.loaderInProgressBooks.loadNext(),
|
||||
this.loaderOnDeckBooks.loadNext(),
|
||||
this.loaderRecentlyReleasedBooks.loadNext(),
|
||||
this.loaderLatestBooks.loadNext(),
|
||||
this.loaderNewSeries.loadNext(),
|
||||
this.loaderUpdatedSeries.loadNext(),
|
||||
this.loaderRecentlyReadBooks.loadNext(),
|
||||
]).then(() => {
|
||||
this.loading = false
|
||||
})
|
||||
}
|
||||
},
|
||||
singleEditSeries(series: SeriesDto) {
|
||||
this.$store.dispatch('dialogUpdateSeries', series)
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@
|
|||
<horizontal-scroller
|
||||
v-if="loaderSeries && loaderSeries.items.length !== 0"
|
||||
class="mb-4"
|
||||
:tick="loaderSeries.page"
|
||||
:tick="loaderSeries.tick"
|
||||
@scroll-changed="(percent) => scrollChanged(loaderSeries, percent)"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
|
|
@ -76,7 +76,7 @@
|
|||
<horizontal-scroller
|
||||
v-if="loaderBooks && loaderBooks.items.length !== 0"
|
||||
class="mb-4"
|
||||
:tick="loaderBooks.page"
|
||||
:tick="loaderBooks.tick"
|
||||
@scroll-changed="(percent) => scrollChanged(loaderBooks, percent)"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
|
|
@ -96,7 +96,7 @@
|
|||
<horizontal-scroller
|
||||
v-if="loaderCollections && loaderCollections.items.length !== 0"
|
||||
class="mb-4"
|
||||
:tick="loaderCollections.page"
|
||||
:tick="loaderCollections.tick"
|
||||
@scroll-changed="(percent) => scrollChanged(loaderCollections, percent)"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
|
|
@ -116,7 +116,7 @@
|
|||
<horizontal-scroller
|
||||
v-if="loaderReadLists && loaderReadLists.items.length !== 0"
|
||||
class="mb-4"
|
||||
:tick="loaderReadLists.page"
|
||||
:tick="loaderReadLists.tick"
|
||||
@scroll-changed="(percent) => scrollChanged(loaderReadLists, percent)"
|
||||
>
|
||||
<template v-slot:prepend>
|
||||
|
|
@ -230,6 +230,7 @@ export default Vue.extend({
|
|||
watch: {
|
||||
'$route.query.q': {
|
||||
handler: function (val) {
|
||||
this.setupLoaders(val)
|
||||
this.loadResults(val)
|
||||
this.selectedBooks = []
|
||||
this.selectedSeries = []
|
||||
|
|
@ -352,29 +353,14 @@ export default Vue.extend({
|
|||
))
|
||||
},
|
||||
reloadResults: throttle(function (this: any) {
|
||||
this.loadResults(this.$route.query.q.toString())
|
||||
this.loadResults(this.$route.query.q.toString(), true)
|
||||
}, 500),
|
||||
async loadResults(search: string) {
|
||||
this.selectedBooks = []
|
||||
this.selectedSeries = []
|
||||
this.selectedCollections = []
|
||||
this.selectedReadLists = []
|
||||
setupLoaders(search: string) {
|
||||
if (search) {
|
||||
this.loading = true
|
||||
|
||||
this.loaderSeries = new PageLoader<SeriesDto>({size: this.pageSize}, (pageable: PageRequest) => this.$komgaSeries.getSeries(undefined, pageable, search))
|
||||
this.loaderBooks = new PageLoader<BookDto>({size: this.pageSize}, (pageable: PageRequest) => this.$komgaBooks.getBooks(undefined, pageable, search))
|
||||
this.loaderCollections = new PageLoader<CollectionDto>({size: this.pageSize}, (pageable: PageRequest) => this.$komgaCollections.getCollections(undefined, pageable, search))
|
||||
this.loaderReadLists = new PageLoader<ReadListDto>({size: this.pageSize}, (pageable: PageRequest) => this.$komgaReadLists.getReadLists(undefined, pageable, search))
|
||||
|
||||
Promise.all([
|
||||
this.loaderSeries.loadNext(),
|
||||
this.loaderBooks.loadNext(),
|
||||
this.loaderCollections.loadNext(),
|
||||
this.loaderReadLists.loadNext(),
|
||||
]).then(() => {
|
||||
this.loading = false
|
||||
})
|
||||
} else {
|
||||
this.loaderSeries = null as unknown as PageLoader<SeriesDto>
|
||||
this.loaderBooks = null as unknown as PageLoader<BookDto>
|
||||
|
|
@ -382,6 +368,35 @@ export default Vue.extend({
|
|||
this.loaderReadLists = null as unknown as PageLoader<ReadListDto>
|
||||
}
|
||||
},
|
||||
async loadResults(search: string, reload: boolean = false) {
|
||||
this.selectedBooks = []
|
||||
this.selectedSeries = []
|
||||
this.selectedCollections = []
|
||||
this.selectedReadLists = []
|
||||
|
||||
if (search) {
|
||||
this.loading = true
|
||||
if (reload) {
|
||||
Promise.all([
|
||||
this.loaderSeries.reload(),
|
||||
this.loaderBooks.reload(),
|
||||
this.loaderCollections.reload(),
|
||||
this.loaderReadLists.reload(),
|
||||
]).then(() => {
|
||||
this.loading = false
|
||||
})
|
||||
} else {
|
||||
Promise.all([
|
||||
this.loaderSeries.loadNext(),
|
||||
this.loaderBooks.loadNext(),
|
||||
this.loaderCollections.loadNext(),
|
||||
this.loaderReadLists.loadNext(),
|
||||
]).then(() => {
|
||||
this.loading = false
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Reference in a new issue