mirror of
https://github.com/koel/koel
synced 2024-11-24 21:23:06 +00:00
feat: synchronize sorting
This commit is contained in:
parent
bd5cd1e621
commit
64c6eebdcd
5 changed files with 58 additions and 35 deletions
|
@ -86,7 +86,7 @@ let initialized = false
|
|||
const fetchSongs = async () => {
|
||||
await favoriteStore.fetch()
|
||||
await nextTick()
|
||||
sort('title', 'asc')
|
||||
sort()
|
||||
}
|
||||
|
||||
eventBus.on('LOAD_MAIN_CONTENT', async (view: MainViewName) => {
|
||||
|
|
|
@ -47,8 +47,7 @@
|
|||
<template v-else>
|
||||
The playlist is currently empty.
|
||||
<span class="d-block secondary">
|
||||
Drag songs into its name in the sidebar
|
||||
or use the "Add To…" button to fill it up.
|
||||
Drag songs into its name in the sidebar or use the "Add To…" button to fill it up.
|
||||
</span>
|
||||
</template>
|
||||
</ScreenEmptyState>
|
||||
|
@ -57,7 +56,7 @@
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { difference } from 'lodash'
|
||||
import { defineAsyncComponent, nextTick, ref, toRef } from 'vue'
|
||||
import { defineAsyncComponent, ref, toRef } from 'vue'
|
||||
import { alerts, eventBus, pluralize } from '@/utils'
|
||||
import { commonStore, playlistStore, songStore } from '@/stores'
|
||||
import { downloadService } from '@/services'
|
||||
|
@ -107,8 +106,7 @@ const fetchSongs = async () => {
|
|||
loading.value = true
|
||||
playlistSongs.value = await songStore.fetchForPlaylist(playlist.value!)
|
||||
loading.value = false
|
||||
await nextTick()
|
||||
sort('title', 'asc')
|
||||
sort()
|
||||
}
|
||||
|
||||
eventBus.on({
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
@click="sort('track')"
|
||||
>
|
||||
#
|
||||
<i v-show="currentSortField === 'track' && sortOrder === 'asc'" class="fa fa-angle-down"></i>
|
||||
<i v-show="currentSortField === 'track' && sortOrder === 'desc'" class="fa fa-angle-up"></i>
|
||||
<i v-show="sortField === 'track' && sortOrder === 'asc'" class="fa fa-angle-down"></i>
|
||||
<i v-show="sortField === 'track' && sortOrder === 'desc'" class="fa fa-angle-up"></i>
|
||||
</span>
|
||||
<span
|
||||
v-if="config.columns.includes('title')"
|
||||
|
@ -27,8 +27,8 @@
|
|||
@click="sort('title')"
|
||||
>
|
||||
Title
|
||||
<i v-show="currentSortField === 'title' && sortOrder === 'asc'" class="fa fa-angle-down"></i>
|
||||
<i v-show="currentSortField === 'title' && sortOrder === 'desc'" class="fa fa-angle-up"></i>
|
||||
<i v-show="sortField === 'title' && sortOrder === 'asc'" class="fa fa-angle-down"></i>
|
||||
<i v-show="sortField === 'title' && sortOrder === 'desc'" class="fa fa-angle-up"></i>
|
||||
</span>
|
||||
<span
|
||||
v-if="config.columns.includes('artist')"
|
||||
|
@ -37,8 +37,8 @@
|
|||
@click="sort('artist_name')"
|
||||
>
|
||||
Artist
|
||||
<i v-show="currentSortField === 'artist_name' && sortOrder === 'asc'" class="fa fa-angle-down"></i>
|
||||
<i v-show="currentSortField === 'artist_name' && sortOrder === 'desc'" class="fa fa-angle-up"></i>
|
||||
<i v-show="sortField === 'artist_name' && sortOrder === 'asc'" class="fa fa-angle-down"></i>
|
||||
<i v-show="sortField === 'artist_name' && sortOrder === 'desc'" class="fa fa-angle-up"></i>
|
||||
</span>
|
||||
<span
|
||||
v-if="config.columns.includes('album')"
|
||||
|
@ -47,8 +47,8 @@
|
|||
@click="sort('album_name')"
|
||||
>
|
||||
Album
|
||||
<i v-show="currentSortField === 'album_name' && sortOrder === 'asc'" class="fa fa-angle-down"></i>
|
||||
<i v-show="currentSortField === 'album_name' && sortOrder === 'desc'" class="fa fa-angle-up"></i>
|
||||
<i v-show="sortField === 'album_name' && sortOrder === 'asc'" class="fa fa-angle-down"></i>
|
||||
<i v-show="sortField === 'album_name' && sortOrder === 'desc'" class="fa fa-angle-up"></i>
|
||||
</span>
|
||||
<span
|
||||
v-if="config.columns.includes('length')"
|
||||
|
@ -56,8 +56,8 @@
|
|||
data-testid="header-length"
|
||||
@click="sort('length')"
|
||||
>
|
||||
<i v-show="currentSortField === 'length' && sortOrder === 'asc'" class="fa fa-angle-down"></i>
|
||||
<i v-show="currentSortField === 'length' && sortOrder === 'desc'" class="fa fa-angle-up"></i>
|
||||
<i v-show="sortField === 'length' && sortOrder === 'asc'" class="fa fa-angle-down"></i>
|
||||
<i v-show="sortField === 'length' && sortOrder === 'desc'" class="fa fa-angle-up"></i>
|
||||
<i class="duration-header fa fa-clock-o"></i>
|
||||
</span>
|
||||
<span class="favorite"></span>
|
||||
|
@ -87,7 +87,14 @@ import isMobile from 'ismobilejs'
|
|||
import { findIndex } from 'lodash'
|
||||
import { computed, defineAsyncComponent, inject, onMounted, ref, watch } from 'vue'
|
||||
import { $, eventBus, startDragging } from '@/utils'
|
||||
import { SelectedSongsKey, SongListConfigKey, SongListTypeKey, SongsKey } from '@/symbols'
|
||||
import {
|
||||
SelectedSongsKey,
|
||||
SongListConfigKey,
|
||||
SongListSortFieldKey,
|
||||
SongListSortOrderKey,
|
||||
SongListTypeKey,
|
||||
SongsKey
|
||||
} from '@/symbols'
|
||||
|
||||
const VirtualScroller = defineAsyncComponent(() => import('@/components/ui/VirtualScroller.vue'))
|
||||
const SongListItem = defineAsyncComponent(() => import('@/components/song/SongListItem.vue'))
|
||||
|
@ -97,10 +104,11 @@ const emit = defineEmits(['press:enter', 'press:delete', 'reorder', 'sort', 'scr
|
|||
const items = inject(SongsKey, ref([]))
|
||||
const type = inject(SongListTypeKey, 'all-songs')
|
||||
const selectedSongs = inject(SelectedSongsKey, ref([]))
|
||||
const sortField = inject(SongListSortFieldKey, ref('title'))
|
||||
const sortOrder = inject(SongListSortOrderKey, ref('asc'))
|
||||
|
||||
const lastSelectedRow = ref<SongRow>()
|
||||
const sortFields = ref<SongListSortField[]>([])
|
||||
const sortOrder = ref<SortOrder>('asc')
|
||||
const songRows = ref<SongRow[]>([])
|
||||
|
||||
const allowReordering = type === 'queue'
|
||||
|
@ -116,12 +124,6 @@ const config = computed((): SongListConfig => {
|
|||
}, inject(SongListConfigKey, {}))
|
||||
})
|
||||
|
||||
const currentSortField = ref<SongListSortField | null>((() => {
|
||||
if (type === 'album' || type === 'artist') return 'track'
|
||||
if (type === 'search-results') return null
|
||||
return config.value.sortable ? 'title' : null
|
||||
})())
|
||||
|
||||
/**
|
||||
* Since song objects themselves are shared by all song lists, we can't use them directly to
|
||||
* determine their selection status (selected/unselected). Therefore, for each song list, we
|
||||
|
@ -144,7 +146,7 @@ const sort = (field: SongListSortField) => {
|
|||
return
|
||||
}
|
||||
|
||||
currentSortField.value = field
|
||||
sortField.value = field
|
||||
sortOrder.value = sortOrder.value === 'asc' ? 'desc' : 'asc'
|
||||
|
||||
emit('sort', field, sortOrder.value)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { computed, getCurrentInstance, provide, reactive, Ref, ref } from 'vue'
|
||||
import { computed, provide, reactive, Ref, ref } from 'vue'
|
||||
import isMobile from 'ismobilejs'
|
||||
import { orderBy } from 'lodash'
|
||||
|
||||
|
@ -9,14 +9,20 @@ import router from '@/router'
|
|||
import ControlsToggle from '@/components/ui/ScreenControlsToggle.vue'
|
||||
import SongList from '@/components/song/SongList.vue'
|
||||
import SongListControls from '@/components/song/SongListControls.vue'
|
||||
import { SelectedSongsKey, SongListConfigKey, SongListTypeKey, SongsKey } from '@/symbols'
|
||||
import {
|
||||
SelectedSongsKey,
|
||||
SongListConfigKey,
|
||||
SongListSortFieldKey,
|
||||
SongListSortOrderKey,
|
||||
SongListTypeKey,
|
||||
SongsKey
|
||||
} from '@/symbols'
|
||||
|
||||
export const useSongList = (
|
||||
songs: Ref<Song[]>,
|
||||
type: SongListType,
|
||||
config: Partial<SongListConfig> = {}
|
||||
) => {
|
||||
const vm = getCurrentInstance()
|
||||
const songList = ref<InstanceType<typeof SongList>>()
|
||||
|
||||
const isPhone = isMobile.phone
|
||||
|
@ -50,32 +56,47 @@ export const useSongList = (
|
|||
router.go('/queue')
|
||||
}
|
||||
|
||||
const sort = (sortField: SongListSortField | null, sortOrder: SortOrder) => {
|
||||
if (!sortField) return
|
||||
const sortField = ref<SongListSortField | null>(((): SongListSortField | null => {
|
||||
if (type === 'album' || type === 'artist') return 'track'
|
||||
if (type === 'search-results') return null
|
||||
return config.sortable ? 'title' : null
|
||||
})())
|
||||
|
||||
let sortFields: SongListSortField[] = [sortField]
|
||||
const sortOrder = ref<SortOrder>('asc')
|
||||
|
||||
if (sortField === 'track') {
|
||||
const sort = (by: SongListSortField | null = sortField.value, order: SortOrder = sortOrder.value) => {
|
||||
if (!by) return
|
||||
|
||||
sortField.value = by
|
||||
sortOrder.value = order
|
||||
|
||||
let sortFields: SongListSortField[] = [by]
|
||||
|
||||
if (by === 'track') {
|
||||
sortFields.push('disc', 'title')
|
||||
} else if (sortField === 'album_name') {
|
||||
} else if (by === 'album_name') {
|
||||
sortFields.push('artist_name', 'track', 'disc', 'title')
|
||||
} else if (sortField === 'artist_name') {
|
||||
} else if (by === 'artist_name') {
|
||||
sortFields.push('album_name', 'track', 'disc', 'title')
|
||||
}
|
||||
|
||||
songs.value = orderBy(songs.value, sortFields, sortOrder)
|
||||
songs.value = orderBy(songs.value, sortFields, order)
|
||||
}
|
||||
|
||||
provide(SongListTypeKey, type)
|
||||
provide(SongsKey, songs)
|
||||
provide(SelectedSongsKey, selectedSongs)
|
||||
provide(SongListConfigKey, reactive(config))
|
||||
provide(SongListSortFieldKey, sortField)
|
||||
provide(SongListSortOrderKey, sortOrder)
|
||||
|
||||
return {
|
||||
SongList,
|
||||
SongListControls,
|
||||
ControlsToggle,
|
||||
songs,
|
||||
sortField,
|
||||
sortOrder,
|
||||
duration,
|
||||
songList,
|
||||
selectedSongs,
|
||||
|
|
|
@ -4,3 +4,5 @@ export const SongListTypeKey: InjectionKey<SongListType> = Symbol('SongListType'
|
|||
export const SongsKey: InjectionKey<Ref<Song[]>> = Symbol('Songs')
|
||||
export const SelectedSongsKey: InjectionKey<Ref<Song[]>> = Symbol('SelectedSongs')
|
||||
export const SongListConfigKey: InjectionKey<Partial<SongListConfig>> = Symbol('SongListConfig')
|
||||
export const SongListSortFieldKey: InjectionKey<Ref<SongListSortField>> = Symbol('SongListSortField')
|
||||
export const SongListSortOrderKey: InjectionKey<Ref<SortOrder>> = Symbol('SongListSortOrder')
|
||||
|
|
Loading…
Reference in a new issue