feat: synchronize sorting

This commit is contained in:
Phan An 2022-07-05 17:09:20 +02:00
parent bd5cd1e621
commit 64c6eebdcd
No known key found for this signature in database
GPG key ID: A81E4477F0BB6FDC
5 changed files with 58 additions and 35 deletions

View file

@ -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) => {

View file

@ -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 &quot;Add To&quot; button to fill it up.
Drag songs into its name in the sidebar or use the &quot;Add To&quot; 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({

View file

@ -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>
&nbsp;<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)

View file

@ -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,

View file

@ -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')