mirror of
https://github.com/koel/koel
synced 2025-02-26 04:07:18 +00:00
more good stuff
This commit is contained in:
parent
014e109b3a
commit
ac83736192
19 changed files with 74 additions and 102 deletions
|
@ -38,6 +38,7 @@
|
||||||
"@typescript-eslint/no-explicit-any": 0,
|
"@typescript-eslint/no-explicit-any": 0,
|
||||||
"@typescript-eslint/no-non-null-assertion": 0,
|
"@typescript-eslint/no-non-null-assertion": 0,
|
||||||
"@typescript-eslint/ban-ts-comment": 0,
|
"@typescript-eslint/ban-ts-comment": 0,
|
||||||
|
"@typescript-eslint/no-empty-function": 0,
|
||||||
"vue/no-side-effects-in-computed-properties": 0,
|
"vue/no-side-effects-in-computed-properties": 0,
|
||||||
"@typescript-eslint/explicit-module-boundary-types": 0,
|
"@typescript-eslint/explicit-module-boundary-types": 0,
|
||||||
"standard/no-callback-literal": 0,
|
"standard/no-callback-literal": 0,
|
||||||
|
|
|
@ -31,7 +31,7 @@ import LoginForm from '@/components/auth/login-form.vue'
|
||||||
import MainWrapper from '@/components/layout/main-wrapper/index.vue'
|
import MainWrapper from '@/components/layout/main-wrapper/index.vue'
|
||||||
import Overlay from '@/components/ui/overlay.vue'
|
import Overlay from '@/components/ui/overlay.vue'
|
||||||
|
|
||||||
import { $, eventBus, hideOverlay, showOverlay } from '@/utils'
|
import { $, eventBus, hideOverlay, showOverlay, arrayify } from '@/utils'
|
||||||
import { favoriteStore, preferenceStore as preferences, queueStore, sharedStore } from '@/stores'
|
import { favoriteStore, preferenceStore as preferences, queueStore, sharedStore } from '@/stores'
|
||||||
import { auth, playback, socket } from '@/services'
|
import { auth, playback, socket } from '@/services'
|
||||||
|
|
||||||
|
@ -84,8 +84,8 @@ onMounted(async () => {
|
||||||
$.addClass(document.documentElement, navigator.userAgent.includes('Mac') ? 'mac' : 'non-mac')
|
$.addClass(document.documentElement, navigator.userAgent.includes('Mac') ? 'mac' : 'non-mac')
|
||||||
})
|
})
|
||||||
|
|
||||||
eventBus.on('SONG_CONTEXT_MENU_REQUESTED', async (e: MouseEvent, songs: Song[]) => {
|
eventBus.on('SONG_CONTEXT_MENU_REQUESTED', async (e: MouseEvent, songs: Song | Song[]) => {
|
||||||
contextMenuSongs.value = ([] as Song[]).concat(songs)
|
contextMenuSongs.value = arrayify(songs)
|
||||||
await nextTick()
|
await nextTick()
|
||||||
songContextMenu.value?.open(e.pageY, e.pageX)
|
songContextMenu.value?.open(e.pageY, e.pageX)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<section id="queueWrapper">
|
<section id="queueWrapper">
|
||||||
<screen-header>
|
<ScreenHeader>
|
||||||
Current Queue
|
Current Queue
|
||||||
<controls-toggler :showing-controls="showingControls" @toggleControls="toggleControls"/>
|
<ControlsToggler :showing-controls="showingControls" @toggleControls="toggleControls"/>
|
||||||
|
|
||||||
<template v-slot:meta>
|
<template v-slot:meta>
|
||||||
<span v-if="meta.songCount" data-test="list-meta">
|
<span v-if="meta.songCount" data-test="list-meta">
|
||||||
|
@ -11,27 +11,27 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-slot:controls>
|
<template v-slot:controls>
|
||||||
<song-list-controls
|
<SongListControls
|
||||||
v-if="state.songs.length && (!isPhone || showingControls)"
|
v-if="songs.length && (!isPhone || showingControls)"
|
||||||
@playAll="playAll"
|
@playAll="playAll"
|
||||||
@playSelected="playSelected"
|
@playSelected="playSelected"
|
||||||
@clearQueue="clearQueue"
|
@clearQueue="clearQueue"
|
||||||
:songs="state.songs"
|
:songs="songs"
|
||||||
:config="songListControlConfig"
|
:config="songListControlConfig"
|
||||||
:selectedSongs="selectedSongs"
|
:selectedSongs="selectedSongs"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</screen-header>
|
</ScreenHeader>
|
||||||
|
|
||||||
<song-list
|
<SongList
|
||||||
v-if="state.songs.length"
|
v-if="songs.length"
|
||||||
:items="state.songs"
|
:items="songs"
|
||||||
:config="{ sortable: false }"
|
:config="{ sortable: false }"
|
||||||
type="queue"
|
type="queue"
|
||||||
ref="songList"
|
ref="songList"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<screen-placeholder v-else>
|
<ScreenPlaceholder v-else>
|
||||||
<template v-slot:icon>
|
<template v-slot:icon>
|
||||||
<i class="fa fa-coffee"></i>
|
<i class="fa fa-coffee"></i>
|
||||||
</template>
|
</template>
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
How about
|
How about
|
||||||
<a class="start" @click.prevent="shuffleAll">shuffling all songs</a>?
|
<a class="start" @click.prevent="shuffleAll">shuffling all songs</a>?
|
||||||
</span>
|
</span>
|
||||||
</screen-placeholder>
|
</ScreenPlaceholder>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ import { pluralize } from '@/utils'
|
||||||
import { queueStore, songStore } from '@/stores'
|
import { queueStore, songStore } from '@/stores'
|
||||||
import { playback } from '@/services'
|
import { playback } from '@/services'
|
||||||
import { useSongList } from '@/composables'
|
import { useSongList } from '@/composables'
|
||||||
import { computed, defineAsyncComponent, reactive } from 'vue'
|
import { computed, defineAsyncComponent, reactive, toRef } from 'vue'
|
||||||
|
|
||||||
const ScreenHeader = defineAsyncComponent(() => import('@/components/ui/screen-header.vue'))
|
const ScreenHeader = defineAsyncComponent(() => import('@/components/ui/screen-header.vue'))
|
||||||
const ScreenPlaceholder = defineAsyncComponent(() => import('@/components/ui/screen-placeholder.vue'))
|
const ScreenPlaceholder = defineAsyncComponent(() => import('@/components/ui/screen-placeholder.vue'))
|
||||||
|
@ -71,14 +71,13 @@ const {
|
||||||
clearQueue: true
|
clearQueue: true
|
||||||
})
|
})
|
||||||
|
|
||||||
const state = reactive(queueStore.state)
|
const songs = toRef(queueStore.state, 'songs')
|
||||||
const songState = reactive(songStore.state)
|
const songState = reactive(songStore.state)
|
||||||
|
|
||||||
const shouldShowShufflingAllLink = computed(() => songState.songs.length > 0)
|
const shouldShowShufflingAllLink = computed(() => songState.songs.length > 0)
|
||||||
|
|
||||||
const playAll = () => {
|
const playAll = () => {
|
||||||
// @ts-ignore
|
playback.queueAndPlay(songs.value.length ? songList.value.getAllSongsWithSort() : songStore.all)
|
||||||
playback.queueAndPlay(state.songs.length ? songList.value?.getAllSongsWithSort() : songStore.all)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const shuffleAll = async () => await playback.queueAndPlay(songStore.all, true)
|
const shuffleAll = async () => await playback.queueAndPlay(songStore.all, true)
|
||||||
|
|
|
@ -31,23 +31,14 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed, defineAsyncComponent, PropType, toRefs } from 'vue'
|
import { computed, defineAsyncComponent, toRefs } from 'vue'
|
||||||
import { eventBus, pluralize, startDragging } from '@/utils'
|
import { eventBus, pluralize, startDragging } from '@/utils'
|
||||||
import { queueStore } from '@/stores'
|
import { queueStore } from '@/stores'
|
||||||
import { playback } from '@/services'
|
import { playback } from '@/services'
|
||||||
|
|
||||||
const LikeButton = defineAsyncComponent(() => import('@/components/song/like-button.vue'))
|
const LikeButton = defineAsyncComponent(() => import('@/components/song/like-button.vue'))
|
||||||
|
|
||||||
const props = defineProps({
|
const props = withDefaults(defineProps<{ song: Song, topPlayCount?: number }>(), { topPlayCount: 0 })
|
||||||
song: {
|
|
||||||
type: Object as PropType<Song>,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
topPlayCount: {
|
|
||||||
type: Number,
|
|
||||||
default: 0
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const { song, topPlayCount } = toRefs(props)
|
const { song, topPlayCount } = toRefs(props)
|
||||||
|
|
||||||
|
|
|
@ -112,7 +112,7 @@
|
||||||
import { computed, defineAsyncComponent, nextTick, reactive, ref, toRefs } from 'vue'
|
import { computed, defineAsyncComponent, nextTick, reactive, ref, toRefs } from 'vue'
|
||||||
import { isEqual, union } from 'lodash'
|
import { isEqual, union } from 'lodash'
|
||||||
|
|
||||||
import { alerts, br2nl, getDefaultCover } from '@/utils'
|
import { alerts, br2nl, getDefaultCover, arrayify } from '@/utils'
|
||||||
import { songInfo } from '@/services/info'
|
import { songInfo } from '@/services/info'
|
||||||
import { albumStore, artistStore, songStore } from '@/stores'
|
import { albumStore, artistStore, songStore } from '@/stores'
|
||||||
|
|
||||||
|
@ -234,7 +234,7 @@ const initCompilationStateCheckbox = async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const open = async () => {
|
const open = async () => {
|
||||||
mutatedSongs.value = ([] as Song[]).concat(songs.value)
|
mutatedSongs.value = arrayify(songs.value)
|
||||||
currentView.value = initialTab!.value
|
currentView.value = initialTab!.value
|
||||||
const firstSong = mutatedSongs.value[0]
|
const firstSong = mutatedSongs.value[0]
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ import {
|
||||||
} from 'vue'
|
} from 'vue'
|
||||||
import { RecycleScroller } from 'vue-virtual-scroller'
|
import { RecycleScroller } from 'vue-virtual-scroller'
|
||||||
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
|
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
|
||||||
import { $, eventBus, orderBy, startDragging } from '@/utils'
|
import { $, eventBus, orderBy, startDragging, arrayify } from '@/utils'
|
||||||
import { favoriteStore, playlistStore, queueStore } from '@/stores'
|
import { favoriteStore, playlistStore, queueStore } from '@/stores'
|
||||||
import { playback } from '@/services'
|
import { playback } from '@/services'
|
||||||
import router from '@/router'
|
import router from '@/router'
|
||||||
|
@ -101,26 +101,10 @@ interface SongRow {
|
||||||
|
|
||||||
const SongItem = defineAsyncComponent(() => import('@/components/song/item.vue'))
|
const SongItem = defineAsyncComponent(() => import('@/components/song/item.vue'))
|
||||||
|
|
||||||
// @ts-ignore
|
const props = withDefaults(
|
||||||
getCurrentInstance()!.__IS_SONG_LIST__ = true
|
defineProps<{ items: Song[], playlist?: Playlist, type?: SongListType, config?: Partial<SongListConfig> }>(),
|
||||||
|
{ type: 'all-songs', config: () => ({}) }
|
||||||
const props = defineProps({
|
)
|
||||||
items: {
|
|
||||||
type: Array as PropType<Song[]>,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
playlist: {
|
|
||||||
type: Object as PropType<Playlist>
|
|
||||||
},
|
|
||||||
type: {
|
|
||||||
type: String as PropType<SongListType>,
|
|
||||||
default: 'all-songs'
|
|
||||||
},
|
|
||||||
config: {
|
|
||||||
type: Object as PropType<Partial<SongListConfig>>,
|
|
||||||
default: () => ({})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const { items, playlist, type, config } = toRefs(props)
|
const { items, playlist, type, config } = toRefs(props)
|
||||||
|
|
||||||
|
@ -170,7 +154,7 @@ const sort = (field: SortField | SortField[] = [], order: SortOrder | null = nul
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sortFields.value = ([] as SortField[]).concat(field)
|
sortFields.value = arrayify(field)
|
||||||
|
|
||||||
if (!sortFields.value.length && ['album', 'artist'].includes(type.value)) {
|
if (!sortFields.value.length && ['album', 'artist'].includes(type.value)) {
|
||||||
// by default, sort Album/Artist by track numbers for a more friendly UX
|
// by default, sort Album/Artist by track numbers for a more friendly UX
|
||||||
|
|
|
@ -25,15 +25,9 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { PropType, ref, toRefs, watchEffect } from 'vue'
|
import { ref, toRefs, watchEffect } from 'vue'
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
value: {
|
|
||||||
type: String as PropType<ArtistAlbumViewMode>,
|
|
||||||
default: 'thumbnails'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<{ value?: ArtistAlbumViewMode }>(), { value: 'thumbnails' })
|
||||||
const { value } = toRefs(props)
|
const { value } = toRefs(props)
|
||||||
|
|
||||||
let modelValue = ref<ArtistAlbumViewMode>()
|
let modelValue = ref<ArtistAlbumViewMode>()
|
||||||
|
|
|
@ -13,7 +13,7 @@ import SongListControls from '@/components/song/list-controls.vue'
|
||||||
import { songStore } from '@/stores'
|
import { songStore } from '@/stores'
|
||||||
|
|
||||||
export const useSongList = (controlsConfig: Partial<SongListControlsConfig> = {}) => {
|
export const useSongList = (controlsConfig: Partial<SongListControlsConfig> = {}) => {
|
||||||
const songList = ref(null)
|
const songList = ref<InstanceType<typeof SongList>>()
|
||||||
const state = reactive<SongListState>({ songs: [] })
|
const state = reactive<SongListState>({ songs: [] })
|
||||||
|
|
||||||
const meta = reactive<SongListMeta>({
|
const meta = reactive<SongListMeta>({
|
||||||
|
@ -35,7 +35,7 @@ export const useSongList = (controlsConfig: Partial<SongListControlsConfig> = {}
|
||||||
meta.totalLength = songStore.getFormattedLength(state.songs)
|
meta.totalLength = songStore.getFormattedLength(state.songs)
|
||||||
})
|
})
|
||||||
|
|
||||||
const getSongsToPlay = (): Song[] => (songList.value as any).getAllSongsWithSort()
|
const getSongsToPlay = (): Song[] => songList.value.getAllSongsWithSort()
|
||||||
const playAll = (shuffled: boolean) => playback.queueAndPlay(getSongsToPlay(), shuffled)
|
const playAll = (shuffled: boolean) => playback.queueAndPlay(getSongsToPlay(), shuffled)
|
||||||
const playSelected = (shuffled: boolean) => playback.queueAndPlay(selectedSongs.value, shuffled)
|
const playSelected = (shuffled: boolean) => playback.queueAndPlay(selectedSongs.value, shuffled)
|
||||||
const toggleControls = () => (showingControls.value = !showingControls.value)
|
const toggleControls = () => (showingControls.value = !showingControls.value)
|
||||||
|
|
|
@ -5,6 +5,8 @@ import { favoriteStore, playlistStore, queueStore } from '@/stores'
|
||||||
* Each component including this mixin must have a `songs` array as either data, prop, or computed.
|
* Each component including this mixin must have a `songs` array as either data, prop, or computed.
|
||||||
*/
|
*/
|
||||||
export const useSongMenuMethods = (songs: Song[], close: TAnyFunction) => {
|
export const useSongMenuMethods = (songs: Song[], close: TAnyFunction) => {
|
||||||
|
console.log(songs)
|
||||||
|
|
||||||
const queueSongsAfterCurrent = () => {
|
const queueSongsAfterCurrent = () => {
|
||||||
queueStore.queueAfterCurrent(songs)
|
queueStore.queueAfterCurrent(songs)
|
||||||
close()
|
close()
|
||||||
|
|
|
@ -1,16 +1,10 @@
|
||||||
import { playlistStore, favoriteStore } from '@/stores'
|
import { favoriteStore, playlistStore } from '@/stores'
|
||||||
import { auth } from '.'
|
import { auth } from '.'
|
||||||
import { alerts } from '@/utils'
|
import { alerts, arrayify } from '@/utils'
|
||||||
|
|
||||||
let events: any
|
|
||||||
|
|
||||||
if (KOEL_ENV === 'app') {
|
|
||||||
events = require('&/events').default
|
|
||||||
}
|
|
||||||
|
|
||||||
export const download = {
|
export const download = {
|
||||||
fromSongs (songs: Song | Song[]): void {
|
fromSongs (songs: Song | Song[]): void {
|
||||||
const query = (<Song[]>[]).concat(songs).reduce((q, song) => `songs[]=${song.id}&${q}`, '')
|
const query = arrayify(songs).reduce((q, song) => `songs[]=${song.id}&${q}`, '')
|
||||||
this.trigger(`songs?${query}`)
|
this.trigger(`songs?${query}`)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { union, difference, take, orderBy } from 'lodash'
|
||||||
import stub from '@/stubs/album'
|
import stub from '@/stubs/album'
|
||||||
import { artistStore } from '.'
|
import { artistStore } from '.'
|
||||||
import { http } from '@/services'
|
import { http } from '@/services'
|
||||||
import { use } from '@/utils'
|
import { arrayify, use } from '@/utils'
|
||||||
|
|
||||||
const UNKNOWN_ALBUM_ID = 1
|
const UNKNOWN_ALBUM_ID = 1
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ export const albumStore = {
|
||||||
},
|
},
|
||||||
|
|
||||||
add (albums: Album | Album[]): void {
|
add (albums: Album | Album[]): void {
|
||||||
(<Album[]>[]).concat(albums).forEach(album => {
|
arrayify(albums).forEach(album => {
|
||||||
this.setupAlbum(album)
|
this.setupAlbum(album)
|
||||||
album.playCount = album.songs.reduce((count, song) => count + song.playCount, 0)
|
album.playCount = album.songs.reduce((count, song) => count + song.playCount, 0)
|
||||||
this.all.push(album)
|
this.all.push(album)
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { difference, take, orderBy } from 'lodash'
|
||||||
|
|
||||||
import { http } from '@/services'
|
import { http } from '@/services'
|
||||||
import stub from '@/stubs/artist'
|
import stub from '@/stubs/artist'
|
||||||
import { use } from '@/utils'
|
import { arrayify, use } from '@/utils'
|
||||||
|
|
||||||
const UNKNOWN_ARTIST_ID = 1
|
const UNKNOWN_ARTIST_ID = 1
|
||||||
const VARIOUS_ARTISTS_ID = 2
|
const VARIOUS_ARTISTS_ID = 2
|
||||||
|
@ -50,7 +50,7 @@ export const artistStore = {
|
||||||
},
|
},
|
||||||
|
|
||||||
add (artists: Artist | Artist[]) {
|
add (artists: Artist | Artist[]) {
|
||||||
(<Artist[]>[]).concat(artists).forEach(artist => {
|
arrayify(artists).forEach(artist => {
|
||||||
this.setupArtist(artist)
|
this.setupArtist(artist)
|
||||||
artist.playCount = artist.songs.reduce((count, song) => count + song.playCount, 0)
|
artist.playCount = artist.songs.reduce((count, song) => count + song.playCount, 0)
|
||||||
this.all.push(artist)
|
this.all.push(artist)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { difference, union } from 'lodash'
|
import { difference, union } from 'lodash'
|
||||||
import { http } from '@/services'
|
import { http } from '@/services'
|
||||||
|
import { arrayify } from '@/utils'
|
||||||
|
|
||||||
export const favoriteStore = {
|
export const favoriteStore = {
|
||||||
state: {
|
state: {
|
||||||
|
@ -29,14 +30,14 @@ export const favoriteStore = {
|
||||||
* Add a song/songs into the store.
|
* Add a song/songs into the store.
|
||||||
*/
|
*/
|
||||||
add (songs: Song | Song[]): void {
|
add (songs: Song | Song[]): void {
|
||||||
this.all = union(this.all, (<Song[]>[]).concat(songs))
|
this.all = union(this.all, arrayify(songs))
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a song/songs from the store.
|
* Remove a song/songs from the store.
|
||||||
*/
|
*/
|
||||||
remove (songs: Song | Song[]): void {
|
remove (songs: Song | Song[]): void {
|
||||||
this.all = difference(this.all, (<Song[]>[]).concat(songs))
|
this.all = difference(this.all, arrayify(songs))
|
||||||
},
|
},
|
||||||
|
|
||||||
clear (): void {
|
clear (): void {
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { difference, union, orderBy } from 'lodash'
|
||||||
|
|
||||||
import stub from '@/stubs/playlist'
|
import stub from '@/stubs/playlist'
|
||||||
import { http } from '@/services'
|
import { http } from '@/services'
|
||||||
import { alerts, pluralize } from '@/utils'
|
import { alerts, pluralize, arrayify } from '@/utils'
|
||||||
import { songStore } from '.'
|
import { songStore } from '.'
|
||||||
import models from '@/config/smart-playlist/models'
|
import models from '@/config/smart-playlist/models'
|
||||||
import operators from '@/config/smart-playlist/operators'
|
import operators from '@/config/smart-playlist/operators'
|
||||||
|
@ -79,7 +79,7 @@ export const playlistStore = {
|
||||||
* Add a playlist/playlists into the store.
|
* Add a playlist/playlists into the store.
|
||||||
*/
|
*/
|
||||||
add (playlists: Playlist | Playlist[]) {
|
add (playlists: Playlist | Playlist[]) {
|
||||||
const playlistsToAdd = (<Playlist[]>[]).concat(playlists)
|
const playlistsToAdd = arrayify(playlists)
|
||||||
playlistsToAdd.forEach(playlist => this.setupPlaylist(playlist))
|
playlistsToAdd.forEach(playlist => this.setupPlaylist(playlist))
|
||||||
this.all = this.sort(union(this.all, playlistsToAdd))
|
this.all = this.sort(union(this.all, playlistsToAdd))
|
||||||
},
|
},
|
||||||
|
@ -88,7 +88,7 @@ export const playlistStore = {
|
||||||
* Remove a playlist/playlists from the store.
|
* Remove a playlist/playlists from the store.
|
||||||
*/
|
*/
|
||||||
remove (playlists: Playlist | Playlist[]) {
|
remove (playlists: Playlist | Playlist[]) {
|
||||||
this.all = difference(this.all, (<Playlist[]>[]).concat(playlists))
|
this.all = difference(this.all, arrayify(playlists))
|
||||||
},
|
},
|
||||||
|
|
||||||
async store (name: string, songs: Song[] = [], rules: SmartPlaylistRuleGroup[] = []): Promise<Playlist> {
|
async store (name: string, songs: Song[] = [], rules: SmartPlaylistRuleGroup[] = []): Promise<Playlist> {
|
||||||
|
@ -169,7 +169,7 @@ export const playlistStore = {
|
||||||
/**
|
/**
|
||||||
* Serialize the rule (groups) to be ready for database.
|
* Serialize the rule (groups) to be ready for database.
|
||||||
*/
|
*/
|
||||||
serializeSmartPlaylistRulesForStorage: (ruleGroups: SmartPlaylistRuleGroup[]): object[] | null => {
|
serializeSmartPlaylistRulesForStorage: (ruleGroups: SmartPlaylistRuleGroup[]): any[] | null => {
|
||||||
if (!ruleGroups || !ruleGroups.length) {
|
if (!ruleGroups || !ruleGroups.length) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import { union, difference, shuffle } from 'lodash'
|
import { union, difference, shuffle } from 'lodash'
|
||||||
|
import { reactive } from 'vue'
|
||||||
|
import { arrayify } from '@/utils'
|
||||||
|
|
||||||
export const queueStore = {
|
export const queueStore = {
|
||||||
state: {
|
state: reactive({
|
||||||
songs: [] as Song[],
|
songs: [] as Song[],
|
||||||
current: undefined as Song | undefined
|
current: undefined as Song | undefined
|
||||||
},
|
}),
|
||||||
|
|
||||||
init () {
|
init () {
|
||||||
// We don't have anything to do here yet.
|
// We don't have anything to do here yet.
|
||||||
|
@ -57,7 +59,7 @@ export const queueStore = {
|
||||||
*/
|
*/
|
||||||
queue (songs: Song | Song[]): void {
|
queue (songs: Song | Song[]): void {
|
||||||
this.unqueue(songs)
|
this.unqueue(songs)
|
||||||
this.all = union(this.all, (<Song[]>[]).concat(songs))
|
this.all = union(this.all, arrayify(songs))
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -65,7 +67,7 @@ export const queueStore = {
|
||||||
* @param {Song|Song[]} songs The song, or an array of songs
|
* @param {Song|Song[]} songs The song, or an array of songs
|
||||||
*/
|
*/
|
||||||
queueToTop (songs: Song | Song[]): void {
|
queueToTop (songs: Song | Song[]): void {
|
||||||
this.all = union((<Song[]>[]).concat(songs), this.all)
|
this.all = union(arrayify(songs), this.all)
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -73,7 +75,7 @@ export const queueStore = {
|
||||||
* @param {Song|Song[]} songs The song, or an array of songs
|
* @param {Song|Song[]} songs The song, or an array of songs
|
||||||
*/
|
*/
|
||||||
replaceQueueWith (songs: Song | Song[]): void {
|
replaceQueueWith (songs: Song | Song[]): void {
|
||||||
this.all = (<Song[]>[]).concat(songs)
|
this.all = arrayify(songs)
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -81,7 +83,7 @@ export const queueStore = {
|
||||||
* @param {Song|Song[]} songs The song, or an array of songs
|
* @param {Song|Song[]} songs The song, or an array of songs
|
||||||
*/
|
*/
|
||||||
queueAfterCurrent (songs: Song | Song[]): void {
|
queueAfterCurrent (songs: Song | Song[]): void {
|
||||||
songs = (<Song[]>[]).concat(songs)
|
songs = arrayify(songs)
|
||||||
|
|
||||||
if (!this.current || !this.all.length) {
|
if (!this.current || !this.all.length) {
|
||||||
return this.queue(songs)
|
return this.queue(songs)
|
||||||
|
@ -95,7 +97,7 @@ export const queueStore = {
|
||||||
},
|
},
|
||||||
|
|
||||||
unqueue (songs: Song | Song[]): void {
|
unqueue (songs: Song | Song[]): void {
|
||||||
this.all = difference(this.all, (<Song[]>[]).concat(songs))
|
this.all = difference(this.all, arrayify(songs))
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -106,7 +108,7 @@ export const queueStore = {
|
||||||
*/
|
*/
|
||||||
move (songs: Song | Song[], target: Song): void {
|
move (songs: Song | Song[], target: Song): void {
|
||||||
const targetIndex = this.indexOf(target)
|
const targetIndex = this.indexOf(target)
|
||||||
const movedSongs = (<Song[]>[]).concat(songs)
|
const movedSongs = arrayify(songs)
|
||||||
|
|
||||||
movedSongs.forEach(song => {
|
movedSongs.forEach(song => {
|
||||||
this.all.splice(this.indexOf(song), 1)
|
this.all.splice(this.indexOf(song), 1)
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import Vue from 'vue'
|
import { reactive } from 'vue'
|
||||||
import slugify from 'slugify'
|
import slugify from 'slugify'
|
||||||
import { without, take, remove, orderBy, unionBy } from 'lodash'
|
import { orderBy, remove, take, unionBy, without } from 'lodash'
|
||||||
import isMobile from 'ismobilejs'
|
import isMobile from 'ismobilejs'
|
||||||
|
|
||||||
import { secondsToHis, alerts, pluralize, use } from '@/utils'
|
import { alerts, arrayify, pluralize, secondsToHis, use } from '@/utils'
|
||||||
import { http, auth, ls } from '@/services'
|
import { auth, http, ls } from '@/services'
|
||||||
import { sharedStore, favoriteStore, albumStore, artistStore, preferenceStore } from '.'
|
import { albumStore, artistStore, favoriteStore, preferenceStore, sharedStore } from '.'
|
||||||
import stub from '@/stubs/song'
|
import stub from '@/stubs/song'
|
||||||
|
|
||||||
interface BroadcastSongData {
|
interface BroadcastSongData {
|
||||||
|
@ -34,10 +34,10 @@ export const songStore = {
|
||||||
stub,
|
stub,
|
||||||
cache: {} as { [key: string]: Song },
|
cache: {} as { [key: string]: Song },
|
||||||
|
|
||||||
state: {
|
state: reactive({
|
||||||
songs: [] as Song[],
|
songs: [] as Song[],
|
||||||
recentlyPlayed: [] as Song[]
|
recentlyPlayed: [] as Song[]
|
||||||
},
|
}),
|
||||||
|
|
||||||
init (songs: Song[]): void {
|
init (songs: Song[]): void {
|
||||||
this.all = songs
|
this.all = songs
|
||||||
|
@ -107,7 +107,7 @@ export const songStore = {
|
||||||
},
|
},
|
||||||
|
|
||||||
getFormattedLength (songs: Song[]): string {
|
getFormattedLength (songs: Song[]): string {
|
||||||
return <string>this.getLength(songs, true)
|
return String(this.getLength(songs, true))
|
||||||
},
|
},
|
||||||
|
|
||||||
get all (): Song[] {
|
get all (): Song[] {
|
||||||
|
@ -124,7 +124,7 @@ export const songStore = {
|
||||||
|
|
||||||
byIds (ids: string[]): Song[] {
|
byIds (ids: string[]): Song[] {
|
||||||
const songs = [] as Song[]
|
const songs = [] as Song[]
|
||||||
([] as string[]).concat(ids).forEach(id => use(this.byId(id), song => songs.push(song!)))
|
arrayify(ids).forEach(id => use(this.byId(id), song => songs.push(song!)))
|
||||||
return songs
|
return songs
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
1
resources/assets/js/types.d.ts
vendored
1
resources/assets/js/types.d.ts
vendored
|
@ -1,5 +1,6 @@
|
||||||
declare module '*.jpg'
|
declare module '*.jpg'
|
||||||
declare module '*.png'
|
declare module '*.png'
|
||||||
|
declare module '*.svg'
|
||||||
|
|
||||||
declare type TAnyFunction = (...args: Array<unknown|any>) => unknown|any
|
declare type TAnyFunction = (...args: Array<unknown|any>) => unknown|any
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import select from 'select'
|
import select from 'select'
|
||||||
import { eventBus, noop, pluralize } from '@/utils'
|
import { eventBus, noop, pluralize, arrayify } from '@/utils'
|
||||||
import defaultCover from '@/../img/covers/unknown-album.png'
|
import defaultCover from '@/../img/covers/unknown-album.png'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -81,7 +81,7 @@ export const startDragging = (event: DragEvent, dragged: Song | Song[] | Album |
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'Song':
|
case 'Song':
|
||||||
dragged = (<Song[]>[]).concat(<Song>dragged)
|
dragged = arrayify(<Song>dragged)
|
||||||
text = dragged.length === 1
|
text = dragged.length === 1
|
||||||
? `${dragged[0].title} by ${dragged[0].artist.name}`
|
? `${dragged[0].title} by ${dragged[0].artist.name}`
|
||||||
: pluralize(dragged.length, 'song')
|
: pluralize(dragged.length, 'song')
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export const use = <T>(value: T, cb: (arg: T) => void): void => {
|
export const use = <T> (value: T, cb: (arg: T) => void) => {
|
||||||
if (typeof value === 'undefined' || value === null) {
|
if (typeof value === 'undefined' || value === null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -6,4 +6,7 @@ export const use = <T>(value: T, cb: (arg: T) => void): void => {
|
||||||
cb(value)
|
cb(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const arrayify = <T> (maybeArray: T | Array<T>) => ([] as Array<T>).concat(maybeArray)
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
export const noop = () => {}
|
export const noop = () => {}
|
||||||
|
|
Loading…
Add table
Reference in a new issue