2022-04-15 14:24:30 +00:00
|
|
|
<template>
|
2022-04-15 17:00:08 +00:00
|
|
|
<BaseContextMenu extra-class="song-menu" ref="base" data-testid="song-context-menu">
|
|
|
|
<template v-if="onlyOneSongSelected">
|
2022-04-15 14:24:30 +00:00
|
|
|
<li class="playback" @click.stop.prevent="doPlayback">
|
|
|
|
<span v-if="firstSongPlaying">Pause</span>
|
|
|
|
<span v-else>Play</span>
|
|
|
|
</li>
|
|
|
|
<li class="go-to-album" @click="viewAlbumDetails(songs[0].album)">Go to Album</li>
|
|
|
|
<li class="go-to-artist" @click="viewArtistDetails(songs[0].artist)">Go to Artist</li>
|
|
|
|
</template>
|
|
|
|
<li class="has-sub">
|
|
|
|
Add To
|
|
|
|
<ul class="menu submenu menu-add-to">
|
|
|
|
<li class="after-current" @click="queueSongsAfterCurrent">After Current Song</li>
|
|
|
|
<li class="bottom-queue" @click="queueSongsToBottom">Bottom of Queue</li>
|
|
|
|
<li class="top-queue" @click="queueSongsToTop">Top of Queue</li>
|
|
|
|
<li class="separator"></li>
|
|
|
|
<li class="favorite" @click="addSongsToFavorite">Favorites</li>
|
|
|
|
<li class="separator" v-if="normalPlaylists.length"></li>
|
|
|
|
<li
|
|
|
|
class="playlist"
|
|
|
|
v-for="p in normalPlaylists"
|
|
|
|
:key="p.id"
|
|
|
|
@click="addSongsToExistingPlaylist(p)"
|
|
|
|
>{{ p.name }}
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</li>
|
|
|
|
<li class="open-edit-form" v-if="isAdmin" @click="openEditForm">Edit</li>
|
|
|
|
<li class="download" v-if="sharedState.allowDownload" @click="download">Download</li>
|
|
|
|
<li
|
|
|
|
class="copy-url"
|
|
|
|
v-if="copyable && onlyOneSongSelected"
|
|
|
|
@click="copyUrl"
|
|
|
|
>
|
|
|
|
Copy Shareable URL
|
|
|
|
</li>
|
2022-04-15 17:00:08 +00:00
|
|
|
</BaseContextMenu>
|
2022-04-15 14:24:30 +00:00
|
|
|
</template>
|
|
|
|
|
2022-04-15 17:00:08 +00:00
|
|
|
<script lang="ts" setup>
|
2022-04-20 10:20:09 +00:00
|
|
|
import { computed, reactive, Ref, toRef, toRefs, watchEffect } from 'vue'
|
2022-04-15 17:00:08 +00:00
|
|
|
import { copyText, eventBus, isClipboardSupported as copyable } from '@/utils'
|
|
|
|
import { playlistStore, queueStore, sharedStore, songStore, userStore } from '@/stores'
|
|
|
|
import { download as downloadService, playback } from '@/services'
|
2022-04-15 14:24:30 +00:00
|
|
|
import router from '@/router'
|
2022-04-15 17:00:08 +00:00
|
|
|
import { useContextMenu, useSongMenuMethods } from '@/composables'
|
|
|
|
|
|
|
|
const {
|
2022-04-20 10:20:09 +00:00
|
|
|
context,
|
2022-04-15 17:00:08 +00:00
|
|
|
base,
|
|
|
|
BaseContextMenu,
|
|
|
|
open,
|
|
|
|
close
|
|
|
|
} = useContextMenu()
|
|
|
|
|
2022-04-20 10:20:09 +00:00
|
|
|
const songs = toRef(context, 'songs') as Ref<Song[]>
|
|
|
|
|
2022-04-15 17:00:08 +00:00
|
|
|
const {
|
|
|
|
queueSongsAfterCurrent,
|
|
|
|
queueSongsToBottom,
|
|
|
|
queueSongsToTop,
|
|
|
|
addSongsToFavorite,
|
|
|
|
addSongsToExistingPlaylist
|
2022-04-20 10:20:09 +00:00
|
|
|
} = useSongMenuMethods(songs, close)
|
2022-04-15 17:00:08 +00:00
|
|
|
|
|
|
|
const playlistState = reactive(playlistStore.state)
|
|
|
|
const sharedState = reactive(sharedStore.state)
|
|
|
|
const userState = reactive(userStore.state)
|
|
|
|
|
|
|
|
const onlyOneSongSelected = computed(() => songs.value.length === 1)
|
|
|
|
const firstSongPlaying = computed(() => songs.value.length ? songs.value[0].playbackState === 'Playing' : false)
|
|
|
|
const normalPlaylists = computed(() => playlistState.playlists.filter(playlist => !playlist.is_smart))
|
|
|
|
const isAdmin = computed(() => userState.current.is_admin)
|
|
|
|
|
|
|
|
const doPlayback = () => {
|
|
|
|
if (!songs.value.length) return
|
|
|
|
|
|
|
|
switch (songs.value[0].playbackState) {
|
|
|
|
case 'Playing':
|
|
|
|
playback.pause()
|
|
|
|
break
|
|
|
|
|
|
|
|
case 'Paused':
|
|
|
|
playback.resume()
|
|
|
|
break
|
|
|
|
|
|
|
|
default:
|
|
|
|
queueStore.contains(songs.value[0]) || queueStore.queueAfterCurrent(songs.value[0])
|
|
|
|
playback.play(songs.value[0])
|
|
|
|
break
|
2022-04-15 14:24:30 +00:00
|
|
|
}
|
2022-04-15 17:00:08 +00:00
|
|
|
|
|
|
|
close()
|
|
|
|
}
|
|
|
|
|
|
|
|
const openEditForm = () => {
|
|
|
|
songs.value.length && eventBus.emit('MODAL_SHOW_EDIT_SONG_FORM', songs)
|
|
|
|
close()
|
|
|
|
}
|
|
|
|
|
|
|
|
const viewAlbumDetails = (album: Album) => {
|
|
|
|
router.go(`album/${album.id}`)
|
|
|
|
close()
|
|
|
|
}
|
|
|
|
|
|
|
|
const viewArtistDetails = (artist: Artist) => {
|
|
|
|
router.go(`artist/${artist.id}`)
|
|
|
|
close()
|
|
|
|
}
|
|
|
|
|
|
|
|
const download = () => {
|
|
|
|
downloadService.fromSongs(songs.value)
|
|
|
|
close()
|
|
|
|
}
|
|
|
|
|
|
|
|
const copyUrl = () => {
|
|
|
|
copyText(songStore.getShareableUrl(songs.value[0]))
|
|
|
|
close()
|
|
|
|
}
|
|
|
|
|
|
|
|
defineExpose({ open, close })
|
2022-04-15 14:24:30 +00:00
|
|
|
</script>
|