mirror of
https://github.com/owntone/owntone-server.git
synced 2025-07-20 05:58:56 -04:00
[web] Fix a bug in the Spotify search
This commit is contained in:
parent
eb33a25ce7
commit
4adb623c3f
@ -34,7 +34,6 @@ export default {
|
||||
props: {
|
||||
items: { required: true, type: Object },
|
||||
load: { default: null, type: Function },
|
||||
loaded: { default: true, type: Boolean },
|
||||
mediaKind: { default: '', type: String }
|
||||
},
|
||||
emits: ['play-count-changed', 'podcast-deleted'],
|
||||
|
@ -13,7 +13,7 @@
|
||||
@open="open(item)"
|
||||
@open-details="openDetails(item)"
|
||||
/>
|
||||
<loader-list-item :load="load" :loaded="loaded" />
|
||||
<loader-list-item :load="load" />
|
||||
<modal-dialog-album-spotify
|
||||
:item="selectedItem"
|
||||
:show="showDetailsModal"
|
||||
@ -32,8 +32,7 @@ export default {
|
||||
components: { ListItem, LoaderListItem, ModalDialogAlbumSpotify },
|
||||
props: {
|
||||
items: { required: true, type: Object },
|
||||
load: { default: null, type: Function },
|
||||
loaded: { default: true, type: Boolean }
|
||||
load: { default: null, type: Function }
|
||||
},
|
||||
setup() {
|
||||
return { settingsStore: useSettingsStore() }
|
||||
|
@ -24,8 +24,7 @@ export default {
|
||||
components: { ListItem, ModalDialogArtist },
|
||||
props: {
|
||||
items: { required: true, type: Object },
|
||||
load: { default: null, type: Function },
|
||||
loaded: { default: true, type: Boolean }
|
||||
load: { default: null, type: Function }
|
||||
},
|
||||
data() {
|
||||
return { selectedItem: {}, showDetailsModal: false }
|
||||
|
@ -8,7 +8,7 @@
|
||||
@open="open(item)"
|
||||
@open-details="openDetails(item)"
|
||||
/>
|
||||
<loader-list-item :load="load" :loaded="loaded" />
|
||||
<loader-list-item :load="load" />
|
||||
<modal-dialog-artist-spotify
|
||||
:item="selectedItem"
|
||||
:show="showDetailsModal"
|
||||
@ -26,8 +26,7 @@ export default {
|
||||
components: { ListItem, LoaderListItem, ModalDialogArtistSpotify },
|
||||
props: {
|
||||
items: { required: true, type: Object },
|
||||
load: { default: null, type: Function },
|
||||
loaded: { default: true, type: Boolean }
|
||||
load: { default: null, type: Function }
|
||||
},
|
||||
data() {
|
||||
return { selectedItem: {}, showDetailsModal: false }
|
||||
|
@ -24,8 +24,7 @@ export default {
|
||||
components: { ListItem, ModalDialogComposer },
|
||||
props: {
|
||||
items: { required: true, type: Object },
|
||||
load: { default: null, type: Function },
|
||||
loaded: { default: true, type: Boolean }
|
||||
load: { default: null, type: Function }
|
||||
},
|
||||
data() {
|
||||
return { selectedItem: {}, showDetailsModal: false }
|
||||
|
@ -25,8 +25,7 @@ export default {
|
||||
components: { ListItem, ModalDialogPlaylist },
|
||||
props: {
|
||||
items: { required: true, type: Object },
|
||||
load: { default: null, type: Function },
|
||||
loaded: { default: true, type: Boolean }
|
||||
load: { default: null, type: Function }
|
||||
},
|
||||
data() {
|
||||
return { selectedItem: {}, showDetailsModal: false }
|
||||
|
@ -8,7 +8,7 @@
|
||||
@open="open(item)"
|
||||
@open-details="openDetails(item)"
|
||||
/>
|
||||
<loader-list-item :load="load" :loaded="loaded" />
|
||||
<loader-list-item :load="load" />
|
||||
<modal-dialog-playlist-spotify
|
||||
:item="selectedItem"
|
||||
:show="showDetailsModal"
|
||||
@ -26,8 +26,7 @@ export default {
|
||||
components: { ListItem, LoaderListItem, ModalDialogPlaylistSpotify },
|
||||
props: {
|
||||
items: { required: true, type: Object },
|
||||
load: { default: null, type: Function },
|
||||
loaded: { default: true, type: Boolean }
|
||||
load: { default: null, type: Function }
|
||||
},
|
||||
|
||||
data() {
|
||||
|
@ -32,7 +32,6 @@ export default {
|
||||
icon: { default: null, type: String },
|
||||
items: { default: null, type: Object },
|
||||
load: { default: null, type: Function },
|
||||
loaded: { default: true, type: Boolean },
|
||||
showProgress: { default: false, type: Boolean },
|
||||
uris: { default: '', type: String }
|
||||
},
|
||||
|
@ -19,7 +19,7 @@
|
||||
/>)
|
||||
</template>
|
||||
</list-item>
|
||||
<loader-list-item :load="load" :loaded="loaded" />
|
||||
<loader-list-item :load="load" />
|
||||
<modal-dialog-track-spotify
|
||||
:item="selectedItem"
|
||||
:show="showDetailsModal"
|
||||
@ -39,8 +39,7 @@ export default {
|
||||
props: {
|
||||
contextUri: { default: '', type: String },
|
||||
items: { required: true, type: Object },
|
||||
load: { default: null, type: Function },
|
||||
loaded: { default: true, type: Boolean }
|
||||
load: { default: null, type: Function }
|
||||
},
|
||||
data() {
|
||||
return { selectedItem: {}, showDetailsModal: false }
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<vue-eternal-loading v-if="load && !loaded" :load="load">
|
||||
<vue-eternal-loading v-if="load" :load="load">
|
||||
<template #loading>
|
||||
<div class="columns is-centered">
|
||||
<div class="column has-text-centered">
|
||||
@ -23,8 +23,7 @@ export default {
|
||||
name: 'LoaderListItem',
|
||||
components: { VueEternalLoading },
|
||||
props: {
|
||||
load: { default: null, type: Function },
|
||||
loaded: { default: true, type: Boolean }
|
||||
load: { default: null, type: Function }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -12,7 +12,7 @@
|
||||
/>
|
||||
</template>
|
||||
<template #content>
|
||||
<list-albums-spotify :items="albums" :load="load" :loaded="loaded" />
|
||||
<list-albums-spotify :items="albums" :load="load" />
|
||||
</template>
|
||||
</content-with-heading>
|
||||
<modal-dialog-artist-spotify
|
||||
@ -84,9 +84,6 @@ export default {
|
||||
subtitle: [{ count: this.total, key: 'data.albums' }],
|
||||
title: this.artist.name
|
||||
}
|
||||
},
|
||||
loaded() {
|
||||
return !(this.offset < this.total)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -21,7 +21,6 @@
|
||||
:context-uri="playlist.uri"
|
||||
:items="tracks"
|
||||
:load="load"
|
||||
:loaded="loaded"
|
||||
/>
|
||||
</template>
|
||||
</content-with-heading>
|
||||
@ -96,9 +95,6 @@ export default {
|
||||
}
|
||||
}
|
||||
return {}
|
||||
},
|
||||
loaded() {
|
||||
return !(this.offset < this.total)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
@ -44,16 +44,16 @@ import ListTracks from '@/components/ListTracks.vue'
|
||||
import library from '@/api/library'
|
||||
import { useSearchStore } from '@/stores/search'
|
||||
|
||||
const PAGE_SIZE = 3,
|
||||
SEARCH_TYPES = [
|
||||
'track',
|
||||
'artist',
|
||||
'album',
|
||||
'composer',
|
||||
'playlist',
|
||||
'audiobook',
|
||||
'podcast'
|
||||
]
|
||||
const PAGE_SIZE = 3
|
||||
const SEARCH_TYPES = [
|
||||
'track',
|
||||
'artist',
|
||||
'album',
|
||||
'composer',
|
||||
'playlist',
|
||||
'audiobook',
|
||||
'podcast'
|
||||
]
|
||||
|
||||
export default {
|
||||
name: 'PageSearchLibrary',
|
||||
@ -72,7 +72,7 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
limit: {},
|
||||
limit: PAGE_SIZE,
|
||||
results: new Map(),
|
||||
types: SEARCH_TYPES
|
||||
}
|
||||
@ -86,23 +86,17 @@ export default {
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.searchStore.source = this.$route.name
|
||||
this.limit = PAGE_SIZE
|
||||
this.search()
|
||||
},
|
||||
methods: {
|
||||
expand(type) {
|
||||
this.types = [type]
|
||||
this.limit = -1
|
||||
this.search()
|
||||
this.search([type], -1)
|
||||
},
|
||||
getItems(items) {
|
||||
return items
|
||||
},
|
||||
openSearch(query) {
|
||||
this.searchStore.query = query
|
||||
this.types = SEARCH_TYPES
|
||||
this.limit = PAGE_SIZE
|
||||
this.search()
|
||||
},
|
||||
reset() {
|
||||
@ -111,12 +105,10 @@ export default {
|
||||
this.results.set(type, new GroupedList())
|
||||
})
|
||||
},
|
||||
search(event) {
|
||||
search(types = SEARCH_TYPES, limit = PAGE_SIZE) {
|
||||
if (this.searchStore.query) {
|
||||
if (event) {
|
||||
this.types = SEARCH_TYPES
|
||||
this.limit = PAGE_SIZE
|
||||
}
|
||||
this.types = types
|
||||
this.limit = limit
|
||||
this.searchStore.query = this.searchStore.query.trim()
|
||||
this.reset()
|
||||
this.types.forEach((type) => {
|
||||
|
@ -4,6 +4,7 @@
|
||||
:expanded="expanded"
|
||||
:get-items="getItems"
|
||||
:history="history"
|
||||
:load="(expanded && searchNext) || null"
|
||||
:results="results"
|
||||
@search="search"
|
||||
@search-library="searchLibrary"
|
||||
@ -23,9 +24,9 @@ import SpotifyWebApi from 'spotify-web-api-js'
|
||||
import services from '@/api/services'
|
||||
import { useSearchStore } from '@/stores/search'
|
||||
|
||||
const PAGE_SIZE = 3,
|
||||
PAGE_SIZE_EXPANDED = 50,
|
||||
SEARCH_TYPES = ['track', 'artist', 'album', 'playlist']
|
||||
const PAGE_SIZE = 3
|
||||
const PAGE_SIZE_EXPANDED = 50
|
||||
const SEARCH_TYPES = ['track', 'artist', 'album', 'playlist']
|
||||
|
||||
export default {
|
||||
name: 'PageSearchSpotify',
|
||||
@ -43,8 +44,8 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
results: new Map(),
|
||||
parameters: {},
|
||||
results: new Map(),
|
||||
types: SEARCH_TYPES
|
||||
}
|
||||
},
|
||||
@ -59,25 +60,17 @@ export default {
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.searchStore.source = this.$route.name
|
||||
this.parameters.limit = PAGE_SIZE
|
||||
this.search()
|
||||
},
|
||||
methods: {
|
||||
expand(type) {
|
||||
this.types = [type]
|
||||
this.parameters.limit = PAGE_SIZE_EXPANDED
|
||||
this.parameters.offset = 0
|
||||
this.search()
|
||||
this.search([type], PAGE_SIZE_EXPANDED)
|
||||
},
|
||||
getItems(items) {
|
||||
return items.items
|
||||
},
|
||||
openSearch(query) {
|
||||
this.searchStore.query = query
|
||||
this.types = SEARCH_TYPES
|
||||
this.parameters.limit = PAGE_SIZE
|
||||
this.parameters.offset = 0
|
||||
this.search()
|
||||
},
|
||||
reset() {
|
||||
@ -86,12 +79,11 @@ export default {
|
||||
this.results.set(type, { items: [], total: 0 })
|
||||
})
|
||||
},
|
||||
search(event) {
|
||||
search(types = SEARCH_TYPES, limit = PAGE_SIZE, offset = 0) {
|
||||
if (this.searchStore.query) {
|
||||
if (event) {
|
||||
this.types = SEARCH_TYPES
|
||||
this.parameters.limit = PAGE_SIZE
|
||||
}
|
||||
this.types = types
|
||||
this.parameters.limit = limit
|
||||
this.parameters.offset = offset
|
||||
this.searchStore.query = this.searchStore.query.trim()
|
||||
this.reset()
|
||||
this.searchItems().then((data) => {
|
||||
@ -123,9 +115,8 @@ export default {
|
||||
this.searchItems().then((data) => {
|
||||
const [next] = Object.values(data)
|
||||
items.items.push(...next.items)
|
||||
items.total = next.total
|
||||
this.parameters.offset = (this.parameters.offset || 0) + next.limit
|
||||
loaded(next.items.length, PAGE_SIZE_EXPANDED)
|
||||
this.parameters.offset += next.items.length
|
||||
loaded(Number(next.next && next.limit), PAGE_SIZE_EXPANDED)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -43,16 +43,11 @@
|
||||
<pane-title :content="{ title: $t(`page.search.${type}s`) }" />
|
||||
</template>
|
||||
<template #content>
|
||||
<component
|
||||
:is="components[type]"
|
||||
:items="getItems(items)"
|
||||
:load="load"
|
||||
:loaded="!expanded"
|
||||
/>
|
||||
<component :is="components[type]" :items="getItems(items)" :load="load" />
|
||||
</template>
|
||||
<template v-if="!expanded" #footer>
|
||||
<control-button
|
||||
v-if="showAllButton(items)"
|
||||
v-if="items.total"
|
||||
:button="{
|
||||
handler: () => $emit('expand', type),
|
||||
title: $t(
|
||||
@ -62,7 +57,7 @@
|
||||
)
|
||||
}"
|
||||
/>
|
||||
<div v-if="!items.total" class="has-text-centered-mobile">
|
||||
<div v-else class="has-text-centered-mobile">
|
||||
<i v-text="$t('page.search.no-results')" />
|
||||
</div>
|
||||
</template>
|
||||
@ -98,11 +93,6 @@ export default {
|
||||
return {
|
||||
searchStore: useSearchStore()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showAllButton(items) {
|
||||
return items.total > items.items.length
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
Loading…
x
Reference in New Issue
Block a user