Implemented search in music.mpd

This commit is contained in:
Fabio Manganiello 2021-01-01 15:58:37 +01:00
parent d10649e1f1
commit d2887b7454
21 changed files with 358 additions and 52 deletions

View file

@ -1 +1 @@
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/favicon.ico"><title>platypush</title><link href="/static/css/chunk-24ff873d.64d9bc0b.css" rel="prefetch"><link href="/static/css/chunk-3b44ec4e.0c4a18da.css" rel="prefetch"><link href="/static/css/chunk-45939517.e4a1ddf3.css" rel="prefetch"><link href="/static/css/chunk-4bbbb9a3.3108d379.css" rel="prefetch"><link href="/static/css/chunk-4c0b0f48.009b6a70.css" rel="prefetch"><link href="/static/css/chunk-4eeb8349.2026dd4f.css" rel="prefetch"><link href="/static/css/chunk-52804492.a64fd302.css" rel="prefetch"><link href="/static/css/chunk-53360c78.c486a396.css" rel="prefetch"><link href="/static/css/chunk-62a3d08e.6cb54f10.css" rel="prefetch"><link href="/static/css/chunk-d8561e02.b52f89a0.css" rel="prefetch"><link href="/static/css/chunk-e8078048.c6785c78.css" rel="prefetch"><link href="/static/js/chunk-24ff873d.691c883d.js" rel="prefetch"><link href="/static/js/chunk-2d2091df.1e51ae4c.js" rel="prefetch"><link href="/static/js/chunk-2d21da1a.6bb60047.js" rel="prefetch"><link href="/static/js/chunk-3b44ec4e.904c7e10.js" rel="prefetch"><link href="/static/js/chunk-45939517.c0034c6b.js" rel="prefetch"><link href="/static/js/chunk-4bbbb9a3.251fff37.js" rel="prefetch"><link href="/static/js/chunk-4c0b0f48.366980a2.js" rel="prefetch"><link href="/static/js/chunk-4eeb8349.5c94d58c.js" rel="prefetch"><link href="/static/js/chunk-52804492.1cbed362.js" rel="prefetch"><link href="/static/js/chunk-53360c78.51ee7c96.js" rel="prefetch"><link href="/static/js/chunk-62a3d08e.17d3c86d.js" rel="prefetch"><link href="/static/js/chunk-d8561e02.1e366cb3.js" rel="prefetch"><link href="/static/js/chunk-e8078048.ce29b8d4.js" rel="prefetch"><link href="/static/css/app.4868c461.css" rel="preload" as="style"><link href="/static/css/chunk-vendors.5dad8b00.css" rel="preload" as="style"><link href="/static/js/app.ce952734.js" rel="preload" as="script"><link href="/static/js/chunk-vendors.30e3a6cb.js" rel="preload" as="script"><link href="/static/css/chunk-vendors.5dad8b00.css" rel="stylesheet"><link href="/static/css/app.4868c461.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but platypush doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/static/js/chunk-vendors.30e3a6cb.js"></script><script src="/static/js/app.ce952734.js"></script></body></html>
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/favicon.ico"><title>platypush</title><link href="/static/css/chunk-24ff873d.64d9bc0b.css" rel="prefetch"><link href="/static/css/chunk-3b44ec4e.0c4a18da.css" rel="prefetch"><link href="/static/css/chunk-45939517.e4a1ddf3.css" rel="prefetch"><link href="/static/css/chunk-4bbbb9a3.3108d379.css" rel="prefetch"><link href="/static/css/chunk-4c0b0f48.009b6a70.css" rel="prefetch"><link href="/static/css/chunk-4eeb8349.2026dd4f.css" rel="prefetch"><link href="/static/css/chunk-53360c78.c486a396.css" rel="prefetch"><link href="/static/css/chunk-62a3d08e.6cb54f10.css" rel="prefetch"><link href="/static/css/chunk-d8561e02.b52f89a0.css" rel="prefetch"><link href="/static/css/chunk-e8078048.c6785c78.css" rel="prefetch"><link href="/static/css/chunk-e9fa4af6.f205d678.css" rel="prefetch"><link href="/static/js/chunk-24ff873d.691c883d.js" rel="prefetch"><link href="/static/js/chunk-2d2091df.1e51ae4c.js" rel="prefetch"><link href="/static/js/chunk-2d21da1a.911f2770.js" rel="prefetch"><link href="/static/js/chunk-3b44ec4e.904c7e10.js" rel="prefetch"><link href="/static/js/chunk-45939517.c0034c6b.js" rel="prefetch"><link href="/static/js/chunk-4bbbb9a3.251fff37.js" rel="prefetch"><link href="/static/js/chunk-4c0b0f48.366980a2.js" rel="prefetch"><link href="/static/js/chunk-4eeb8349.5c94d58c.js" rel="prefetch"><link href="/static/js/chunk-53360c78.51ee7c96.js" rel="prefetch"><link href="/static/js/chunk-62a3d08e.17d3c86d.js" rel="prefetch"><link href="/static/js/chunk-d8561e02.1e366cb3.js" rel="prefetch"><link href="/static/js/chunk-e8078048.ce29b8d4.js" rel="prefetch"><link href="/static/js/chunk-e9fa4af6.567a1ae1.js" rel="prefetch"><link href="/static/css/app.4868c461.css" rel="preload" as="style"><link href="/static/css/chunk-vendors.5dad8b00.css" rel="preload" as="style"><link href="/static/js/app.6e791066.js" rel="preload" as="script"><link href="/static/js/chunk-vendors.30e3a6cb.js" rel="preload" as="script"><link href="/static/css/chunk-vendors.5dad8b00.css" rel="stylesheet"><link href="/static/css/app.4868c461.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but platypush doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/static/js/chunk-vendors.30e3a6cb.js"></script><script src="/static/js/app.6e791066.js"></script></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -79,11 +79,12 @@
<div class="track-container col-s-8 col-m-8 col-l-3">
<div class="track-info" v-if="track && status?.state !== 'stop'">
<div class="title">
<a href="#" v-text="track.title" @click="$emit('search', {album: track.album})" v-if="track.album"></a>
<a :href="$route.fullPath" v-text="track.title"
@click.prevent="$emit('search', {artist: track.artist, album: track.album})" v-if="track.album"></a>
<span v-text="track.title" v-else></span>
</div>
<div class="artist" v-if="track.artist">
<a href="#" v-text="track.artist" @click="$emit('search', {artist: track.artist})"></a>
<a :href="$route.fullPath" v-text="track.artist" @click.prevent="$emit('search', {artist: track.artist})"></a>
</div>
</div>
</div>

View file

@ -7,7 +7,7 @@
<Controls :status="status" :track="track" @play="$emit('play', $event)" @pause="$emit('pause', $event)"
@stop="$emit('stop')" @previous="$emit('previous')" @next="$emit('next')" @seek="$emit('seek', $event)"
@set-volume="$emit('set-volume', $event)" @consume="$emit('consume', $event)"
@repeat="$emit('repeat', $event)" @random="$emit('random', $event)" />
@repeat="$emit('repeat', $event)" @random="$emit('random', $event)" @search="$emit('search', $event)" />
</div>
</div>
</template>
@ -18,7 +18,7 @@ import Controls from "@/components/Media/Controls";
export default {
name: "View",
components: {Controls},
emits: ['play', 'pause', 'stop', 'next', 'previous', 'set-volume', 'seek', 'consume', 'random', 'repeat'],
emits: ['play', 'pause', 'stop', 'next', 'previous', 'set-volume', 'seek', 'consume', 'random', 'repeat', 'search'],
props: {
pluginName: {
type: String,

View file

@ -4,7 +4,7 @@
<MediaView :plugin-name="pluginName" :status="status" :track="track" @play="$emit('play', $event)"
@pause="$emit('pause')" @stop="$emit('stop')" @previous="$emit('previous')" @next="$emit('next')"
@set-volume="$emit('set-volume', $event)" @seek="$emit('seek', $event)" @consume="$emit('consume', $event)"
@repeat="$emit('repeat', $event)" @random="$emit('random', $event)" v-else>
@repeat="$emit('repeat', $event)" @random="$emit('random', $event)" @search="search" v-else>
<main>
<div class="nav-container">
<Nav :selected-view="selectedView" @input="selectedView = $event" />
@ -15,16 +15,21 @@
@play="$emit('play', $event)" @clear="$emit('clear')" @swap="$emit('swap-tracks', $event)"
@add="$emit('add-to-tracklist', $event)" @remove="$emit('remove-from-tracklist', $event)"
@move="$emit('tracklist-move', $event)" @save="$emit('tracklist-save', $event)"
@track-info="$emit('track-info', $event)" @add-to-playlist="openAddToPlaylist" />
@info="$emit('info', $event)" @add-to-playlist="openAddToPlaylist" @search="search" />
<Playlists :playlists="playlists" :loading="loading" v-else-if="selectedView === 'playlists'"
:edited-playlist="editedPlaylist" :tracks="editedPlaylistTracks"
@play="$emit('play-playlist', $event)" @load="$emit('load-playlist', $event)"
@remove="$emit('remove-playlist', $event)" @playlist-edit="$emit('playlist-edit', $event)"
@load-track="$emit('add-to-tracklist-from-edited-playlist', $event)"
@remove-track="$emit('remove-from-playlist', $event)" @track-info="$emit('track-info', $event)"
@remove-track="$emit('remove-from-playlist', $event)" @info="$emit('info', $event)"
@playlist-add="$emit('playlist-add', $event)" @add-to-playlist="openAddToPlaylist"
@track-move="$emit('playlist-track-move', $event)"/>
@track-move="$emit('playlist-track-move', $event)" @search="search" />
<Search :loading="loading" v-else-if="selectedView === 'search'" @search="search"
:results="searchResults" @clear="$emit('search-clear')" @info="$emit('info', $event)"
@play="$emit('play', $event)" @load="$emit('add-to-tracklist', $event)"
@add-to-playlist="openAddToPlaylist"/>
</div>
</main>
</MediaView>
@ -40,8 +45,7 @@
<div class="row artist" v-if="trackInfo.artist">
<div class="col-3 attr">Artist</div>
<div class="col-9 value">
<a :href="$route.fullPath" v-text="trackInfo.artist"
@click.stop="$emit('search', {artist: trackInfo.artist})" />
<a :href="$route.fullPath" v-text="trackInfo.artist" @click.prevent="search({artist: trackInfo.artist})" />
</div>
</div>
@ -54,7 +58,7 @@
<div class="col-3 attr">Album</div>
<div class="col-9 value">
<a :href="$route.fullPath" v-text="trackInfo.album"
@click.stop="$emit('search', {album: trackInfo.album})" />
@click.prevent="search({artist: trackInfo.artist, album: trackInfo.album})" />
</div>
</div>
@ -81,9 +85,8 @@
</div>
<div class="playlists">
<label class="row playlist"
:class="{hidden: playlistFilter?.length > 0 && playlist.name.toLowerCase().indexOf(playlistFilter.toLowerCase()) < 0}"
v-for="(playlist, i) in playlists" :key="i">
<label class="row playlist" v-for="(playlist, i) in playlists" :key="i"
:class="{hidden: playlistFilter?.length > 0 && playlist.name.toLowerCase().indexOf(playlistFilter.toLowerCase()) < 0}">
<input type="checkbox" :checked="selectedPlaylists[i]"
@change="selectedPlaylists[i] = $event.target.checked" />
<span class="name" v-text="playlist.name" />
@ -108,6 +111,7 @@ import MediaView from "@/components/Media/View";
import Nav from "@/components/panels/Music/Nav";
import Playlist from "@/components/panels/Music/Playlist";
import Playlists from "@/components/panels/Music/Playlists";
import Search from "@/components/panels/Music/Search";
import Utils from "@/Utils";
export default {
@ -115,11 +119,11 @@ export default {
emits: ['play', 'pause', 'stop', 'clear', 'previous', 'next', 'set-volume', 'seek', 'consume', 'repeat', 'random',
'status-update', 'playlist-update', 'new-playing-track', 'add-to-tracklist', 'remove-from-tracklist',
'swap-tracks', 'play-playlist', 'load-playlist', 'remove-playlist', 'tracklist-move', 'tracklist-save',
'add-to-tracklist-from-edited-playlist', 'remove-from-playlist', 'track-info', 'playlist-add', 'add-to-playlist',
'playlist-track-move'],
'add-to-tracklist-from-edited-playlist', 'remove-from-playlist', 'info', 'playlist-add', 'add-to-playlist',
'playlist-track-move', 'search', 'search-clear'],
mixins: [Utils, MediaUtils],
components: {Loading, Modal, Nav, MediaView, Playlist, Playlists, FormFooter},
components: {Loading, Modal, Nav, MediaView, Playlist, Playlists, FormFooter, Search},
props: {
pluginName: {
type: String,
@ -163,6 +167,10 @@ export default {
trackInfo: {
type: String,
},
searchResults: {
type: Array,
},
},
data() {
@ -227,6 +235,12 @@ export default {
this.addToPlaylistTrack = null
this.playlistFilter = ''
},
async search(filter) {
this.$emit('search', filter)
this.$refs.trackInfo.isVisible = false
this.selectedView = 'search'
},
},
mounted() {
@ -345,6 +359,10 @@ main {
@include from($tablet) {
width: 35em;
}
.file {
user-select: text;
}
}
}
</style>

View file

@ -27,7 +27,7 @@ export default {
return {
playing: {
iconClass: 'fas fa-play',
displayName: 'Now Playing',
displayName: 'Queue',
},
search: {

View file

@ -54,12 +54,12 @@
<div class="artist" v-if="track.artist">
<a :href="$route.fullPath" v-text="track.artist"
@click.stop="$emit('search', {artist: track.artist})" />
@click.prevent="$emit('search', {artist: track.artist})" />
</div>
<div class="album" v-if="track.album">
<a :href="$route.fullPath" v-text="track.album"
@click.stop="$emit('search', {artist: track.album})" />
@click.prevent="$emit('search', {artist: track.artist, album: track.album})" />
</div>
</div>
@ -71,7 +71,7 @@
<DropdownItem text="Play" icon-class="fa fa-play" @click="$emit('play', {pos: i})" />
<DropdownItem text="Add to playlist" icon-class="fa fa-list-ul" @click="$emit('add-to-playlist', track)" />
<DropdownItem text="Remove" icon-class="fa fa-trash" @click="$emit('remove', [...(new Set([...selectedTracks, i]))])" />
<DropdownItem text="Track info" icon-class="fa fa-info" @click="$emit('track-info', tracks[i])" />
<DropdownItem text="Info" icon-class="fa fa-info" @click="$emit('info', tracks[i])" />
</Dropdown>
</span>
</div>
@ -90,7 +90,7 @@ export default {
name: "Playlist",
mixins: [MediaUtils],
components: {DropdownItem, Dropdown, MusicHeader},
emits: ['play', 'clear', 'add', 'remove', 'swap', 'search', 'move', 'save', 'track-info'],
emits: ['play', 'clear', 'add', 'remove', 'swap', 'search', 'move', 'save', 'info'],
props: {
tracks: {
type: Array,

View file

@ -33,11 +33,12 @@
</div>
<div class="artist" v-if="track.artist">
<a :href="$route.fullPath" v-text="track.artist" @click.stop="$emit('search', {artist: track.artist})" />
<a :href="$route.fullPath" v-text="track.artist" @click.prevent="$emit('search', {artist: track.artist})" />
</div>
<div class="album" v-if="track.album">
<a :href="$route.fullPath" v-text="track.album" @click.stop="$emit('search', {artist: track.album})" />
<a :href="$route.fullPath" v-text="track.album"
@click.prevent="$emit('search', {artist: track.artist, album: track.album})" />
</div>
</div>
@ -47,10 +48,10 @@
<span class="actions">
<Dropdown title="Actions" icon-class="fa fa-ellipsis-h">
<DropdownItem text="Play" icon-class="fa fa-play" @click="$emit('load-track', {pos: i, play: true})" />
<DropdownItem text="Add to tracklist" icon-class="fa fa-plus" @click="$emit('load-track', {pos: i, play: false})" />
<DropdownItem text="Add to queue" icon-class="fa fa-plus" @click="$emit('load-track', {pos: i, play: false})" />
<DropdownItem text="Add to playlist" icon-class="fa fa-list-ul" @click="$emit('add-to-playlist', track)" />
<DropdownItem text="Remove" icon-class="fa fa-trash" @click="$emit('remove-track', [...(new Set([...selectedTracks, i]))])" />
<DropdownItem text="Show info" icon-class="fa fa-info" @click.stop="$emit('track-info', tracks[i])" />
<DropdownItem text="Info" icon-class="fa fa-info" @click.stop="$emit('info', tracks[i])" />
</Dropdown>
</span>
</div>
@ -106,7 +107,7 @@ export default {
name: "Playlists",
mixins: [MediaUtils],
components: {DropdownItem, Dropdown, MusicHeader},
emits: ['play', 'load', 'remove', 'playlist-edit', 'search', 'remove-track', 'load-track', 'track-info',
emits: ['play', 'load', 'remove', 'playlist-edit', 'search', 'remove-track', 'load-track', 'info',
'playlist-add', 'add-to-playlist', 'track-move'],
props: {

View file

@ -0,0 +1,264 @@
<template>
<div class="search fade-in" :class="{'form-collapsed': formCollapsed}">
<form class="search-form" v-if="!formCollapsed" @submit.prevent="$emit('search', filteredQuery)">
<div class="row">
<label>
<input type="text" placeholder="Any" v-model="query.any" />
</label>
</div>
<div class="row">
<label>
<input type="text" placeholder="Artist" v-model="query.artist" />
</label>
</div>
<div class="row">
<label>
<input type="text" placeholder="Title" v-model="query.title" />
</label>
</div>
<div class="row">
<label>
<input type="text" placeholder="Album" v-model="query.album" />
</label>
</div>
<FormFooter>
<button @click="clear">
<i class="icon fa fa-times" />
<span class="btn-title">Clear</span>
</button>
<button type="submit">
<i class="icon fa fa-search" />
<span class="btn-title">Search</span>
</button>
</FormFooter>
</form>
<MusicHeader v-else>
<label class="search-box">
<input type="search" placeholder="Filter" v-model="filter">
</label>
<span class="buttons">
<button @click="clear">
<i class="icon fa fa-times" />
<span class="btn-title">Clear</span>
</button>
</span>
</MusicHeader>
<div class="results">
<div class="row track" :class="{selected: selectedResults.has(i), hidden: !displayedTracks.has(i)}"
v-for="(result, i) in results" :key="i" @click="resultClick(i, $event)">
<div class="col-10">
<div class="title">
{{ result.title || '[No Title]' }}
</div>
<div class="artist" v-text="result.artist" v-if="result.artist?.length" />
<div class="album" v-text="result.album" v-if="result.album?.length" />
</div>
<div class="col-2 right-side">
<span class="duration" v-text="result.time && parseInt(result.time) ? convertTime(result.time) : '-:--'" />
<span class="actions">
<Dropdown title="Actions" icon-class="fa fa-ellipsis-h">
<DropdownItem text="Play" icon-class="fa fa-play" @click="play(i)" />
<DropdownItem text="Add to queue" icon-class="fa fa-plus" @click="load(i)" />
<DropdownItem text="Add to playlist" icon-class="fa fa-list-ul" @click="$emit('add-to-playlist', result)" />
<DropdownItem text="Info" icon-class="fa fa-info" @click="$emit('info', result)" />
</Dropdown>
</span>
</div>
</div>
</div>
</div>
</template>
<script>
import Dropdown from "@/components/elements/Dropdown";
import DropdownItem from "@/components/elements/DropdownItem";
import FormFooter from "@/components/elements/FormFooter";
import MediaUtils from "@/components/Media/Utils";
import MusicHeader from "@/components/panels/Music/Header";
export default {
name: "Search",
components: {Dropdown, DropdownItem, FormFooter, MusicHeader},
mixins: [MediaUtils],
emits: ['search', 'clear', 'play', 'load', 'add-to-playlist', 'info'],
props: {
loading: {
type: Boolean,
default: false,
},
results: {
type: Array,
},
},
data() {
return {
selectedResults: new Set(),
filter: '',
query: {
any: '',
artist: '',
title: '',
album: '',
},
}
},
computed: {
formCollapsed() {
return this.results?.length > 0
},
filteredQuery() {
return Object.entries(this.query).filter((o) => o[1]?.length).reduce((obj, [k, v]) => {
obj[k] = v
return obj
}, {})
},
displayedTracks() {
return new Set([...Array(this.results?.length || 0).keys()].filter((i) => {
const result = this.results[i]
if (!this.filter?.length)
return result
const filter = this.filter.toLowerCase()
return (result?.artist || '').toLowerCase().indexOf(filter) >= 0 ||
(result?.title || '').toLowerCase().indexOf(filter) >= 0 ||
(result?.album || '').toLowerCase().indexOf(filter) >= 0
}))
},
},
methods: {
clear() {
this.$emit('clear')
this.selectedResults = new Set()
},
resultClick(pos, event) {
if (event.shiftKey) {
if (this.selectedResults.size > 0 && !this.selectedResults.has(pos)) {
const results = [...this.selectedResults]
const min = Math.min(Math.min(results), pos)
const max = Math.max(Math.max(results), pos)
this.selectedResults = new Set([...Array(max-min+1).keys()].map((i) => i+min))
}
} else {
if (!event.ctrlKey)
this.selectedResults = new Set()
if (this.selectedResults.has(pos))
this.selectedResults.delete(pos)
else
this.selectedResults.add(pos)
}
},
play(pos) {
this.$emit('play', this.results[pos])
if (this.selectedResults.size)
this.selectedResults.forEach((result) => {
this.$emit('load', result)
})
},
load(pos) {
if (!this.selectedResults.has(pos))
this.selectedResults.add(pos)
this.selectedResults.forEach((i) => {
this.$emit('load', this.results[i])
})
},
},
}
</script>
<style lang="scss" scoped>
@import 'track.scss';
.search {
width: 100%;
display: flex;
flex-direction: column;
&:not(.form-collapsed) {
justify-content: center;
align-items: center;
}
form {
width: calc(100% - 2em);
max-width: 30em;
height: 17em;
background: $default-bg-5;
display: flex;
padding: 2em;
border-radius: 1.5em;
.row {
margin: .25em 0;
}
input[type=text] {
width: 100%;
}
::v-deep(.form-footer) {
height: 3em;
padding-right: 0;
border: 0;
}
::v-deep(button) {
border: 0;
&[type=submit] {
background: none;
}
&:hover {
border: 0;
color: $default-hover-fg-2;
}
}
}
.results {
overflow: auto;
}
::v-deep(.header) {
display: flex;
width: 100%;
align-items: center;
.search-box {
width: 70%;
input[type=search] {
width: 100%;
}
}
.buttons {
width: 30%;
display: inline-flex;
justify-content: right;
margin: 0;
}
}
}
</style>

View file

@ -2,16 +2,18 @@
<Loading v-if="loading" />
<MusicPlugin plugin-name="music.mpd" :loading="loading" :config="config" :tracks="tracks" :status="status"
:playlists="playlists" :edited-playlist="editedPlaylist" :edited-playlist-tracks="editedPlaylistTracks"
:track-info="trackInfo" @play="play" @pause="pause" @stop="stop" @previous="previous" @next="next"
@clear="clear" @set-volume="setVolume" @seek="seek" @consume="consume" @random="random" @repeat="repeat"
@status-update="refreshStatus(true)" @playlist-update="refresh(true)"
@new-playing-track="refreshStatus(true)" @remove-from-tracklist="removeFromTracklist"
@add-to-tracklist="addToTracklist" @swap-tracks="swapTracks" @load-playlist="loadPlaylist"
@play-playlist="playPlaylist" @remove-playlist="removePlaylist" @tracklist-move="moveTracklistTracks"
@tracklist-save="saveToPlaylist" @playlist-edit="playlistEditChanged"
:track-info="trackInfo" :search-results="searchResults" @play="play" @pause="pause" @stop="stop"
@previous="previous" @next="next" @clear="clear" @set-volume="setVolume" @seek="seek" @consume="consume"
@random="random" @repeat="repeat" @status-update="refreshStatus(true)"
@playlist-update="refresh(true)" @new-playing-track="refreshStatus(true)"
@remove-from-tracklist="removeFromTracklist" @add-to-tracklist="addToTracklist" @swap-tracks="swapTracks"
@load-playlist="loadPlaylist" @play-playlist="playPlaylist" @remove-playlist="removePlaylist"
@tracklist-move="moveTracklistTracks" @tracklist-save="saveToPlaylist"
@playlist-edit="playlistEditChanged"
@add-to-tracklist-from-edited-playlist="addToTracklistFromEditedPlaylist"
@remove-from-playlist="removeFromPlaylist" @track-info="trackInfo = $event" @playlist-add="playlistAdd"
@add-to-playlist="addToPlaylist" @playlist-track-move="playlistTrackMove" />
@remove-from-playlist="removeFromPlaylist" @info="trackInfo = $event" @playlist-add="playlistAdd"
@add-to-playlist="addToPlaylist" @playlist-track-move="playlistTrackMove" @search="search"
@search-clear="searchResults = []" />
</template>
<script>
@ -39,6 +41,7 @@ export default {
editedPlaylist: null,
editedPlaylistTracks: [],
trackInfo: null,
searchResults: [],
}
},
@ -130,6 +133,8 @@ export default {
async play(event) {
if (event?.pos != null) {
await this.request('music.mpd.play_pos', {pos: event.pos})
} else if (event.file) {
await this.request('music.mpd.play', {resource: event.file})
} else {
await this.request('music.mpd.play')
}
@ -191,6 +196,9 @@ export default {
},
async addToTracklist(resource) {
if (resource.file)
resource = resource.file
await this.request('music.mpd.add', {resource: resource})
await this.refresh(true)
},
@ -295,6 +303,16 @@ export default {
await this.playlistEditChanged(event.playlist)
},
async search(query) {
this.loading = true
try {
this.searchResults = await this.request('music.mpd.search', {filter: query})
} finally {
this.loading = false
}
},
},
mounted() {

View file

@ -34,6 +34,8 @@ $dashboard-bg: url('/img/dashboard-bg-light.jpg');
$border-color-1: #e1e4e8 !default;
$border-color-2: #dddddd !default;
$border-color-3: #cccccc !default;
$border-focus: 1px solid rgba(127, 216, 95, 0.83);
$border-hover: 1px solid rgba(159, 180, 152, 0.83);
$default-border: 1px solid $border-color-1 !default;
$default-border-2: 1px solid $border-color-2 !default;