mirror of
https://codeberg.org/Hyperpipe/Hyperpipe
synced 2025-06-27 12:48:01 +02:00
Created AddToPlaylist Modal
This commit is contained in:
parent
0144f1ee4e
commit
d0245c273e
10 changed files with 565 additions and 457 deletions
708
package-lock.json
generated
708
package-lock.json
generated
File diff suppressed because it is too large
Load diff
12
package.json
12
package.json
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 />
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
{
|
||||
"date": "2023-06-20"
|
||||
"date": "2023-07-16"
|
||||
}
|
||||
|
|
141
src/components/AddToPlaylist.vue
Normal file
141
src/components/AddToPlaylist.vue
Normal 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>
|
|
@ -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';
|
||||
|
|
|
@ -60,17 +60,17 @@ async function Stream() {
|
|||
}
|
||||
});
|
||||
|
||||
window.offline = new shaka.offline.Storage(audioPlayer);
|
||||
window.offline.configure({
|
||||
offline: {
|
||||
progressCallback: (data, prog) => console.log(data, prog),
|
||||
trackSelectionCallback: tracks => [
|
||||
tracks
|
||||
.sort((a, b) => a.bandwidth - b.bandwidth)
|
||||
.find(i => i.type == 'variant'),
|
||||
],
|
||||
},
|
||||
});
|
||||
window.offline = new shaka.offline.Storage(audioPlayer);
|
||||
window.offline.configure({
|
||||
offline: {
|
||||
progressCallback: (data, prog) => console.log(data, prog),
|
||||
trackSelectionCallback: tracks => [
|
||||
tracks
|
||||
.sort((a, b) => a.bandwidth - b.bandwidth)
|
||||
.find(i => i.type == 'variant'),
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
audioPlayer.configure({
|
||||
preferredAudioCodecs: codecs ? codecs.split(':') : ['opus', 'mp4a'],
|
||||
|
|
|
@ -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,
|
||||
})),
|
||||
)
|
||||
" />
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue