-
-
- Создать
-
-
- Плейлистов пока нет.
-
- Плейлист удалён на сервере. Несохранённый черновик сохранён до отмены.
- Загрузить актуальный список
-
-
- Название плейлиста
-
-
- Сохранить название
-
- Добавить MP3
-
- Использовать в игре
-
- Удалить плейлист
- Удалить плейлист «{{ selected.name }}»?
-
-
- Порядок или состав треков изменился на сервере. Загрузите актуальный список перед
- сохранением.
-
- Сохранить порядок
- {{
- hasConflict ? 'Загрузить актуальный список' : 'Отменить изменения'
- }}
-
-
-
- Добавить группу
-
-
- Для изменения активной группы и порядка групп остановите музыку. Другие игры также могут
- блокировать редактирование.
-
-
-
-
- {{ section.name }}
- saveGroup(section.ID, groupName, endMode)"
- @remove="emit('deleteGroup', selectedId, section.ID)"
- @dirty="dirtyGroups[section.ID] = $event"
- @move="moveGroup(section.ID, $event)"
- />
- Треков пока нет.
-
- {{ index + 1 }}.
- {{
- selected.tracks?.find((track) => track.ID === id)?.name ??
- 'Трек удалён на сервере'
- }}
-
-
- ↑
- ↓
-
-
- Удалить
-
- Удалить трек из плейлиста?
-
-
-
-
-
-
-
+ ref="editor"
+ :playlists="playlists"
+ :music="music"
+ :is-busy="isBusy"
+ @set-music="(change) => emit('setMusic', change)"
+ @save-group="
+ (playlistID, groupID, name, endMode) =>
+ emit('saveGroup', playlistID, groupID, name, endMode)
+ "
+ @delete-group="(playlistID, groupID) => emit('deleteGroup', playlistID, groupID)"
+ @reorder-groups="(playlistID, groupIDs) => emit('reorderGroups', playlistID, groupIDs)"
+ @set-track-group="
+ (playlistID, trackID, groupID) => emit('setTrackGroup', playlistID, trackID, groupID)
+ "
+ @create-playlist="(name) => emit('createPlaylist', name)"
+ @rename-playlist="(id, name) => emit('renamePlaylist', id, name)"
+ @reorder-tracks="(playlistID, trackIDs) => emit('reorderTracks', playlistID, trackIDs)"
+ @delete-playlist="(id) => emit('deletePlaylist', id)"
+ @upload-track="(playlistID, file) => emit('uploadTrack', playlistID, file)"
+ @delete-track="(playlistID, trackID) => emit('deleteTrack', playlistID, trackID)"
+ />
()
const isMusicBusy = ref(false)
let musicRequestVersion = 0
let musicSyncedAt = Date.now()
+const {
+ saveGroup,
+ deleteGroup,
+ reorderGroups,
+ setTrackGroup,
+ createPlaylist,
+ renamePlaylist,
+ reorderTracks,
+ deletePlaylist,
+ uploadTrack,
+ deleteTrack,
+} = usePlaylistActions(
+ isMusicBusy,
+ () => getGameMusic(true),
+ () => {
+ musicRequestVersion += 1
+ },
+)
const isScreenBusy = ref(false)
const isScreensLoading = ref(true)
const screensError = ref('')
@@ -704,161 +722,6 @@ async function setGameMusic(change: {
}
}
-async function saveGroup(
- playlistID: number,
- groupID: number,
- name: string,
- endMode: PlaylistGroup['endMode'],
-) {
- if (isMusicBusy.value) return
- isMusicBusy.value = true
- musicRequestVersion += 1
- try {
- await client.SavePlaylistGroup({ playlistID, groupID, name, endMode })
- await getGameMusic(true)
- } catch (err) {
- message.error(err instanceof Error ? err.message : 'Не удалось изменить группы музыки')
- } finally {
- isMusicBusy.value = false
- }
-}
-
-async function deleteGroup(playlistID: number, groupID: number) {
- if (isMusicBusy.value) return
- isMusicBusy.value = true
- musicRequestVersion += 1
- try {
- await client.DeletePlaylistGroup({ playlistID, groupID })
- await getGameMusic(true)
- } catch (err) {
- message.error(err instanceof Error ? err.message : 'Не удалось изменить группы музыки')
- } finally {
- isMusicBusy.value = false
- }
-}
-
-async function reorderGroups(playlistID: number, groupIDs: number[]) {
- if (isMusicBusy.value) return
- isMusicBusy.value = true
- musicRequestVersion += 1
- try {
- await client.ReorderPlaylistGroups({ playlistID, groupIDs })
- await getGameMusic(true)
- } catch (err) {
- message.error(err instanceof Error ? err.message : 'Не удалось изменить группы музыки')
- } finally {
- isMusicBusy.value = false
- }
-}
-
-async function setTrackGroup(playlistID: number, trackID: number, groupID: number) {
- if (isMusicBusy.value) return
- isMusicBusy.value = true
- musicRequestVersion += 1
- try {
- await client.SetPlaylistTrackGroup({ playlistID, trackID, groupID })
- await getGameMusic(true)
- } catch (err) {
- message.error(err instanceof Error ? err.message : 'Не удалось изменить группы музыки')
- } finally {
- isMusicBusy.value = false
- }
-}
-
-async function createPlaylist(name: string) {
- if (isMusicBusy.value || !name.trim()) return
- isMusicBusy.value = true
- musicRequestVersion += 1
- try {
- await client.CreatePlaylist({ name: name.trim() })
- await getGameMusic(true)
- } catch (err) {
- message.error(err instanceof Error ? err.message : 'Не удалось создать плейлист')
- } finally {
- isMusicBusy.value = false
- }
-}
-
-async function renamePlaylist(id: number, name: string) {
- if (isMusicBusy.value || !name.trim()) return
- isMusicBusy.value = true
- musicRequestVersion += 1
- try {
- await client.UpdatePlaylist({ ID: id, name: name.trim() })
- await getGameMusic(true)
- } catch (err) {
- message.error(err instanceof Error ? err.message : 'Не удалось переименовать плейлист')
- } finally {
- isMusicBusy.value = false
- }
-}
-
-async function reorderTracks(playlistID: number, trackIDs: number[]) {
- if (isMusicBusy.value) return
- isMusicBusy.value = true
- musicRequestVersion += 1
- try {
- await client.ReorderPlaylistTracks({ playlistID, trackIDs })
- await getGameMusic(true)
- } catch (err) {
- message.error(err instanceof Error ? err.message : 'Не удалось сохранить порядок треков')
- } finally {
- isMusicBusy.value = false
- }
-}
-
-async function deletePlaylist(id: number) {
- if (isMusicBusy.value) return
- isMusicBusy.value = true
- musicRequestVersion += 1
- try {
- await client.DeletePlaylist({ ID: id })
- await getGameMusic(true)
- } catch (err) {
- message.error(err instanceof Error ? err.message : 'Не удалось удалить плейлист')
- } finally {
- isMusicBusy.value = false
- }
-}
-
-async function uploadTrack(playlistID: number, file: File) {
- if (isMusicBusy.value) return
- if (!/\.mp3$/i.test(file.name) || file.size === 0 || file.size > 64 * 1024 * 1024) {
- message.error('Выберите непустой MP3 размером до 64 МиБ')
- return
- }
- isMusicBusy.value = true
- musicRequestVersion += 1
- try {
- const data = uint8ToBase64(new Uint8Array(await file.arrayBuffer()))
- await client.UploadPlaylistTrack({ playlistID, name: file.name, filename: file.name, data })
- await getGameMusic(true)
- } catch (err) {
- message.error(err instanceof Error ? err.message : 'Не удалось загрузить MP3')
- } finally {
- isMusicBusy.value = false
- }
-}
-
-async function deleteTrack(playlistID: number, id: number) {
- if (isMusicBusy.value) return
- isMusicBusy.value = true
- musicRequestVersion += 1
- try {
- await client.DeletePlaylistTrack({ playlistID, trackID: id })
- await getGameMusic(true)
- } catch (err) {
- message.error(err instanceof Error ? err.message : 'Не удалось удалить трек')
- } finally {
- isMusicBusy.value = false
- }
-}
-function uint8ToBase64(data: Uint8Array): string {
- let binary = ''
- for (let i = 0; i < data.length; i += 0x8000) binary += String.fromCharCode(...data.subarray(i, i + 0x8000))
- return btoa(binary)
-}
-
async function unbindScreen(screen: ScreenState) {
if (isScreenBusy.value) return
isScreenBusy.value = true
diff --git a/src/components/HeaderMenu.vue b/src/components/HeaderMenu.vue
index 6bd0caf..92d00b1 100644
--- a/src/components/HeaderMenu.vue
+++ b/src/components/HeaderMenu.vue
@@ -104,6 +104,15 @@ const openMenu = ref(false)
>
Экран
+