diff --git a/komga-webui/src/components/CollectionsExpansionPanels.vue b/komga-webui/src/components/CollectionsExpansionPanels.vue
index e55d3e48b..1c9f18a5c 100644
--- a/komga-webui/src/components/CollectionsExpansionPanels.vue
+++ b/komga-webui/src/components/CollectionsExpansionPanels.vue
@@ -5,14 +5,18 @@
>
{{ $t('collections_expansion_panel.title', {name: c.name}) }}
-
+ scrollChanged(collectionsLoaders[index], percent)"
+ >
{{ $t('collections_expansion_panel.manage_collection') }}
+ >{{ $t('collections_expansion_panel.manage_collection') }}
+
- {
return {
collectionPanel: undefined as number | undefined,
- collectionsContent: [[]] as any[],
+ collectionsLoaders: [] as PageLoader[],
}
},
watch: {
collections: {
- handler (val) {
+ handler(val: CollectionDto[]) {
this.collectionPanel = undefined
- this.collectionsContent = [...Array(val.length)].map(elem => new Array(0))
+ this.collectionsLoaders = val.map(coll => new PageLoader(
+ {},
+ (pageable: PageRequest) => this.$komgaCollections.getSeries(coll.id, pageable),
+ (x: SeriesDto) => {
+ x.context = {origin: ContextOrigin.COLLECTION, id: coll.id}
+ return x
+ },
+ ))
},
immediate: true,
},
- async collectionPanel (val) {
+ async collectionPanel(val) {
if (val !== undefined) {
- const collId = this.collections[val].id
- if (this.$_.isEmpty(this.collectionsContent[val])) {
- const content = (await this.$komgaCollections.getSeries(collId, { unpaged: true } as PageRequest)).content
- content.forEach((x: SeriesDto) => x.context = { origin: ContextOrigin.COLLECTION, id: collId })
- this.collectionsContent.splice(val, 1, content)
+ if (!this.collectionsLoaders[val].hasLoadedAny) {
+ this.collectionsLoaders[val].loadNext()
}
}
},
},
+ methods: {
+ async scrollChanged(loader: PageLoader, percent: number) {
+ if (percent > 0.95) await loader.loadNext()
+ },
+ },
})
diff --git a/komga-webui/src/components/ReadListsExpansionPanels.vue b/komga-webui/src/components/ReadListsExpansionPanels.vue
index 21de8ab35..0df7c5712 100644
--- a/komga-webui/src/components/ReadListsExpansionPanels.vue
+++ b/komga-webui/src/components/ReadListsExpansionPanels.vue
@@ -5,14 +5,18 @@
>
{{ $t('readlists_expansion_panel.title', {name: r.name}) }}
-
+ scrollChanged(readListsLoaders[index], percent)"
+ >
{{ $t('readlists_expansion_panel.manage_readlist') }}
+ >{{ $t('readlists_expansion_panel.manage_readlist') }}
+
- [],
}
},
watch: {
readLists: {
- handler (val) {
+ handler(val: ReadListDto[]) {
this.readListPanel = undefined
- this.readListsContent = [...Array(val.length)].map(elem => new Array(0))
+ this.readListsLoaders = val.map(rl => new PageLoader(
+ {},
+ (pageable: PageRequest) => this.$komgaReadLists.getBooks(rl.id, pageable),
+ (x: BookDto) => {
+ x.context = {origin: ContextOrigin.READLIST, id: rl.id}
+ return x
+ },
+ ))
},
immediate: true,
},
- async readListPanel (val) {
+ async readListPanel(val) {
if (val !== undefined) {
- const rlId = this.readLists[val].id
- if (this.$_.isEmpty(this.readListsContent[val])) {
- const content = (await this.$komgaReadLists.getBooks(rlId, { unpaged: true } as PageRequest)).content
- content.forEach((x: BookDto) => x.context = { origin: ContextOrigin.READLIST, id: rlId })
- this.readListsContent.splice(val, 1, content)
+ if (!this.readListsLoaders[val].hasLoadedAny) {
+ this.readListsLoaders[val].loadNext()
}
}
},
},
+ methods: {
+ async scrollChanged(loader: PageLoader, percent: number) {
+ if (percent > 0.95) await loader.loadNext()
+ },
+ },
})
diff --git a/komga-webui/src/types/pageLoader.ts b/komga-webui/src/types/pageLoader.ts
index 9f0dd3809..8bf03a23e 100644
--- a/komga-webui/src/types/pageLoader.ts
+++ b/komga-webui/src/types/pageLoader.ts
@@ -1,6 +1,7 @@
export class PageLoader {
private readonly pageable: PageRequest
private readonly loader: (pageRequest: PageRequest) => Promise>
+ private readonly postProcessor: (item: T) => T
private currentPage = undefined as unknown as Page
private loadedPages: number[] = []
@@ -15,9 +16,15 @@ export class PageLoader {
return this._tick
}
- constructor(pageable: PageRequest, loader: (pageRequest: PageRequest) => Promise>) {
+ // whether anything has been loaded yet
+ get hasLoadedAny() {
+ return this.currentPage
+ }
+
+ constructor(pageable: PageRequest, loader: (pageRequest: PageRequest) => Promise>, postProcessor: (item: T) => T = (item) => item) {
this.pageable = pageable
this.loader = loader
+ this.postProcessor = postProcessor
}
async reload() {
@@ -29,7 +36,7 @@ export class PageLoader {
page: 0,
})
const page = await this.loader(pageable)
- this.items.splice(0, this.items.length, ...page.content)
+ this.items.splice(0, this.items.length, ...page.content.map(this.postProcessor))
this._tick++
}
@@ -38,7 +45,7 @@ export class PageLoader {
if (!this.currentPage) {
this.loadedPages.push(this.pageable.page || 0)
this.currentPage = await this.loader(this.pageable)
- this.items.push(...this.currentPage.content)
+ this.items.push(...this.currentPage.content.map(this.postProcessor))
this._tick++
return true
}
@@ -50,7 +57,7 @@ export class PageLoader {
this.loadedPages.push(nextPage)
const pageable = Object.assign({}, this.pageable, {page: nextPage})
this.currentPage = await this.loader(pageable)
- this.items.push(...this.currentPage.content)
+ this.items.push(...this.currentPage.content.map(this.postProcessor))
this._tick++
return true
}