fix(webui): dashboard and search results pages would reload entirely upon events

This commit is contained in:
Gauthier Roebroeck 2021-09-10 22:27:10 +08:00
parent 45d4421cd6
commit 043c4d3a73
3 changed files with 98 additions and 49 deletions

View file

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

View file

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

View file

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