[web] Confine the use of VueEternalLoading to one component

This commit is contained in:
Alain Nussbaumer 2025-03-28 15:36:45 +01:00
parent f5aecdc4a4
commit 2e4e741e9a
10 changed files with 148 additions and 120 deletions

File diff suppressed because one or more lines are too long

View File

@ -13,6 +13,7 @@
@open="open(item)" @open="open(item)"
@open-details="openDetails(item)" @open-details="openDetails(item)"
/> />
<loader-list-item :load="load" :loaded="loaded" />
<modal-dialog-album-spotify <modal-dialog-album-spotify
:item="selectedItem" :item="selectedItem"
:show="showDetailsModal" :show="showDetailsModal"
@ -22,13 +23,18 @@
<script> <script>
import ListItem from '@/components/ListItem.vue' import ListItem from '@/components/ListItem.vue'
import LoaderListItem from '@/components/LoaderListItem.vue'
import ModalDialogAlbumSpotify from '@/components/ModalDialogAlbumSpotify.vue' import ModalDialogAlbumSpotify from '@/components/ModalDialogAlbumSpotify.vue'
import { useSettingsStore } from '@/stores/settings' import { useSettingsStore } from '@/stores/settings'
export default { export default {
name: 'ListAlbumsSpotify', name: 'ListAlbumsSpotify',
components: { ListItem, ModalDialogAlbumSpotify }, components: { ListItem, LoaderListItem, ModalDialogAlbumSpotify },
props: { items: { required: true, type: Object } }, props: {
items: { required: true, type: Object },
load: { default: null, type: Function },
loaded: { default: true, type: Boolean }
},
setup() { setup() {
return { settingsStore: useSettingsStore() } return { settingsStore: useSettingsStore() }
}, },

View File

@ -8,6 +8,7 @@
@open="open(item)" @open="open(item)"
@open-details="openDetails(item)" @open-details="openDetails(item)"
/> />
<loader-list-item :load="load" :loaded="loaded" />
<modal-dialog-artist-spotify <modal-dialog-artist-spotify
:item="selectedItem" :item="selectedItem"
:show="showDetailsModal" :show="showDetailsModal"
@ -17,13 +18,17 @@
<script> <script>
import ListItem from '@/components/ListItem.vue' import ListItem from '@/components/ListItem.vue'
import LoaderListItem from '@/components/LoaderListItem.vue'
import ModalDialogArtistSpotify from '@/components/ModalDialogArtistSpotify.vue' import ModalDialogArtistSpotify from '@/components/ModalDialogArtistSpotify.vue'
export default { export default {
name: 'ListArtistsSpotify', name: 'ListArtistsSpotify',
components: { ListItem, ModalDialogArtistSpotify }, components: { ListItem, LoaderListItem, ModalDialogArtistSpotify },
props: { items: { required: true, type: Object } }, props: {
items: { required: true, type: Object },
load: { default: null, type: Function },
loaded: { default: true, type: Boolean }
},
data() { data() {
return { selectedItem: {}, showDetailsModal: false } return { selectedItem: {}, showDetailsModal: false }
}, },

View File

@ -8,6 +8,7 @@
@open="open(item)" @open="open(item)"
@open-details="openDetails(item)" @open-details="openDetails(item)"
/> />
<loader-list-item :load="load" :loaded="loaded" />
<modal-dialog-playlist-spotify <modal-dialog-playlist-spotify
:item="selectedItem" :item="selectedItem"
:show="showDetailsModal" :show="showDetailsModal"
@ -17,12 +18,17 @@
<script> <script>
import ListItem from '@/components/ListItem.vue' import ListItem from '@/components/ListItem.vue'
import LoaderListItem from '@/components/LoaderListItem.vue'
import ModalDialogPlaylistSpotify from '@/components/ModalDialogPlaylistSpotify.vue' import ModalDialogPlaylistSpotify from '@/components/ModalDialogPlaylistSpotify.vue'
export default { export default {
name: 'ListPlaylistsSpotify', name: 'ListPlaylistsSpotify',
components: { ListItem, ModalDialogPlaylistSpotify }, components: { ListItem, LoaderListItem, ModalDialogPlaylistSpotify },
props: { items: { required: true, type: Object } }, props: {
items: { required: true, type: Object },
load: { default: null, type: Function },
loaded: { default: true, type: Boolean }
},
data() { data() {
return { selectedItem: {}, showDetailsModal: false } return { selectedItem: {}, showDetailsModal: false }

View File

@ -19,6 +19,7 @@
/>) />)
</template> </template>
</list-item> </list-item>
<loader-list-item :load="load" :loaded="loaded" />
<modal-dialog-track-spotify <modal-dialog-track-spotify
:item="selectedItem" :item="selectedItem"
:show="showDetailsModal" :show="showDetailsModal"
@ -28,15 +29,18 @@
<script> <script>
import ListItem from '@/components/ListItem.vue' import ListItem from '@/components/ListItem.vue'
import LoaderListItem from '@/components/LoaderListItem.vue'
import ModalDialogTrackSpotify from '@/components/ModalDialogTrackSpotify.vue' import ModalDialogTrackSpotify from '@/components/ModalDialogTrackSpotify.vue'
import webapi from '@/webapi' import webapi from '@/webapi'
export default { export default {
name: 'ListTracksSpotify', name: 'ListTracksSpotify',
components: { ListItem, ModalDialogTrackSpotify }, components: { ListItem, LoaderListItem, ModalDialogTrackSpotify },
props: { props: {
contextUri: { default: '', type: String }, contextUri: { default: '', type: String },
items: { required: true, type: Object } items: { required: true, type: Object },
load: { default: null, type: Function },
loaded: { default: true, type: Boolean }
}, },
data() { data() {
return { selectedItem: {}, showDetailsModal: false } return { selectedItem: {}, showDetailsModal: false }

View File

@ -0,0 +1,30 @@
<template>
<vue-eternal-loading v-if="load && !loaded" :load="load">
<template #loading>
<div class="columns is-centered">
<div class="column has-text-centered">
<mdicon class="icon mdi-spin" name="loading" />
</div>
</div>
</template>
<template #no-more>
<br />
</template>
<template #no-results>
<br />
</template>
</vue-eternal-loading>
</template>
<script>
import { VueEternalLoading } from '@ts-pro/vue-eternal-loading'
export default {
name: 'LoaderListItem',
components: { VueEternalLoading },
props: {
load: { default: null, type: Function },
loaded: { default: true, type: Boolean }
}
}
</script>

View File

@ -34,10 +34,12 @@ import webapi from '@/webapi'
const dataObject = { const dataObject = {
load(to) { load(to) {
const spotifyApi = new SpotifyWebApi() return webapi.spotify().then(({ data }) => {
spotifyApi.setAccessToken(useServicesStore().spotify.webapi_token) const spotifyApi = new SpotifyWebApi()
return spotifyApi.getAlbum(to.params.id, { spotifyApi.setAccessToken(data.webapi_token)
market: useServicesStore().spotify.webapi_country return spotifyApi.getAlbum(to.params.id, {
market: useServicesStore().spotify.webapi_country
})
}) })
}, },
set(vm, response) { set(vm, response) {

View File

@ -12,22 +12,7 @@
/> />
</template> </template>
<template #content> <template #content>
<list-albums-spotify :items="albums" /> <list-albums-spotify :items="albums" :load="load" :loaded="loaded" />
<vue-eternal-loading v-if="offset < total" :load="load">
<template #loading>
<div class="columns is-centered">
<div class="column has-text-centered">
<mdicon class="icon mdi-spin" name="loading" />
</div>
</div>
</template>
<template #no-more>
<br />
</template>
<template #no-results>
<br />
</template>
</vue-eternal-loading>
</template> </template>
</content-with-heading> </content-with-heading>
<modal-dialog-artist-spotify <modal-dialog-artist-spotify
@ -44,7 +29,6 @@ import HeadingTitle from '@/components/HeadingTitle.vue'
import ListAlbumsSpotify from '@/components/ListAlbumsSpotify.vue' import ListAlbumsSpotify from '@/components/ListAlbumsSpotify.vue'
import ModalDialogArtistSpotify from '@/components/ModalDialogArtistSpotify.vue' import ModalDialogArtistSpotify from '@/components/ModalDialogArtistSpotify.vue'
import SpotifyWebApi from 'spotify-web-api-js' import SpotifyWebApi from 'spotify-web-api-js'
import { VueEternalLoading } from '@ts-pro/vue-eternal-loading'
import { useServicesStore } from '@/stores/services' import { useServicesStore } from '@/stores/services'
import webapi from '@/webapi' import webapi from '@/webapi'
@ -52,17 +36,19 @@ const PAGE_SIZE = 50
const dataObject = { const dataObject = {
load(to) { load(to) {
const spotifyApi = new SpotifyWebApi() return webapi.spotify().then(({ data }) => {
spotifyApi.setAccessToken(useServicesStore().spotify.webapi_token) const spotifyApi = new SpotifyWebApi()
return Promise.all([ spotifyApi.setAccessToken(data.webapi_token)
spotifyApi.getArtist(to.params.id), return Promise.all([
spotifyApi.getArtistAlbums(to.params.id, { spotifyApi.getArtist(to.params.id),
include_groups: 'album,single', spotifyApi.getArtistAlbums(to.params.id, {
limit: PAGE_SIZE, include_groups: 'album,single',
market: useServicesStore().spotify.webapi_country, limit: PAGE_SIZE,
offset: 0 market: useServicesStore().spotify.webapi_country,
}) offset: 0
]) })
])
})
}, },
set(vm, response) { set(vm, response) {
vm.artist = response.shift() vm.artist = response.shift()
@ -80,8 +66,7 @@ export default {
ControlButton, ControlButton,
HeadingTitle, HeadingTitle,
ListAlbumsSpotify, ListAlbumsSpotify,
ModalDialogArtistSpotify, ModalDialogArtistSpotify
VueEternalLoading
}, },
beforeRouteEnter(to, from, next) { beforeRouteEnter(to, from, next) {
dataObject.load(to).then((response) => { dataObject.load(to).then((response) => {
@ -106,6 +91,9 @@ export default {
subtitle: [{ count: this.total, key: 'count.albums' }], subtitle: [{ count: this.total, key: 'count.albums' }],
title: this.artist.name title: this.artist.name
} }
},
loaded() {
return !(this.offset < this.total)
} }
}, },
methods: { methods: {
@ -115,18 +103,20 @@ export default {
this.offset += data.limit this.offset += data.limit
}, },
load({ loaded }) { load({ loaded }) {
const spotifyApi = new SpotifyWebApi() webapi.spotify().then(({ data }) => {
spotifyApi.setAccessToken(this.servicesStore.spotify.webapi_token) const spotifyApi = new SpotifyWebApi()
spotifyApi spotifyApi.setAccessToken(data.webapi_token)
.getArtistAlbums(this.artist.id, { spotifyApi
include_groups: 'album,single', .getArtistAlbums(this.artist.id, {
limit: PAGE_SIZE, include_groups: 'album,single',
offset: this.offset limit: PAGE_SIZE,
}) offset: this.offset
.then((data) => { })
this.appendAlbums(data) .then((albums) => {
loaded(data.items.length, PAGE_SIZE) this.appendAlbums(albums)
}) loaded(albums.items.length, PAGE_SIZE)
})
})
}, },
openDetails() { openDetails() {
this.showDetailsModal = true this.showDetailsModal = true

View File

@ -17,19 +17,12 @@
/> />
</template> </template>
<template #content> <template #content>
<list-tracks-spotify :items="tracks" :context-uri="playlist.uri" /> <list-tracks-spotify
<vue-eternal-loading v-if="offset < total" :load="load"> :context-uri="playlist.uri"
<template #loading> :items="tracks"
<div class="columns is-centered"> :load="load"
<div class="column has-text-centered"> :loaded="loaded"
<mdicon class="icon mdi-spin" name="loading" /> />
</div>
</div>
</template>
<template #no-more>
<br />
</template>
</vue-eternal-loading>
</template> </template>
</content-with-heading> </content-with-heading>
<modal-dialog-playlist-spotify <modal-dialog-playlist-spotify
@ -46,7 +39,6 @@ import HeadingTitle from '@/components/HeadingTitle.vue'
import ListTracksSpotify from '@/components/ListTracksSpotify.vue' import ListTracksSpotify from '@/components/ListTracksSpotify.vue'
import ModalDialogPlaylistSpotify from '@/components/ModalDialogPlaylistSpotify.vue' import ModalDialogPlaylistSpotify from '@/components/ModalDialogPlaylistSpotify.vue'
import SpotifyWebApi from 'spotify-web-api-js' import SpotifyWebApi from 'spotify-web-api-js'
import { VueEternalLoading } from '@ts-pro/vue-eternal-loading'
import { useServicesStore } from '@/stores/services' import { useServicesStore } from '@/stores/services'
import webapi from '@/webapi' import webapi from '@/webapi'
@ -81,8 +73,7 @@ export default {
ControlButton, ControlButton,
HeadingTitle, HeadingTitle,
ListTracksSpotify, ListTracksSpotify,
ModalDialogPlaylistSpotify, ModalDialogPlaylistSpotify
VueEternalLoading
}, },
beforeRouteEnter(to, from, next) { beforeRouteEnter(to, from, next) {
dataObject.load(to).then((response) => { dataObject.load(to).then((response) => {
@ -112,6 +103,9 @@ export default {
} }
} }
return {} return {}
},
loaded() {
return !(this.offset < this.total)
} }
}, },
methods: { methods: {

View File

@ -35,19 +35,12 @@
<heading-title :content="{ title: $t(`page.search.${type}s`) }" /> <heading-title :content="{ title: $t(`page.search.${type}s`) }" />
</template> </template>
<template #content> <template #content>
<component :is="components[type]" :items="items.items" /> <component
<vue-eternal-loading v-if="expanded" :load="searchNext"> :is="components[type]"
<template #loading> :items="items.items"
<div class="columns is-centered"> :load="searchNext"
<div class="column has-text-centered"> :loaded="!expanded"
<mdicon class="icon mdi-spin" name="loading" /> />
</div>
</div>
</template>
<template #no-more>
<br />
</template>
</vue-eternal-loading>
</template> </template>
<template v-if="!expanded" #footer> <template v-if="!expanded" #footer>
<control-button <control-button
@ -78,7 +71,6 @@ import ListPlaylistsSpotify from '@/components/ListPlaylistsSpotify.vue'
import ListTracksSpotify from '@/components/ListTracksSpotify.vue' import ListTracksSpotify from '@/components/ListTracksSpotify.vue'
import SpotifyWebApi from 'spotify-web-api-js' import SpotifyWebApi from 'spotify-web-api-js'
import TabsSearch from '@/components/TabsSearch.vue' import TabsSearch from '@/components/TabsSearch.vue'
import { VueEternalLoading } from '@ts-pro/vue-eternal-loading'
import { useSearchStore } from '@/stores/search' import { useSearchStore } from '@/stores/search'
import webapi from '@/webapi' import webapi from '@/webapi'
@ -96,8 +88,7 @@ export default {
ListArtistsSpotify, ListArtistsSpotify,
ListPlaylistsSpotify, ListPlaylistsSpotify,
ListTracksSpotify, ListTracksSpotify,
TabsSearch, TabsSearch
VueEternalLoading
}, },
setup() { setup() {
return { searchStore: useSearchStore() } return { searchStore: useSearchStore() }