mirror of
https://github.com/owntone/owntone-server.git
synced 2025-05-03 00:13:47 -04:00
[web] Add the possibility to remove past search queries
This commit is contained in:
parent
e5e7702fc5
commit
0362896bfb
@ -10,7 +10,7 @@
|
|||||||
'is-active': $route.name === 'search-library'
|
'is-active': $route.name === 'search-library'
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<a @click="search_library">
|
<a @click="$emit('search-library')">
|
||||||
<mdicon class="icon is-small" name="bookshelf" size="16" />
|
<mdicon class="icon is-small" name="bookshelf" size="16" />
|
||||||
<span v-text="$t('page.search.tabs.library')" />
|
<span v-text="$t('page.search.tabs.library')" />
|
||||||
</a>
|
</a>
|
||||||
@ -20,7 +20,7 @@
|
|||||||
'is-active': $route.name === 'search-spotify'
|
'is-active': $route.name === 'search-spotify'
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<a @click="search_spotify">
|
<a @click="$emit('search-spotify')">
|
||||||
<mdicon class="icon is-small" name="spotify" size="16" />
|
<mdicon class="icon is-small" name="spotify" size="16" />
|
||||||
<span v-text="$t('page.search.tabs.spotify')" />
|
<span v-text="$t('page.search.tabs.spotify')" />
|
||||||
</a>
|
</a>
|
||||||
@ -36,39 +36,12 @@
|
|||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'TabsSearch',
|
name: 'TabsSearch',
|
||||||
props: { query: { default: '', type: String } },
|
emits: ['search-library', 'search-spotify'],
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
route_query() {
|
|
||||||
if (this.query) {
|
|
||||||
return {
|
|
||||||
limit: 3,
|
|
||||||
offset: 0,
|
|
||||||
query: this.query,
|
|
||||||
type: 'track,artist,album,composer,playlist,audiobook,podcast'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
},
|
|
||||||
spotify_enabled() {
|
spotify_enabled() {
|
||||||
return this.$store.state.spotify.webapi_token_valid
|
return this.$store.state.spotify.webapi_token_valid
|
||||||
}
|
}
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
search_library() {
|
|
||||||
this.$router.push({
|
|
||||||
name: 'search-library',
|
|
||||||
query: this.route_query
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
search_spotify() {
|
|
||||||
this.$router.push({
|
|
||||||
name: 'search-spotify',
|
|
||||||
query: this.route_query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="columns is-centered">
|
<div class="columns is-centered">
|
||||||
<div class="column is-four-fifths">
|
<div class="column is-four-fifths">
|
||||||
<form @submit.prevent="new_search">
|
<form @submit.prevent="search">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<p class="control has-icons-left">
|
<p class="control has-icons-left">
|
||||||
<input
|
<input
|
||||||
@ -32,43 +32,42 @@
|
|||||||
</i18n-t>
|
</i18n-t>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<div class="tags mt-4">
|
<div class="field is-grouped is-grouped-multiline mt-4">
|
||||||
<a
|
<div v-for="query in recent_searches" :key="query" class="control">
|
||||||
v-for="recent_search in recent_searches"
|
<div class="tags has-addons">
|
||||||
:key="recent_search"
|
<a class="tag" @click="open_search(query)" v-text="query" />
|
||||||
class="tag"
|
<a class="tag is-delete" @click="remove_search(query)"></a>
|
||||||
@click="open_recent_search(recent_search)"
|
</div>
|
||||||
v-text="recent_search"
|
</div>
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<tabs-search :query="search_query" />
|
<tabs-search @search-library="search" @search-spotify="search_spotify" />
|
||||||
<template v-for="type in search_types" :key="type">
|
<template v-for="[type, items] in results" :key="type">
|
||||||
<content-with-heading v-if="show(type)" class="pt-0">
|
<content-with-heading class="pt-0">
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="$t(`page.search.${type}s`)" />
|
<p class="title is-4" v-text="$t(`page.search.${type}s`)" />
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<component :is="components[type]" :items="results[type]" />
|
<component :is="components[type]" :items="items" />
|
||||||
</template>
|
</template>
|
||||||
<template #footer>
|
<template v-if="!expanded" #footer>
|
||||||
<nav v-if="show_all_button(type)" class="level">
|
<nav v-if="show_all_button(items)" class="level">
|
||||||
<p class="level-item">
|
<p class="level-item">
|
||||||
<a
|
<a
|
||||||
class="button is-light is-small is-rounded"
|
class="button is-light is-small is-rounded"
|
||||||
@click="open_search(type)"
|
@click="expand(type)"
|
||||||
v-text="
|
v-text="
|
||||||
$t(`page.search.show-${type}s`, results[type].total, {
|
$t(`page.search.show-${type}s`, items.total, {
|
||||||
count: $filters.number(results[type].total)
|
count: $filters.number(items.total)
|
||||||
})
|
})
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
</nav>
|
</nav>
|
||||||
<p v-if="!results[type].total" class="has-text-centered-mobile">
|
<p v-if="!items.total" class="has-text-centered-mobile">
|
||||||
<i v-text="$t('page.search.no-results')" />
|
<i v-text="$t('page.search.no-results')" />
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
@ -88,6 +87,17 @@ import ListTracks from '@/components/ListTracks.vue'
|
|||||||
import TabsSearch from '@/components/TabsSearch.vue'
|
import TabsSearch from '@/components/TabsSearch.vue'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
|
const PAGE_SIZE = 3,
|
||||||
|
SEARCH_TYPES = [
|
||||||
|
'track',
|
||||||
|
'artist',
|
||||||
|
'album',
|
||||||
|
'composer',
|
||||||
|
'playlist',
|
||||||
|
'audiobook',
|
||||||
|
'podcast'
|
||||||
|
]
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PageSearchLibrary',
|
name: 'PageSearchLibrary',
|
||||||
components: {
|
components: {
|
||||||
@ -111,139 +121,98 @@ export default {
|
|||||||
podcast: ListAlbums.name,
|
podcast: ListAlbums.name,
|
||||||
track: ListTracks.name
|
track: ListTracks.name
|
||||||
},
|
},
|
||||||
results: {
|
results: new Map(),
|
||||||
album: new GroupedList(),
|
search_limit: {},
|
||||||
artist: new GroupedList(),
|
|
||||||
audiobook: new GroupedList(),
|
|
||||||
composer: new GroupedList(),
|
|
||||||
playlist: new GroupedList(),
|
|
||||||
podcast: new GroupedList(),
|
|
||||||
track: new GroupedList()
|
|
||||||
},
|
|
||||||
search_query: '',
|
search_query: '',
|
||||||
search_types: [
|
search_types: SEARCH_TYPES
|
||||||
'track',
|
|
||||||
'artist',
|
|
||||||
'album',
|
|
||||||
'composer',
|
|
||||||
'playlist',
|
|
||||||
'audiobook',
|
|
||||||
'podcast'
|
|
||||||
],
|
|
||||||
tracks: new GroupedList()
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
expanded() {
|
||||||
|
return this.search_types.length === 1
|
||||||
|
},
|
||||||
recent_searches() {
|
recent_searches() {
|
||||||
return this.$store.state.recent_searches
|
return this.$store.state.recent_searches
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
$route(to, from) {
|
search_query() {
|
||||||
this.search(to)
|
this.$store.commit(types.SEARCH_QUERY, this.search_query)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$store.commit(types.SEARCH_SOURCE, this.$route.name)
|
this.$store.commit(types.SEARCH_SOURCE, this.$route.name)
|
||||||
|
this.search_query = this.$store.state.search_query
|
||||||
|
this.search_limit = PAGE_SIZE
|
||||||
this.search()
|
this.search()
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
new_search() {
|
expand(type) {
|
||||||
if (!this.search_query) {
|
this.search_query = this.$store.state.search_query
|
||||||
return
|
this.search_types = [type]
|
||||||
}
|
this.search_limit = -1
|
||||||
this.$router.push({
|
this.search()
|
||||||
query: {
|
|
||||||
limit: 3,
|
|
||||||
offset: 0,
|
|
||||||
query: this.search_query,
|
|
||||||
type: this.search_types.join()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
this.$refs.search_field.blur()
|
|
||||||
},
|
},
|
||||||
open_recent_search(query) {
|
open_search(query) {
|
||||||
this.search_query = query
|
this.search_query = query
|
||||||
this.new_search()
|
this.search_types = SEARCH_TYPES
|
||||||
|
this.search_limit = PAGE_SIZE
|
||||||
|
this.search()
|
||||||
},
|
},
|
||||||
open_search(type) {
|
remove_search(query) {
|
||||||
this.$router.push({
|
this.$store.dispatch('remove_recent_search', query)
|
||||||
query: { query: this.$route.query.query, type }
|
},
|
||||||
|
reset() {
|
||||||
|
this.results.clear()
|
||||||
|
this.search_types.forEach((type) => {
|
||||||
|
this.results.set(type, new GroupedList())
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
search() {
|
search(event) {
|
||||||
this.search_query = this.$route.query.query?.trim()
|
if (event) {
|
||||||
|
this.search_types = SEARCH_TYPES
|
||||||
|
this.search_limit = PAGE_SIZE
|
||||||
|
}
|
||||||
if (!this.search_query || !this.search_query.replace(/^query:/u, '')) {
|
if (!this.search_query || !this.search_query.replace(/^query:/u, '')) {
|
||||||
this.$refs.search_field.focus()
|
this.$refs.search_field.focus()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.$route.query.query = this.search_query
|
this.reset()
|
||||||
this.searchMusic(this.$route.query)
|
this.search_types.forEach((type) => {
|
||||||
this.searchType(this.$route.query, 'audiobook')
|
this.search_items(type)
|
||||||
this.searchType(this.$route.query, 'podcast')
|
})
|
||||||
this.$store.dispatch('add_recent_search', this.search_query)
|
this.$store.dispatch('add_recent_search', this.search_query)
|
||||||
},
|
},
|
||||||
searchMusic(query) {
|
search_items(type) {
|
||||||
if (
|
const music = type !== 'audiobook' && type !== 'podcast',
|
||||||
!query.type.includes('track') &&
|
kind = music ? 'music' : type,
|
||||||
!query.type.includes('artist') &&
|
parameters = {
|
||||||
!query.type.includes('album') &&
|
type: music ? type : 'album',
|
||||||
!query.type.includes('playlist') &&
|
limit: this.search_limit
|
||||||
!query.type.includes('composer')
|
|
||||||
) {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
const parameters = {
|
if (this.search_query.startsWith('query:')) {
|
||||||
type: query.type
|
parameters.expression = `(${this.search_query.replace(/^query:/u, '').trim()}) and media_kind is ${kind}`
|
||||||
}
|
} else if (music) {
|
||||||
if (query.query.startsWith('query:')) {
|
parameters.query = this.search_query
|
||||||
parameters.expression = `(${query.query.replace(/^query:/u, '').trim()}) and media_kind is music`
|
parameters.media_kind = kind
|
||||||
} else {
|
} else {
|
||||||
parameters.query = query.query
|
parameters.expression = `(album includes "${this.search_query}" or artist includes "${this.search_query}") and media_kind is ${kind}`
|
||||||
parameters.media_kind = 'music'
|
|
||||||
}
|
|
||||||
if (query.limit) {
|
|
||||||
parameters.limit = query.limit
|
|
||||||
parameters.offset = query.offset
|
|
||||||
}
|
}
|
||||||
webapi.search(parameters).then(({ data }) => {
|
webapi.search(parameters).then(({ data }) => {
|
||||||
this.results.track = new GroupedList(data.tracks)
|
this.results.set(type, new GroupedList(data[`${parameters.type}s`]))
|
||||||
this.results.artist = new GroupedList(data.artists)
|
|
||||||
this.results.album = new GroupedList(data.albums)
|
|
||||||
this.results.composer = new GroupedList(data.composers)
|
|
||||||
this.results.playlist = new GroupedList(data.playlists)
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
searchType(query, type) {
|
search_spotify() {
|
||||||
if (!query.type.includes(type)) {
|
this.$router.push({ name: 'search-spotify' })
|
||||||
return
|
|
||||||
}
|
|
||||||
const parameters = {
|
|
||||||
type: 'album'
|
|
||||||
}
|
|
||||||
if (query.query.startsWith('query:')) {
|
|
||||||
parameters.expression = query.query.replace(/^query:/u, '').trim()
|
|
||||||
} else {
|
|
||||||
parameters.expression = `album includes "${query.query}" or artist includes "${query.query}"`
|
|
||||||
}
|
|
||||||
parameters.expression = `(${parameters.expression}) and media_kind is ${type}`
|
|
||||||
if (query.limit) {
|
|
||||||
parameters.limit = query.limit
|
|
||||||
parameters.offset = query.offset
|
|
||||||
}
|
|
||||||
webapi.search(parameters).then(({ data }) => {
|
|
||||||
this.results[type] = new GroupedList(data.albums)
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
show(type) {
|
show(type) {
|
||||||
return this.$route.query.type?.includes(type) ?? false
|
return this.search_types.includes(type)
|
||||||
},
|
},
|
||||||
show_all_button(type) {
|
show_all_button(items) {
|
||||||
const items = this.results[type]
|
|
||||||
return items.total > items.items.length
|
return items.total > items.items.length
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="columns is-centered">
|
<div class="columns is-centered">
|
||||||
<div class="column is-four-fifths">
|
<div class="column is-four-fifths">
|
||||||
<form @submit.prevent="new_search">
|
<form @submit.prevent="search">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<p class="control has-icons-left">
|
<p class="control has-icons-left">
|
||||||
<input
|
<input
|
||||||
@ -18,28 +18,27 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<div class="tags mt-4">
|
<div class="field is-grouped is-grouped-multiline mt-4">
|
||||||
<a
|
<div v-for="query in recent_searches" :key="query" class="control">
|
||||||
v-for="recent_search in recent_searches"
|
<div class="tags has-addons">
|
||||||
:key="recent_search"
|
<a class="tag" @click="open_search(query)" v-text="query" />
|
||||||
class="tag"
|
<a class="tag is-delete" @click="remove_search(query)"></a>
|
||||||
@click="open_recent_search(recent_search)"
|
</div>
|
||||||
v-text="recent_search"
|
</div>
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<tabs-search :query="search_query" />
|
<tabs-search @search-library="search_library" @search-spotify="search" />
|
||||||
<template v-for="type in search_types" :key="type">
|
<template v-for="[type, items] in results" :key="type">
|
||||||
<content-with-heading v-if="show(type)" class="pt-0">
|
<content-with-heading class="pt-0">
|
||||||
<template #heading-left>
|
<template #heading-left>
|
||||||
<p class="title is-4" v-text="$t(`page.spotify.search.${type}s`)" />
|
<p class="title is-4" v-text="$t(`page.spotify.search.${type}s`)" />
|
||||||
</template>
|
</template>
|
||||||
<template #content>
|
<template #content>
|
||||||
<component :is="components[type]" :items="results[type].items" />
|
<component :is="components[type]" :items="items.items" />
|
||||||
<VueEternalLoading v-if="$route.query.type === type" :load="search_next">
|
<VueEternalLoading v-if="expanded" :load="search_next">
|
||||||
<template #loading>
|
<template #loading>
|
||||||
<div class="columns is-centered">
|
<div class="columns is-centered">
|
||||||
<div class="column has-text-centered">
|
<div class="column has-text-centered">
|
||||||
@ -50,21 +49,21 @@
|
|||||||
<template #no-more> </template>
|
<template #no-more> </template>
|
||||||
</VueEternalLoading>
|
</VueEternalLoading>
|
||||||
</template>
|
</template>
|
||||||
<template #footer>
|
<template v-if="!expanded" #footer>
|
||||||
<nav v-if="show_all_button(type)" class="level">
|
<nav v-if="show_all_button(items)" class="level">
|
||||||
<p class="level-item">
|
<p class="level-item">
|
||||||
<a
|
<a
|
||||||
class="button is-light is-small is-rounded"
|
class="button is-light is-small is-rounded"
|
||||||
@click="open_search(type)"
|
@click="expand(type)"
|
||||||
v-text="
|
v-text="
|
||||||
$t(`page.spotify.search.show-${type}s`, results[type].total, {
|
$t(`page.spotify.search.show-${type}s`, items.total, {
|
||||||
count: $filters.number(results[type].total)
|
count: $filters.number(items.total)
|
||||||
})
|
})
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
</nav>
|
</nav>
|
||||||
<p v-if="!results[type].total" class="has-text-centered-mobile">
|
<p v-if="!items.total" class="has-text-centered-mobile">
|
||||||
<i v-text="$t(`page.spotify.search.no-results`)" />
|
<i v-text="$t(`page.spotify.search.no-results`)" />
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
@ -84,7 +83,9 @@ import TabsSearch from '@/components/TabsSearch.vue'
|
|||||||
import { VueEternalLoading } from '@ts-pro/vue-eternal-loading'
|
import { VueEternalLoading } from '@ts-pro/vue-eternal-loading'
|
||||||
import webapi from '@/webapi'
|
import webapi from '@/webapi'
|
||||||
|
|
||||||
const PAGE_SIZE = 50
|
const PAGE_SIZE = 3,
|
||||||
|
PAGE_SIZE_EXPANDED = 50,
|
||||||
|
SEARCH_TYPES = ['track', 'artist', 'album', 'playlist']
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PageSearchSpotify',
|
name: 'PageSearchSpotify',
|
||||||
@ -106,114 +107,115 @@ export default {
|
|||||||
playlist: ListPlaylistsSpotify.name,
|
playlist: ListPlaylistsSpotify.name,
|
||||||
track: ListTracksSpotify.name
|
track: ListTracksSpotify.name
|
||||||
},
|
},
|
||||||
results: {
|
results: new Map(),
|
||||||
album: { items: [], total: 0 },
|
search_parameters: {},
|
||||||
artist: { items: [], total: 0 },
|
|
||||||
playlist: { items: [], total: 0 },
|
|
||||||
track: { items: [], total: 0 }
|
|
||||||
},
|
|
||||||
search_param: {},
|
|
||||||
search_query: '',
|
search_query: '',
|
||||||
search_types: ['track', 'artist', 'album', 'playlist']
|
search_types: SEARCH_TYPES
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
|
expanded() {
|
||||||
|
return this.search_types.length === 1
|
||||||
|
},
|
||||||
recent_searches() {
|
recent_searches() {
|
||||||
return this.$store.state.recent_searches.filter(
|
return this.$store.state.recent_searches.filter(
|
||||||
(search) => !search.startsWith('query:')
|
(query) => !query.startsWith('query:')
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
$route(to, from) {
|
search_query() {
|
||||||
this.search()
|
this.$store.commit(types.SEARCH_QUERY, this.search_query)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$store.commit(types.SEARCH_SOURCE, this.$route.name)
|
this.$store.commit(types.SEARCH_SOURCE, this.$route.name)
|
||||||
|
this.search_query = this.$store.state.search_query
|
||||||
|
this.search_parameters.limit = PAGE_SIZE
|
||||||
this.search()
|
this.search()
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
new_search() {
|
expand(type) {
|
||||||
if (!this.search_query) {
|
this.search_query = this.$store.state.search_query
|
||||||
return
|
this.search_types = [type]
|
||||||
}
|
this.search_parameters.limit = PAGE_SIZE_EXPANDED
|
||||||
this.$router.push({
|
this.search_parameters.offset = 0
|
||||||
query: {
|
|
||||||
limit: 3,
|
this.search()
|
||||||
offset: 0,
|
|
||||||
query: this.search_query,
|
|
||||||
type: this.search_types.join()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
this.$refs.search_field.blur()
|
|
||||||
},
|
},
|
||||||
open_recent_search(query) {
|
open_search(query) {
|
||||||
this.search_query = query
|
this.search_query = query
|
||||||
this.new_search()
|
this.search_types = SEARCH_TYPES
|
||||||
|
this.search_parameters.limit = PAGE_SIZE
|
||||||
|
this.search_parameters.offset = 0
|
||||||
|
this.search()
|
||||||
},
|
},
|
||||||
open_search(type) {
|
remove_search(query) {
|
||||||
this.$router.push({
|
this.$store.dispatch('remove_recent_search', query)
|
||||||
query: { query: this.$route.query.query, type }
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
reset() {
|
reset() {
|
||||||
Object.entries(this.results).forEach(
|
this.results.clear()
|
||||||
(key) => (this.results[key] = { items: [], total: 0 })
|
this.search_types.forEach((type) => {
|
||||||
)
|
this.results.set(type, { items: [], total: 0 })
|
||||||
|
})
|
||||||
},
|
},
|
||||||
search() {
|
search(event) {
|
||||||
this.reset()
|
if (event) {
|
||||||
this.search_query = this.$route.query.query?.trim()
|
this.search_types = SEARCH_TYPES
|
||||||
if (!this.search_query || this.search_query.startsWith('query:')) {
|
this.search_parameters.limit = PAGE_SIZE
|
||||||
this.search_query = ''
|
}
|
||||||
|
if (!this.search_query) {
|
||||||
this.$refs.search_field.focus()
|
this.$refs.search_field.focus()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.$route.query.query = this.search_query
|
this.reset()
|
||||||
this.search_all()
|
this.search_items().then((data) => {
|
||||||
|
this.search_types.forEach((type) => {
|
||||||
|
this.results.set(type, data[`${type}s`])
|
||||||
|
})
|
||||||
|
})
|
||||||
this.$store.dispatch('add_recent_search', this.search_query)
|
this.$store.dispatch('add_recent_search', this.search_query)
|
||||||
},
|
},
|
||||||
search_all() {
|
search_items() {
|
||||||
this.search_param.limit = this.$route.query.limit ?? PAGE_SIZE
|
return webapi.spotify().then(({ data }) => {
|
||||||
this.search_param.offset = this.$route.query.offset ?? 0
|
this.search_parameters.market = data.webapi_country
|
||||||
const types = this.$route.query.type
|
const spotifyApi = new SpotifyWebApi()
|
||||||
.split(',')
|
spotifyApi.setAccessToken(data.webapi_token)
|
||||||
.filter((type) => this.search_types.includes(type))
|
return spotifyApi.search(
|
||||||
this.search_spotify(types).then((data) => {
|
this.search_query,
|
||||||
this.results.track = data.tracks ?? { items: [], total: 0 }
|
this.search_types,
|
||||||
this.results.artist = data.artists ?? { items: [], total: 0 }
|
this.search_parameters
|
||||||
this.results.album = data.albums ?? { items: [], total: 0 }
|
)
|
||||||
this.results.playlist = data.playlists ?? { items: [], total: 0 }
|
})
|
||||||
|
},
|
||||||
|
search_library() {
|
||||||
|
this.$router.push({
|
||||||
|
name: 'search-library'
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
search_next({ loaded }) {
|
search_next({ loaded }) {
|
||||||
const items = this.results[this.$route.query.type]
|
const [type] = this.search_types,
|
||||||
this.search_spotify([this.$route.query.type]).then((data) => {
|
items = this.results.get(type)
|
||||||
|
this.search_parameters.limit = PAGE_SIZE_EXPANDED
|
||||||
|
this.search_items().then((data) => {
|
||||||
const [next] = Object.values(data)
|
const [next] = Object.values(data)
|
||||||
items.items.push(...next.items)
|
items.items.push(...next.items)
|
||||||
items.total = next.total
|
items.total = next.total
|
||||||
this.search_param.offset += next.limit
|
if (!this.search_parameters.offset) {
|
||||||
loaded(next.items.length, PAGE_SIZE)
|
this.search_parameters.offset = 0
|
||||||
})
|
}
|
||||||
},
|
this.search_parameters.offset += next.limit
|
||||||
search_spotify(types) {
|
loaded(next.items.length, PAGE_SIZE_EXPANDED)
|
||||||
return webapi.spotify().then(({ data }) => {
|
|
||||||
this.search_param.market = data.webapi_country
|
|
||||||
const spotifyApi = new SpotifyWebApi()
|
|
||||||
spotifyApi.setAccessToken(data.webapi_token)
|
|
||||||
return spotifyApi.search(this.$route.query.query, types, this.search_param)
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
show(type) {
|
show(type) {
|
||||||
return this.$route.query.type?.includes(type) ?? false
|
return this.search_types.includes(type)
|
||||||
},
|
},
|
||||||
show_all_button(type) {
|
show_all_button(items) {
|
||||||
const items = this.results[type]
|
|
||||||
return items.total > items.items.length
|
return items.total > items.items.length
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,7 @@ export default createStore({
|
|||||||
},
|
},
|
||||||
recent_searches: [],
|
recent_searches: [],
|
||||||
rss_count: {},
|
rss_count: {},
|
||||||
|
search_query: '',
|
||||||
search_source: 'search-library',
|
search_source: 'search-library',
|
||||||
settings: {
|
settings: {
|
||||||
categories: []
|
categories: []
|
||||||
@ -130,6 +131,9 @@ export default createStore({
|
|||||||
[types.UPDATE_PAIRING](state, pairing) {
|
[types.UPDATE_PAIRING](state, pairing) {
|
||||||
state.pairing = pairing
|
state.pairing = pairing
|
||||||
},
|
},
|
||||||
|
[types.SEARCH_QUERY](state, query) {
|
||||||
|
state.search_query = query
|
||||||
|
},
|
||||||
[types.SEARCH_SOURCE](state, searchSource) {
|
[types.SEARCH_SOURCE](state, searchSource) {
|
||||||
state.search_source = searchSource
|
state.search_source = searchSource
|
||||||
},
|
},
|
||||||
@ -200,8 +204,8 @@ export default createStore({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
add_recent_search({ commit, state }, query) {
|
add_recent_search({ commit, state }, query) {
|
||||||
const index = state.recent_searches.findIndex((elem) => elem === query)
|
const index = state.recent_searches.indexOf(query)
|
||||||
if (index >= 0) {
|
if (index !== -1) {
|
||||||
state.recent_searches.splice(index, 1)
|
state.recent_searches.splice(index, 1)
|
||||||
}
|
}
|
||||||
state.recent_searches.splice(0, 0, query)
|
state.recent_searches.splice(0, 0, query)
|
||||||
@ -209,6 +213,12 @@ export default createStore({
|
|||||||
state.recent_searches.pop()
|
state.recent_searches.pop()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
remove_recent_search({ commit, state }, query) {
|
||||||
|
const index = state.recent_searches.indexOf(query)
|
||||||
|
if (index !== -1) {
|
||||||
|
state.recent_searches.splice(index, 1)
|
||||||
|
}
|
||||||
|
},
|
||||||
delete_notification({ commit, state }, notification) {
|
delete_notification({ commit, state }, notification) {
|
||||||
const index = state.notifications.list.indexOf(notification)
|
const index = state.notifications.list.indexOf(notification)
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
|
@ -1,25 +1,26 @@
|
|||||||
export const UPDATE_CONFIG = 'UPDATE_CONFIG'
|
export const ALBUMS_SORT = 'ALBUMS_SORT',
|
||||||
export const UPDATE_SETTINGS = 'UPDATE_SETTINGS'
|
ARTISTS_SORT = 'ARTISTS_SORT',
|
||||||
export const UPDATE_LIBRARY_STATS = 'UPDATE_LIBRARY_STATS'
|
ARTIST_ALBUMS_SORT = 'ARTIST_ALBUMS_SORT',
|
||||||
export const UPDATE_LIBRARY_RSS_COUNT = 'UPDATE_LIBRARY_RSS_COUNT'
|
ARTIST_TRACKS_SORT = 'ARTIST_TRACKS_SORT',
|
||||||
export const UPDATE_OUTPUTS = 'UPDATE_OUTPUTS'
|
COMPOSER_TRACKS_SORT = 'COMPOSER_TRACKS_SORT',
|
||||||
export const UPDATE_PLAYER_STATUS = 'UPDATE_PLAYER_STATUS'
|
GENRE_TRACKS_SORT = 'GENRE_TRACKS_SORT',
|
||||||
export const UPDATE_QUEUE = 'UPDATE_QUEUE'
|
HIDE_SINGLES = 'HIDE_SINGLES',
|
||||||
export const UPDATE_LYRICS = 'UPDATE_LYRICS'
|
HIDE_SPOTIFY = 'HIDE_SPOTIFY',
|
||||||
export const UPDATE_LASTFM = 'UPDATE_LASTFM'
|
SEARCH_QUERY = 'SEARCH_QUERY',
|
||||||
export const UPDATE_SPOTIFY = 'UPDATE_SPOTIFY'
|
SEARCH_SOURCE = 'SEARCH_SOURCE',
|
||||||
export const UPDATE_PAIRING = 'UPDATE_PAIRING'
|
SHOW_BURGER_MENU = 'SHOW_BURGER_MENU',
|
||||||
export const SEARCH_SOURCE = 'SEARCH_SOURCE'
|
SHOW_ONLY_NEXT_ITEMS = 'SHOW_ONLY_NEXT_ITEMS',
|
||||||
export const COMPOSER_TRACKS_SORT = 'COMPOSER_TRACKS_SORT'
|
SHOW_PLAYER_MENU = 'SHOW_PLAYER_MENU',
|
||||||
export const GENRE_TRACKS_SORT = 'GENRE_TRACKS_SORT'
|
SHOW_UPDATE_DIALOG = 'SHOW_UPDATE_DIALOG',
|
||||||
export const HIDE_SINGLES = 'HIDE_SINGLES'
|
UPDATE_CONFIG = 'UPDATE_CONFIG',
|
||||||
export const HIDE_SPOTIFY = 'HIDE_SPOTIFY'
|
UPDATE_DIALOG_SCAN_KIND = 'UPDATE_DIALOG_SCAN_KIND',
|
||||||
export const ARTISTS_SORT = 'ARTISTS_SORT'
|
UPDATE_LASTFM = 'UPDATE_LASTFM',
|
||||||
export const ARTIST_ALBUMS_SORT = 'ARTIST_ALBUMS_SORT'
|
UPDATE_LIBRARY_RSS_COUNT = 'UPDATE_LIBRARY_RSS_COUNT',
|
||||||
export const ARTIST_TRACKS_SORT = 'ARTIST_TRACKS_SORT'
|
UPDATE_LIBRARY_STATS = 'UPDATE_LIBRARY_STATS',
|
||||||
export const ALBUMS_SORT = 'ALBUMS_SORT'
|
UPDATE_LYRICS = 'UPDATE_LYRICS',
|
||||||
export const SHOW_ONLY_NEXT_ITEMS = 'SHOW_ONLY_NEXT_ITEMS'
|
UPDATE_OUTPUTS = 'UPDATE_OUTPUTS',
|
||||||
export const SHOW_BURGER_MENU = 'SHOW_BURGER_MENU'
|
UPDATE_PAIRING = 'UPDATE_PAIRING',
|
||||||
export const SHOW_PLAYER_MENU = 'SHOW_PLAYER_MENU'
|
UPDATE_PLAYER_STATUS = 'UPDATE_PLAYER_STATUS',
|
||||||
export const SHOW_UPDATE_DIALOG = 'SHOW_UPDATE_DIALOG'
|
UPDATE_QUEUE = 'UPDATE_QUEUE',
|
||||||
export const UPDATE_DIALOG_SCAN_KIND = 'UPDATE_DIALOG_SCAN_KIND'
|
UPDATE_SETTINGS = 'UPDATE_SETTINGS',
|
||||||
|
UPDATE_SPOTIFY = 'UPDATE_SPOTIFY'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user