Created AddToPlaylist Modal

This commit is contained in:
Shiny Nematoda 2023-07-16 10:48:52 +00:00
parent 0144f1ee4e
commit d0245c273e
10 changed files with 565 additions and 457 deletions

708
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -6,23 +6,23 @@
"host": "vite --host",
"build": "vite build",
"preview": "vite preview --port 5050",
"pretty": "prettier --write .",
"check": "prettier --check ."
"format": "prettier --write .",
"lint": "prettier --check ."
},
"dependencies": {
"bootstrap-icons": "^1.10.5",
"dompurify": "^3.0.3",
"dompurify": "^3.0.5",
"mux.js": "^6.3.0",
"peerjs": "^1.4.7",
"pinia": "^2.1.4",
"shaka-player": "^4.3.6",
"shaka-player": "^4.3.7",
"sortablejs": "^1.15.0",
"vue": "^3.2.38"
},
"devDependencies": {
"@vitejs/plugin-vue": "^4.2.3",
"prettier": "^2.8.8",
"vite": "^4.3.9",
"prettier": "^3.0.0",
"vite": "^4.4.4",
"vite-plugin-pwa": "^0.16.4"
}
}

View file

@ -17,6 +17,7 @@ import Search from '@/components/Search.vue';
import Playlists from '@/components/Playlists.vue';
import Lyrics from '@/components/Lyrics.vue';
import Info from '@/components/Info.vue';
import AddToPlaylist from '@/components/AddToPlaylist.vue';
import Artist from '@/components/Artist.vue';
/* Async Components */
@ -193,6 +194,8 @@ onMounted(() => {
</div>
</Transition>
<AddToPlaylist />
<StatusBar />
<Player />

View file

@ -1,3 +1,3 @@
{
"date": "2023-06-20"
"date": "2023-07-16"
}

View file

@ -0,0 +1,141 @@
<script setup>
import { ref, watch, onMounted, onActivated } from 'vue';
import Modal from './Modal.vue';
import { getAuthPlaylists, useAuthAddToPlaylist } from '@/scripts/fetch.js';
import { useListPlaylists, useUpdatePlaylist } from '@/scripts/db.js';
import { useStore } from '@/scripts/util.js';
import { useData, usePlayer } from '@/stores/player.js';
import { useI18n } from '@/stores/misc.js';
const { t } = useI18n(),
data = useData(),
player = usePlayer(),
store = useStore();
const pl = ref(''),
list = ref([]),
remote = ref([]),
plRemote = ref(false);
function Save() {
if (pl.value) {
if (plRemote.value == true && store.auth) {
useAuthAddToPlaylist(pl.value, data.state.url);
} else if (plRemote.value == false) {
useUpdatePlaylist(
pl.value,
{
url: data.state.url,
title: data.state.title,
},
e => {
if (e === true) console.log('Added Song');
},
);
}
}
}
function List() {
player.state.add = true;
useListPlaylists(res => {
list.value = res;
});
getAuthPlaylists().then(res => {
remote.value = res;
});
}
watch(
() => player.state.add,
e => e == true && List(),
);
</script>
<template>
<Teleport to="body">
<Transition name="fade">
<Modal
n="2"
:display="player.state.add"
:title="t('playlist.select')"
@show="
e => {
player.state.add = e;
}
">
<template #content>
<div
v-for="i in list"
:key="i.name"
class="flex item"
@click="
pl = i.name;
plRemote = false;
"
:data-active="pl == i.name && plRemote == false">
<span>{{ i.name }}</span
><span class="ml-auto">{{ i.urls.length || '' }}</span>
</div>
<div
v-for="i in remote"
:key="i.id"
class="flex item remote"
@click="
pl = i.id;
plRemote = true;
"
:data-active="pl == i.id && plRemote == true">
<span>{{ i.name.replace('Playlist -', '') }}</span
><span class="ml-auto">{{ i.videos }}</span>
</div>
</template>
<template #buttons>
<button aria-label="Cancel" @click="player.state.add = false">
{{ t('action.cancel') }}
</button>
<button
aria-label="Add Song"
@click="
Save();
player.state.add = false;
">
{{ t('action.add') }}
</button>
</template>
</Modal>
</Transition>
</Teleport>
</template>
<style scoped>
.ml-auto {
margin-left: auto;
width: min-content;
}
.item {
background: var(--color-background);
border-radius: 0.5rem;
margin: 0.5rem 0;
transition: background-color 0.1s ease;
}
.item:hover {
background: var(--color-background-mute);
}
.item:active {
background: var(--color-border);
}
.item[data-active='true'] {
color: var(--color-background);
background: linear-gradient(135deg, cornflowerblue, #88c0d0);
}
.remote.item::before {
content: '\F4E1';
font-family: bootstrap-icons;
font-size: 1.25rem;
}
</style>

View file

@ -95,7 +95,7 @@ const setProxy = async () => {
...i.appMetadata,
offlineUri: i.offlineUri,
thumbnail: parseThumb(i.appMetadata.url, proxy.value),
duration: i.duration
duration: i.duration,
})),
});
nav.state.page = 'home';

View file

@ -36,7 +36,7 @@ const shuffleAdd = () => {
thumbnails: [{ url: i.thumbnail }],
thumbnail: i.thumbnail,
offlineUri: i.offlineUri,
duration: i.duration
duration: i.duration,
})),
copy = [];
@ -61,7 +61,7 @@ const shuffleAdd = () => {
thumbnails: [{ url: i.thumbnail }],
thumbnail: i.thumbnail,
offlineUri: i.offlineUri,
duration: i.duration
duration: i.duration,
}));
song.url = song.url || '/watch?v=' + song.id;
@ -254,7 +254,7 @@ onDeactivated(() => {
thumbnails: [{ url: item.thumbnail }],
thumbnail: item.thumbnail,
offlineUri: item.offlineUri,
duration: item.duration
duration: item.duration,
})),
)
" />

View file

@ -1,10 +1,7 @@
<script setup>
import { ref, reactive } from 'vue';
import Modal from './Modal.vue';
import { useStore } from '@/scripts/util.js';
import { useListPlaylists, useUpdatePlaylist } from '@/scripts/db.js';
import {
getAuthPlaylists,
useAuthCreatePlaylist,
@ -21,13 +18,8 @@ const { t } = useI18n(),
const showme = reactive({
menu: false,
pl: false,
vol: false,
}),
pl = ref(''),
list = ref([]),
remote = ref([]),
plRemote = ref(false),
liked = ref(undefined),
liking = ref(false);
@ -45,36 +37,6 @@ function getFormattedTime(sec) {
).padStart(2, '0')}`;
}
function List() {
showme.pl = true;
useListPlaylists(res => {
list.value = res;
showme.menu = false;
});
getAuthPlaylists().then(res => {
remote.value = res;
});
}
function Save() {
if (pl.value) {
if (plRemote.value == true && store.auth) {
useAuthAddToPlaylist(pl.value, data.state.url);
} else if (plRemote.value == false) {
useUpdatePlaylist(
pl.value,
{
url: data.state.url,
title: data.state.title,
},
e => {
if (e === true) console.log('Added Song');
},
);
}
}
}
async function Offline() {
if (window.offline && data.state.url) {
window.offline.store(window.audioPlayer.getAssetUri(), {
@ -107,61 +69,6 @@ async function Like() {
}
</script>
<template>
<Teleport to="body">
<Transition name="fade">
<Modal
n="2"
:display="showme.pl"
:title="t('playlist.select')"
@show="
e => {
showme.pl = e;
}
">
<template #content>
<div
v-for="i in list"
:key="i.name"
class="flex item"
@click="
pl = i.name;
plRemote = false;
"
:data-active="pl == i.name && plRemote == false">
<span>{{ i.name }}</span
><span class="ml-auto">{{ i.urls.length || '' }}</span>
</div>
<div
v-for="i in remote"
:key="i.id"
class="flex item remote"
@click="
pl = i.id;
plRemote = true;
"
:data-active="pl == i.id && plRemote == true">
<span>{{ i.name.replace('Playlist -', '') }}</span
><span class="ml-auto">{{ i.videos }}</span>
</div>
</template>
<template #buttons>
<button aria-label="Cancel" @click="showme.pl = false">
{{ t('action.cancel') }}
</button>
<button
aria-label="Add Song"
@click="
Save();
showme.pl = false;
">
{{ t('action.add') }}
</button>
</template>
</Modal>
</Transition>
</Teleport>
<div id="statusbar" class="flex">
<div class="flex statusbar-progress-container">
<span>{{ getFormattedTime(player.state.realTime) }}</span>
@ -301,7 +208,10 @@ async function Like() {
title="Add Current Song to a Playlist"
aria-label="Add Current Song to a Playlist"
class="bi bi-collection clickable"
@click="List"></button>
@click="
player.toggle('add');
showme.menu = false;
"></button>
<button
id="btn-lyrics"
@ -479,31 +389,6 @@ input[type='range']::-moz-range-track {
}
/* Playlist addition */
.ml-auto {
margin-left: auto;
width: min-content;
}
.item {
background: var(--color-background);
border-radius: 0.5rem;
margin: 0.5rem 0;
transition: background-color 0.1s ease;
}
.item:hover {
background: var(--color-background-mute);
}
.item:active {
background: var(--color-border);
}
.item[data-active='true'] {
color: var(--color-background);
background: linear-gradient(135deg, cornflowerblue, #88c0d0);
}
.remote.item::before {
content: '\F4E1';
font-family: bootstrap-icons;
font-size: 1.25rem;
}
@media (max-width: 500px) {
.statusbar-progress-container {

View file

@ -42,7 +42,7 @@ export const useData = defineStore('data', () => {
async function play(song) {
if (song.offlineUri) {
state.art = song.thumbnail;
player.state.duration = song.duration
player.state.duration = song.duration;
for (let i of ['title', 'artist', 'artistUrl', 'url']) state[i] = song[i];
window.audioPlayer.load(song.offlineUri);
} else await getSong(song.url);
@ -150,6 +150,7 @@ export const usePlayer = defineStore('player', () => {
playlist: false,
lyrics: false,
info: false,
add: false,
vol: store.vol ? store.vol / 100 : 1,
});