diff --git a/komga-webui/package-lock.json b/komga-webui/package-lock.json index a6f948ee3..c24ae64d3 100644 --- a/komga-webui/package-lock.json +++ b/komga-webui/package-lock.json @@ -15670,6 +15670,11 @@ "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", "dev": true }, + "vue-typed-mixins": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/vue-typed-mixins/-/vue-typed-mixins-0.2.0.tgz", + "integrity": "sha512-0OxuinandPWv3nm5k/reYkuKtX3jjPZ40Sy9roJz0ih8PUzmI7zSRiXFEJ62LsyRegw9Tqy+qMkajk7ipKP8Vg==" + }, "vuelidate": { "version": "0.7.5", "resolved": "https://registry.npmjs.org/vuelidate/-/vuelidate-0.7.5.tgz", diff --git a/komga-webui/package.json b/komga-webui/package.json index 647b2e701..a96c9f405 100644 --- a/komga-webui/package.json +++ b/komga-webui/package.json @@ -18,6 +18,7 @@ "vue-cookies": "^1.6.1", "vue-line-clamp": "^1.3.2", "vue-router": "^3.1.4", + "vue-typed-mixins": "^0.2.0", "vuelidate": "^0.7.5", "vuetify": "^2.2.4", "vuex": "^3.1.2", diff --git a/komga-webui/src/mixins/VisibleElements.ts b/komga-webui/src/mixins/VisibleElements.ts new file mode 100644 index 000000000..5c4e3e0cc --- /dev/null +++ b/komga-webui/src/mixins/VisibleElements.ts @@ -0,0 +1,21 @@ +import Vue from 'vue' + +const visibleElements = Vue.extend({ + data: () => { + return { + visibleElements: [] as number[] + } + }, + methods: { + async onElementIntersect (entries: any, observer: any, isIntersecting: boolean) { + const elementIndex = Number(entries[0].target.dataset['index']) + if (isIntersecting) { + this.visibleElements.push(elementIndex) + } else { + this.$_.pull(this.visibleElements, elementIndex) + } + } + } +}) + +export default visibleElements diff --git a/komga-webui/src/views/BrowseLibraries.vue b/komga-webui/src/views/BrowseLibraries.vue index 6129199a2..2c7f59356 100644 --- a/komga-webui/src/views/BrowseLibraries.vue +++ b/komga-webui/src/views/BrowseLibraries.vue @@ -57,7 +57,7 @@ :loading="s === null" type="card, text" class="ma-3 mx-2" - v-intersect="onCardIntersect" + v-intersect="onElementIntersect" :data-index="i" > @@ -88,10 +88,11 @@ import SortMenuButton from '@/components/SortMenuButton.vue' import ToolbarSticky from '@/components/ToolbarSticky.vue' import { computeCardWidth } from '@/functions/grid-utilities' import { parseQuerySort } from '@/functions/query-params' +import VisibleElements from '@/mixins/VisibleElements' import { LoadState, SeriesStatus } from '@/types/common' -import Vue from 'vue' +import mixins from 'vue-typed-mixins' -export default Vue.extend({ +export default mixins(VisibleElements).extend({ name: 'BrowseLibraries', components: { LibraryActionsMenu, CardSeries, EmptyState, ToolbarSticky, SortMenuButton, Badge }, data: () => { @@ -100,7 +101,6 @@ export default Vue.extend({ series: [] as SeriesDto[], pagesState: [] as LoadState[], pageSize: 20, - visibleCards: [] as number[], totalElements: null as number | null, sortOptions: [{ name: 'Name', key: 'name' }, { name: 'Date added', key: 'createdDate' }, { name: 'Date updated', @@ -128,7 +128,7 @@ export default Vue.extend({ this.updateRoute() this.reloadData(this.libraryId) }, - async visibleCards (val) { + async visibleElements (val) { for (const i of val) { const pageNumber = Math.floor(i / this.pageSize) if (this.pagesState[pageNumber] === undefined || this.pagesState[pageNumber] === LoadState.NotLoaded) { @@ -182,18 +182,10 @@ export default Vue.extend({ parseQueryFilterStatus (queryStatus: any): string[] { return queryStatus ? queryStatus.toString().split(',').filter((x: string) => Object.keys(SeriesStatus).includes(x)) : [] }, - async onCardIntersect (entries: any, observer: any, isIntersecting: boolean) { - const elementIndex = Number(entries[0].target.dataset['index']) - if (isIntersecting) { - this.visibleCards.push(elementIndex) - } else { - this.$_.pull(this.visibleCards, elementIndex) - } - }, reloadData (libraryId: number) { this.totalElements = null this.pagesState = [] - this.visibleCards = [] + this.visibleElements = [] this.series = Array(this.pageSize).fill(null) this.loadInitialData(libraryId) }, diff --git a/komga-webui/src/views/BrowseSeries.vue b/komga-webui/src/views/BrowseSeries.vue index cede26cf3..f67393822 100644 --- a/komga-webui/src/views/BrowseSeries.vue +++ b/komga-webui/src/views/BrowseSeries.vue @@ -75,7 +75,7 @@ :loading="b === null" type="card, text" class="ma-3 mx-2" - v-intersect="onCardIntersect" + v-intersect="onElementIntersect" :data-index="i" > @@ -94,10 +94,11 @@ import ToolbarSticky from '@/components/ToolbarSticky.vue' import { computeCardWidth } from '@/functions/grid-utilities' import { parseQuerySort } from '@/functions/query-params' import { seriesThumbnailUrl } from '@/functions/urls' +import VisibleElements from '@/mixins/VisibleElements' import { LoadState } from '@/types/common' -import Vue from 'vue' +import mixins from 'vue-typed-mixins' -export default Vue.extend({ +export default mixins(VisibleElements).extend({ name: 'BrowseSeries', components: { CardBook, ToolbarSticky, SortMenuButton, Badge }, data: () => { @@ -106,7 +107,6 @@ export default Vue.extend({ books: [] as BookDto[], pagesState: [] as LoadState[], pageSize: 20, - visibleCards: [] as number[], totalElements: null as number | null, sortOptions: [{ name: 'Number', key: 'number' }, { name: 'Date added', key: 'createdDate' }, { name: 'File size', @@ -139,7 +139,7 @@ export default Vue.extend({ this.updateRoute() this.reloadData(this.seriesId) }, - async visibleCards (val) { + async visibleElements (val) { for (const i of val) { const pageNumber = Math.floor(i / this.pageSize) if (this.pagesState[pageNumber] === undefined || this.pagesState[pageNumber] === LoadState.NotLoaded) { @@ -186,14 +186,6 @@ export default Vue.extend({ parseQuerySortOrDefault (querySort: any): SortActive { return parseQuerySort(querySort, this.sortOptions) || this.$_.clone(this.sortDefault) }, - async onCardIntersect (entries: any, observer: any, isIntersecting: boolean) { - const elementIndex = Number(entries[0].target.dataset['index']) - if (isIntersecting) { - this.visibleCards.push(elementIndex) - } else { - this.$_.pull(this.visibleCards, elementIndex) - } - }, updateRoute (index?: string) { this.$router.replace({ name: this.$route.name, @@ -207,7 +199,7 @@ export default Vue.extend({ reloadData (seriesId: number) { this.totalElements = null this.pagesState = [] - this.visibleCards = [] + this.visibleElements = [] this.books = Array(this.pageSize).fill(null) this.loadInitialData(seriesId) },