mirror of
https://github.com/janishutz/MusicPlayer.git
synced 2026-09-10 14:25:24 +02:00
feat: playlist loading
This commit is contained in:
@@ -1,11 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import AssociationView from '@/composables/AssociationView.vue';
|
||||
import PlayerComponent from './PlayerComponent.vue';
|
||||
import SmallPlayerComponent from './SmallPlayerComponent.vue';
|
||||
import {
|
||||
ref
|
||||
} from 'vue';
|
||||
|
||||
const fullPlayer = ref( true );
|
||||
fullPlayer
|
||||
} from '@/ts/player/state';
|
||||
|
||||
const close = () => {
|
||||
fullPlayer.value = false;
|
||||
@@ -14,6 +13,7 @@
|
||||
|
||||
<template>
|
||||
<div class="player-wrapper">
|
||||
<AssociationView />
|
||||
<SmallPlayerComponent v-model="fullPlayer" />
|
||||
<div :class="['player-container', fullPlayer ? undefined : 'hidden']">
|
||||
<i class="fa-solid fa-xmark" @click="close"></i>
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import UserPlaylists from '../playlists/UserPlaylists.vue';
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<h1>Playlists</h1>
|
||||
<UserPlaylists />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
import {
|
||||
queueIdx
|
||||
} from '@/ts/player/state';
|
||||
import {
|
||||
savePlaylist
|
||||
} from '@/ts/userPlaylists/save';
|
||||
|
||||
const queue: WritableComputedRef<Song[]> = computed( {
|
||||
get () {
|
||||
@@ -56,7 +59,7 @@
|
||||
<i class="fa-solid fa-xmark"></i>
|
||||
Clear
|
||||
</button>
|
||||
<button>
|
||||
<button @click="savePlaylist">
|
||||
<i class="fa-solid fa-save"></i>
|
||||
Save
|
||||
</button>
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
<script setup lang="ts">
|
||||
import PopupElement from '../popups/PopupElement.vue';
|
||||
import {
|
||||
ref
|
||||
} from 'vue';
|
||||
|
||||
const showPopup = defineModel<boolean>( {
|
||||
'required': true
|
||||
} );
|
||||
|
||||
const addPlaylist = () => {
|
||||
showPopup.value = false;
|
||||
emit( 'add-playlist', playlistName.value );
|
||||
};
|
||||
|
||||
const playlistName = ref( '' );
|
||||
const emit = defineEmits<{
|
||||
( e: 'add-playlist', name: string ): void;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<PopupElement v-model="showPopup" show-close>
|
||||
<div class="title">
|
||||
<h1>Add Playlist</h1>
|
||||
</div>
|
||||
<input v-model="playlistName" type="text" placeholder="Playlist name">
|
||||
<br>
|
||||
<button @click="addPlaylist">
|
||||
<i class="fa-solid fa-plus"></i>
|
||||
Add Playlist
|
||||
</button>
|
||||
</PopupElement>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.title {
|
||||
>h1 {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
>p {
|
||||
margin: 0;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
.song-sources {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
width: 50vw;
|
||||
height: 40vh;
|
||||
justify-content: center;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
|
||||
>div {
|
||||
width: 45%;
|
||||
margin: 0.5%;
|
||||
height: 60%;
|
||||
background-color: var(--accent-background);
|
||||
border-radius: 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
flex-direction: column;
|
||||
|
||||
>div {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
>.fa-solid {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
>.not-auth-notice {
|
||||
font-size: 0.6rem;
|
||||
margin: 0;
|
||||
width: 70%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,112 @@
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
addPlaylist,
|
||||
removePlaylist
|
||||
} from '@/ts/userPlaylists';
|
||||
import {
|
||||
editingPlaylists,
|
||||
playlistIdx as playlistIdx,
|
||||
playlists
|
||||
} from '@/ts/userPlaylists/state';
|
||||
import {
|
||||
getPlaylists,
|
||||
savePlaylists
|
||||
} from '@/ts/userPlaylists/save';
|
||||
import {
|
||||
onMounted,
|
||||
ref
|
||||
} from 'vue';
|
||||
import AddPlaylist from './AddPlaylist.vue';
|
||||
import {
|
||||
UnownedError
|
||||
} from '@/ts/request';
|
||||
import player from '@/ts/player';
|
||||
import router from '@/router';
|
||||
|
||||
const checkingStatus = ref( true );
|
||||
const dots = ref( 0 );
|
||||
const showAddPlaylist = ref( false );
|
||||
|
||||
let interval = -1;
|
||||
|
||||
const loadPlaylists = async () => {
|
||||
if ( interval < 0 ) {
|
||||
interval = setInterval( () => {
|
||||
dots.value = ( dots.value + 1 ) % 4;
|
||||
}, 500 );
|
||||
}
|
||||
|
||||
try {
|
||||
await getPlaylists();
|
||||
} catch ( e ) {
|
||||
if ( e instanceof UnownedError ) {
|
||||
router.push( '/get' );
|
||||
}
|
||||
}
|
||||
|
||||
checkingStatus.value = false;
|
||||
|
||||
try {
|
||||
clearInterval( interval );
|
||||
interval = -1;
|
||||
} catch { /* Empty */ }
|
||||
};
|
||||
|
||||
onMounted( () => {
|
||||
loadPlaylists();
|
||||
} );
|
||||
|
||||
onMounted( () => {} );
|
||||
|
||||
const openAddPlaylistPopup = () => {
|
||||
showAddPlaylist.value = true;
|
||||
};
|
||||
|
||||
const togglePlaylistEditing = ( idx: number ) => {
|
||||
editingPlaylists.value[ idx ] = !editingPlaylists.value[ idx ];
|
||||
};
|
||||
|
||||
const selectPlaylist = ( idx: number ) => {
|
||||
playlistIdx.value = idx;
|
||||
player.clearQueue();
|
||||
player.loadPlaylist( playlists.value[ idx ]!.songs );
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="playlists">
|
||||
<AddPlaylist v-model="showAddPlaylist" @add-playlist="addPlaylist" />
|
||||
<div v-if="checkingStatus">
|
||||
Loading{{ '.'.repeat( dots ) }}
|
||||
</div>
|
||||
<div v-else-if="playlists.length === 0">
|
||||
No playlists
|
||||
<button @click="openAddPlaylistPopup">
|
||||
<i class="fa-solid fa-plus"></i>
|
||||
Add one
|
||||
</button>
|
||||
</div>
|
||||
<div v-else>
|
||||
<button @click="openAddPlaylistPopup">
|
||||
<i class="fa-solid fa-plus"></i>
|
||||
Add Playlist
|
||||
</button>
|
||||
<button @click="savePlaylists">
|
||||
<i class="fa-solid fa-floppy-disk"></i>
|
||||
Save Changes
|
||||
</button>
|
||||
<button @click="loadPlaylists">
|
||||
<i class="fa-solid fa-rotate"></i>
|
||||
Undo unsaved changes
|
||||
</button>
|
||||
<div v-for="(playlist, index) in playlists" :key="index">
|
||||
<input v-if="editingPlaylists[ index ]" v-model="playlist.name" type="text">
|
||||
<h2 v-else @click="() => selectPlaylist( index )">
|
||||
{{ playlist.name }}
|
||||
</h2>
|
||||
<i class="fa-solid fa-pen-to-square" @click="() => togglePlaylistEditing( index )"></i>
|
||||
<i class="fa-solid fa-trash" @click="() => removePlaylist( index )"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user