From dc92b47ed01ef301036e401ed43f25e318f62057 Mon Sep 17 00:00:00 2001 From: ThrRip Date: Wed, 18 Dec 2024 09:36:58 +0800 Subject: [PATCH] home: Refactor playlist data processing --- packages/home/app/app.vue | 178 +++++++++++++++++--------------------- 1 file changed, 81 insertions(+), 97 deletions(-) diff --git a/packages/home/app/app.vue b/packages/home/app/app.vue index 93350a1..89c40d4 100644 --- a/packages/home/app/app.vue +++ b/packages/home/app/app.vue @@ -189,7 +189,7 @@ class="aspect-square flex flex-row justify-center items-center h-full rounded-lg hover:bg-gray transition active:scale-95 duration-200" title="随机排列" - @click="viewPlaylistDataUpdate(['shuffle'])" + @click="viewPlaylistShuffle" > @@ -294,9 +294,8 @@ interface Song { type Playlist = Array // Backend -const { data: backendPlaylist } = await useAsyncData( +const { data: backendPlaylist } = await useAsyncData( 'backend-databases-home-playlist', - // @ts-expect-error async () => { const appConfig = useAppConfig() const { Client, Databases, Query } = await import('appwrite') @@ -325,7 +324,7 @@ interface SortingSong extends Song { } type PlaylistSortingOrder = 'ascending' | 'descending' const viewPlaylistSortingColumn = ref(null) -const viewPlaylistSortingOrder = ref('ascending') +const viewPlaylistSortingOrder = ref() const viewPlaylistSortingOrderOptions: Record> = { name: ['ascending', 'descending'], artist: ['ascending', 'descending'], @@ -336,7 +335,6 @@ function viewPlaylistToggleSorting (column: PlaylistColumn) { // Enable sorting or switch to another column if (viewPlaylistSortingColumn.value === null || column !== viewPlaylistSortingColumn.value) { viewPlaylistSortingColumn.value = column - // @ts-expect-error viewPlaylistSortingOrder.value = viewPlaylistSortingOrderOptions[column][0] } else @@ -347,117 +345,104 @@ function viewPlaylistToggleSorting (column: PlaylistColumn) { viewPlaylistSortingOrderOptions[column][viewPlaylistSortingOrderOptions[column].length - 1] ) { viewPlaylistSortingColumn.value = null - // @ts-expect-error viewPlaylistSortingOrder.value = viewPlaylistSortingOrderOptions[column][0] + viewPlaylistDataUpdate(viewPlaylistDataShuffled) + return } // Rotate between ordering options else { - // @ts-expect-error viewPlaylistSortingOrder.value = viewPlaylistSortingOrderOptions[column][ viewPlaylistSortingOrderOptions[column].findIndex(option => option === viewPlaylistSortingOrder.value) + 1 ] } - viewPlaylistDataUpdate(['sort']) + viewPlaylistDataSort( + viewPlaylistData.value, + viewPlaylistSortingColumn.value, + viewPlaylistSortingOrder.value as PlaylistSortingOrder + ).then(dataSorted => viewPlaylistDataUpdate(dataSorted)) } -const viewPlaylistData = useState('viewPlaylistData', () => shallowRef([])) -let viewPlaylistDataShuffled: Playlist = [] -function viewPlaylistDataUpdate (tasks: Array<'shuffle' | 'sort'>) { - // @ts-expect-error - if (backendPlaylist.value.length === 0) return - function shuffle () { - // @ts-expect-error - const playlist = backendPlaylist.value.slice() - let currentSong = playlist.length - while (currentSong !== 0) { - const targetSong = Math.floor(Math.random() * currentSong) - currentSong-- - const targetSongBackup = { ...playlist[targetSong] } - playlist[targetSong] = playlist[currentSong] - playlist[currentSong] = targetSongBackup - } - viewPlaylistDataShuffled = playlist - return playlist - } +function viewPlaylistShuffle () { + viewPlaylistDataUpdate(viewPlaylistDataShuffle(viewPlaylistData.value), 'shuffled') +} - async function sort () { - // @ts-expect-error - const playlist: Array = backendPlaylist.value.slice() - const orderModifier = viewPlaylistSortingOrder.value === 'ascending' ? 1 : -1 +async function viewPlaylistDataSort (data: Playlist, column: PlaylistColumn, order: PlaylistSortingOrder) { + const playlist: Array = data.slice() + const orderModifier = order === 'ascending' ? 1 : -1 - // Sort by song name or artist in alphabetical order - if (viewPlaylistSortingColumn.value === 'name' || viewPlaylistSortingColumn.value === 'artist') { - const pinyinPro = await import('pinyin-pro') - playlist.forEach((song, index) => { - // @ts-expect-error - playlist[index][`${viewPlaylistSortingColumn.value}Pinyin`] = - // @ts-expect-error - pinyinPro.pinyin(song[viewPlaylistSortingColumn.value], { toneType: 'none', nonZh: 'consecutive' }) - .replaceAll(' ', '') - }) - playlist.sort((a, b) => { - // @ts-expect-error - if (a[`${viewPlaylistSortingColumn.value}Pinyin`] < b[`${viewPlaylistSortingColumn.value}Pinyin`]) { - return -1 * orderModifier - } - else + // Sort by song name or artist in alphabetical order + if (column === 'name' || column === 'artist') { + const pinyinPro = await import('pinyin-pro') + playlist.forEach((song, index) => { + // @ts-expect-error + playlist[index][`${column}Pinyin`] = // @ts-expect-error - if (a[`${viewPlaylistSortingColumn.value}Pinyin`] > b[`${viewPlaylistSortingColumn.value}Pinyin`]) { - return 1 * orderModifier - } - else { - return 0 - } - }) - } - else - - // Sort by payment requirement - if (viewPlaylistSortingColumn.value === 'payment_amount') { - playlist.sort((a, b) => { - if (a.payment_required === false || b.payment_required === false) { - return (Number(a.payment_required ?? 0) - Number(b.payment_required ?? 0)) * orderModifier - } - return ((a.payment_amount ?? 0) - (b.payment_amount ?? 0)) * orderModifier - }) - } - else + pinyinPro.pinyin(song[column], { toneType: 'none', nonZh: 'consecutive' }) + .replaceAll(' ', '') + }) + playlist.sort((a, b) => { + // @ts-expect-error + if (a[`${column}Pinyin`] < b[`${column}Pinyin`]) { + return -1 * orderModifier + } + else + // @ts-expect-error + if (a[`${column}Pinyin`] > b[`${column}Pinyin`]) { + return 1 * orderModifier + } + else { + return 0 + } + }) + } + else - // Sort by language - if (viewPlaylistSortingColumn.value === 'language') { - const languageOrder = ['国语', '粤语', '日语'] - playlist.sort((a, b) => { - return (languageOrder.findIndex(language => a.language === language) - - languageOrder.findIndex(language => b.language === language)) * orderModifier - }) - } + // Sort by payment requirement + if (column === 'payment_amount') { + playlist.sort((a, b) => { + if (a.payment_required === false || b.payment_required === false) { + return (Number(a.payment_required ?? 0) - Number(b.payment_required ?? 0)) * orderModifier + } + return ((a.payment_amount ?? 0) - (b.payment_amount ?? 0)) * orderModifier + }) + } + else - return playlist + // Sort by language + if (column === 'language') { + const languageOrder = ['国语', '粤语', '日语'] + playlist.sort((a, b) => { + return (languageOrder.findIndex(language => a.language === language) - + languageOrder.findIndex(language => b.language === language)) * orderModifier + }) } - tasks.forEach(async (task, index) => { - if (task === 'shuffle') { - shuffle() - if (index !== tasks.length - 1) { return } - viewPlaylistSortingColumn.value = null - viewPlaylistDataUpdate(['sort']) - viewPlaylistData.value = viewPlaylistDataShuffled - } - else - if (task === 'sort') { - if (index !== tasks.length - 1) { return } - viewPlaylistData.value = viewPlaylistSortingColumn.value === null ? viewPlaylistDataShuffled : await sort() - } - }) + return playlist +} +let viewPlaylistDataShuffled: Playlist = [] +function viewPlaylistDataShuffle (data: Playlist) { + const playlist = data.slice() + let current = playlist.length + while (current !== 0) { + const target = Math.floor(Math.random() * current) + current-- + const targetSongBackup = { ...playlist[target] } + playlist[target] = playlist[current] as Song + playlist[current] = targetSongBackup as Song + } + viewPlaylistDataShuffled = playlist + return playlist } -callOnce(() => viewPlaylistDataUpdate(['shuffle'])) -if (import.meta.client && useNuxtApp().isHydrating && useNuxtApp().payload.serverRendered) { - viewPlaylistDataShuffled = viewPlaylistData.value +const viewPlaylistData = useState('viewPlaylistData', () => shallowRef([])) +function viewPlaylistDataUpdate (newData: Playlist, newDataHint?: 'shuffled') { + if (newDataHint === 'shuffled') { viewPlaylistSortingColumn.value = null } + viewPlaylistData.value = newData } -const viewPlaylistCopySongNameState = ref<{ - [key: Song['$id']]: 'succeeded' | 'failed' | 'stale' -}>({}) +callOnce(() => viewPlaylistData.value = viewPlaylistDataShuffle(backendPlaylist.value)) +onMounted(() => viewPlaylistDataShuffled = viewPlaylistData.value) + +const viewPlaylistCopySongNameState = ref<{ [key: Song['$id']]: 'succeeded' | 'failed' | 'stale' }>({}) function viewPlaylistCopySongName (name: Song['name'], id: Song['$id']) { if (Object.keys(viewPlaylistCopySongNameState.value).includes(id)) { return } const clipboardWritePromise = navigator.clipboard.writeText(`点歌 ${name}`) @@ -478,7 +463,6 @@ function viewPlaylistCopySongName (name: Song['name'], id: Song['$id']) { ) } -// @ts-expect-error const viewPlaylistCountTotal = computed(() => backendPlaylist.value.length) const viewPlaylistCountDisplayed = computed(() => viewPlaylistData.value.length)