Delete remote playlists

+ minor ui changes
This commit is contained in:
Shiny Nematoda 2023-04-16 09:59:47 +00:00 committed by vrifox
parent db0009d186
commit 7bf279438f
No known key found for this signature in database
GPG key ID: D40098E5B60B2197
9 changed files with 62 additions and 16 deletions

View file

@ -1,3 +1,3 @@
{ {
"date": "2023-03-27" "date": "2023-04-16"
} }

View file

@ -138,6 +138,7 @@ onMounted(get);
font-size: 1rem; font-size: 1rem;
font-weight: bold; font-weight: bold;
letter-spacing: 0.125rem; letter-spacing: 0.125rem;
line-break: anywhere;
background-color: var(--color-background-mute); background-color: var(--color-background-mute);
color: var(--btn-color); color: var(--btn-color);
transition: background-color 0.1s ease; transition: background-color 0.1s ease;
@ -153,4 +154,9 @@ onMounted(get);
text-align: center; text-align: center;
text-transform: capitalize; text-transform: capitalize;
} }
@media (max-width: 600px) {
.btn-grid {
grid-template-columns: repeat(3, 1fr);
}
}
</style> </style>

View file

@ -473,7 +473,7 @@ onMounted(async () => {
.grid { .grid {
display: grid; display: grid;
width: fit-content; width: fit-content;
gap: 2rem; gap: 1rem;
grid-auto-rows: 10rem; grid-auto-rows: 10rem;
margin: 0 auto; margin: 0 auto;
} }
@ -553,4 +553,9 @@ input[type='file']::file-selector-button {
display: block; display: block;
text-align: center; text-align: center;
} }
@media (min-width: 400px) {
.grid {
grid-template-columns: 1fr 1fr;
}
}
</style> </style>

View file

@ -5,8 +5,12 @@ import Btn from './Btn.vue';
import SongItem from './SongItem.vue'; import SongItem from './SongItem.vue';
import AlbumItem from './AlbumItem.vue'; import AlbumItem from './AlbumItem.vue';
import { getJsonPiped, getPipedQuery } from '@/scripts/fetch.js'; import {
import { useRoute, useWrap, useShare } from '@/scripts/util.js'; getJsonPiped,
getPipedQuery,
useAuthRemovePlaylist,
} from '@/scripts/fetch.js';
import { useVerifyAuth, useRoute, useWrap, useShare } from '@/scripts/util.js';
import { useCreatePlaylist, useRemovePlaylist } from '@/scripts/db.js'; import { useCreatePlaylist, useRemovePlaylist } from '@/scripts/db.js';
import { useResults, useArtist } from '@/stores/results.js'; import { useResults, useArtist } from '@/stores/results.js';
@ -103,6 +107,20 @@ const shuffleAdd = () => {
}); });
} }
}, },
removePlaylist = async id => {
if (!id && !prompt('Confirm?')) return;
if (useVerifyAuth(id)) {
const { message } = await useAuthRemovePlaylist(id);
if (message != 'ok') {
alert(message);
return;
}
} else useRemovePlaylist(id);
useRoute('/library');
nav.state.page = 'library';
},
getSearch = q => { getSearch = q => {
if (q) { if (q) {
const pq = useWrap(q); const pq = useWrap(q);
@ -252,12 +270,10 @@ onDeactivated(() => {
@click="shuffleAdd"></button> @click="shuffleAdd"></button>
<button <button
v-if="results.items?.songs?.title.startsWith('Local • ')" v-if="results.items?.songs?.items?.[0]?.playlistId"
class="bi bi-trash3 clickable" class="bi bi-trash3 clickable"
@click=" @click="
useRemovePlaylist( removePlaylist(results.items?.songs?.items?.[0]?.playlistId)
results.items?.songs?.title?.replace('Local • ', ''),
)
"></button> "></button>
</div> </div>
</Transition> </Transition>

View file

@ -107,9 +107,9 @@ onMounted(() => {
<span class="flex content"> <span class="flex content">
<h4>{{ title }}</h4> <h4>{{ title }}</h4>
<a <a
class="ign"
:href="channel" :href="channel"
@click.prevent="artist.getArtist(channel.replace('/channel/', ''))" @click.prevent="artist.getArtist(channel.replace('/channel/', ''))">
class="ign">
<i class="ign">{{ author ? author.replaceAll(' - Topic', '') : '' }}</i> <i class="ign">{{ author ? author.replaceAll(' - Topic', '') : '' }}</i>
</a> </a>
</span> </span>

View file

@ -308,7 +308,7 @@ async function Like() {
border-top: 0.25rem solid var(--color-foreground); border-top: 0.25rem solid var(--color-foreground);
background: var(--color-background); background: var(--color-background);
min-height: 15vh; min-height: 15vh;
z-index: 2; z-index: 999;
} }
.statusbar-progress-container, .statusbar-progress-container,

View file

@ -107,6 +107,22 @@ export async function useAuthAddToPlaylist(id, path) {
}); });
} }
export async function useAuthRemovePlaylist(id) {
const auth = useAuthToken();
if (auth && id) {
return getJsonAuth('/user/playlists/delete', {
method: 'POST',
headers: {
Authorization: auth,
},
body: JSON.stringify({
playlistId: id,
}),
});
}
}
export async function useAuthLogout() { export async function useAuthLogout() {
const auth = useAuthToken(), const auth = useAuthToken(),
ctrl = new AbortController(), ctrl = new AbortController(),

View file

@ -6,6 +6,12 @@ export function useSanitize(txt) {
}); });
} }
export function useVerifyAuth(hash) {
return /[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12}/.test(
hash,
);
}
export function useRoute(l) { export function useRoute(l) {
history.pushState({}, '', l); history.pushState({}, '', l);
} }

View file

@ -4,7 +4,7 @@ import { defineStore } from 'pinia';
import { useNav } from '@/stores/misc.js'; import { useNav } from '@/stores/misc.js';
import { getJsonPiped, getJsonHyp, getJsonAuth } from '@/scripts/fetch.js'; import { getJsonPiped, getJsonHyp, getJsonAuth } from '@/scripts/fetch.js';
import { useRoute } from '@/scripts/util.js'; import { useVerifyAuth, useRoute } from '@/scripts/util.js';
export const useResults = defineStore('results', () => { export const useResults = defineStore('results', () => {
const items = ref({}), const items = ref({}),
@ -39,10 +39,7 @@ export const useResults = defineStore('results', () => {
async function getAlbum(e) { async function getAlbum(e) {
const hash = new URLSearchParams(e.substring(e.indexOf('?'))).get('list'), const hash = new URLSearchParams(e.substring(e.indexOf('?'))).get('list'),
isAuth = isAuth = useVerifyAuth(hash),
/[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12}/.test(
hash,
),
path = '/playlists/' + hash, path = '/playlists/' + hash,
json = isAuth ? await getJsonAuth(path) : await getJsonPiped(path); json = isAuth ? await getJsonAuth(path) : await getJsonPiped(path);