add infinite loading to album view

This commit is contained in:
Thomas Amland 2020-09-20 17:33:21 +02:00
parent 6c290689c4
commit 4be81d0e35
6 changed files with 83 additions and 16 deletions

View File

@ -13,6 +13,7 @@
"bootstrap-vue": "^2.17.0", "bootstrap-vue": "^2.17.0",
"md5-es": "1.8.2", "md5-es": "1.8.2",
"vue": "^2.6.12", "vue": "^2.6.12",
"vue-infinite-loading": "2.4.5",
"vue-router": "^3.4.3", "vue-router": "^3.4.3",
"vuex": "^3.5.1" "vuex": "^3.5.1"
}, },

View File

@ -7,9 +7,8 @@
</router-link> </router-link>
</li> </li>
</ul> </ul>
<ContentLoader #default :loading="albums == null">
<AlbumList :items="albums" /> <AlbumList :items="albums" />
</ContentLoader> <InfiniteLoader :key="sort" :loading="loading" :has-more="hasMore" @loadMore="loadMore" />
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -26,7 +25,10 @@
}, },
data() { data() {
return { return {
albums: null as null | Album[], albums: [] as | Album[],
loading: false,
offset: 0 as number,
hasMore: true,
} }
}, },
computed: { computed: {
@ -42,14 +44,23 @@
}, },
watch: { watch: {
sort: { sort: {
immediate: true, handler() {
handler(value: AlbumSort) { this.albums = []
this.albums = null this.offset = 0
this.$api.getAlbums(value).then(albums => { this.hasMore = true
this.albums = albums
})
} }
} }
}, },
methods: {
loadMore() {
this.loading = true
this.$api.getAlbums(this.sort as AlbumSort, 50, this.offset).then(albums => {
this.albums.push(...albums)
this.offset += albums.length
this.hasMore = albums.length > 0
this.loading = false
})
}
}
}) })
</script> </script>

View File

@ -142,7 +142,7 @@ export class API {
.map(this.normalizeArtist, this) .map(this.normalizeArtist, this)
} }
async getAlbums(sort: AlbumSort, size = 500): Promise<Album[]> { async getAlbums(sort: AlbumSort, size: number, offset = 0): Promise<Album[]> {
const type = { const type = {
'a-z': 'alphabeticalByName', 'a-z': 'alphabeticalByName',
'recently-added': 'newest', 'recently-added': 'newest',
@ -151,11 +151,7 @@ export class API {
random: 'random', random: 'random',
}[sort] }[sort]
const params = { const params = { type, offset, size }
type,
offset: '0',
size: size,
}
const response = await this.get('rest/getAlbumList2', params) const response = await this.get('rest/getAlbumList2', params)
const albums = response.albumList2?.album || [] const albums = response.albumList2?.album || []
return albums.map(this.normalizeAlbum, this) return albums.map(this.normalizeAlbum, this)

View File

@ -0,0 +1,52 @@
<template>
<infinite-loading ref="inf" force-use-infinite-wrapper @infinite="loadMore">
<template slot="spinner">
<div class="d-flex justify-content-center my-4">
<span class="spinner-border" />
</div>
</template>
<template slot="no-more">
<span />
</template>
<template slot="no-results">
<span />
</template>
</infinite-loading>
</template>
<script lang="ts">
import Vue from 'vue'
import InfiniteLoading from 'vue-infinite-loading'
export default Vue.extend({
components: {
InfiniteLoading,
},
props: {
loading: { type: Boolean, required: true },
hasMore: { type: Boolean, required: true },
},
watch: {
loading: {
handler(value: boolean) {
if (!this.hasMore) {
(this.$refs.inf as any).stateChanger.complete()
} else if (!value) {
(this.$refs.inf as any).stateChanger.loaded()
}
}
},
hasMore: {
handler(value: boolean) {
if (!value) {
(this.$refs.inf as any).stateChanger.complete()
}
}
}
},
methods: {
loadMore() {
this.$emit('loadMore')
},
}
})
</script>

View File

@ -2,6 +2,7 @@ import Vue from 'vue'
import ContentLoader from './ContentLoader.vue' import ContentLoader from './ContentLoader.vue'
import ExternalLink from './ExternalLink.vue' import ExternalLink from './ExternalLink.vue'
import Icon from './Icon.vue' import Icon from './Icon.vue'
import InfiniteLoader from './InfiniteLoader.vue'
import OverflowMenu from './OverflowMenu.vue' import OverflowMenu from './OverflowMenu.vue'
import Tiles from './Tiles.vue' import Tiles from './Tiles.vue'
import Tile from './Tile.vue' import Tile from './Tile.vue'
@ -10,6 +11,7 @@ const components = {
ContentLoader, ContentLoader,
ExternalLink, ExternalLink,
Icon, Icon,
InfiniteLoader,
OverflowMenu, OverflowMenu,
Tiles, Tiles,
Tile, Tile,

View File

@ -9361,6 +9361,11 @@ vue-hot-reload-api@^2.3.0:
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2" resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2"
integrity sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog== integrity sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==
vue-infinite-loading@2.4.5:
version "2.4.5"
resolved "https://registry.yarnpkg.com/vue-infinite-loading/-/vue-infinite-loading-2.4.5.tgz#cc20fd40af7f20188006443c99b60470cf1de1b3"
integrity sha512-xhq95Mxun060bRnsOoLE2Be6BR7jYwuC89kDe18+GmCLVrRA/dU0jrGb12Xu6NjmKs+iTW0AA6saSEmEW4cR7g==
"vue-loader-v16@npm:vue-loader@^16.0.0-beta.7": "vue-loader-v16@npm:vue-loader@^16.0.0-beta.7":
version "16.0.0-beta.7" version "16.0.0-beta.7"
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-16.0.0-beta.7.tgz#6f2726fa0e2b1fbae67895c47593bbf69f2b9ab8" resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-16.0.0-beta.7.tgz#6f2726fa0e2b1fbae67895c47593bbf69f2b9ab8"