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)
},