mirror of
https://codeberg.org/Hyperpipe/Hyperpipe
synced 2025-06-27 20:58:01 +02:00
Search Improvements
This commit is contained in:
parent
51c56abe16
commit
19fc65e6c0
19 changed files with 545 additions and 404 deletions
|
@ -3,7 +3,7 @@ defineProps({
|
|||
name: String,
|
||||
author: {
|
||||
type: String,
|
||||
default: ''
|
||||
default: '',
|
||||
},
|
||||
grad: String,
|
||||
art: {
|
||||
|
@ -39,7 +39,7 @@ defineEmits(['open-album']);
|
|||
}
|
||||
.card-bg {
|
||||
--art: v-bind('grad || art');
|
||||
background: v-bind('grad');
|
||||
background-color: v-bind('grad');
|
||||
height: 13rem;
|
||||
width: 13rem;
|
||||
}
|
||||
|
|
|
@ -1,104 +1,107 @@
|
|||
<script setup>
|
||||
import { ref, watch } from 'vue'
|
||||
import { ref, watch } from 'vue';
|
||||
|
||||
const props = defineProps(['display', 'title', 'n']),
|
||||
emit = defineEmits(['show']),
|
||||
show = ref(props.display);
|
||||
const props = defineProps(['display', 'title', 'n']),
|
||||
emit = defineEmits(['show']),
|
||||
show = ref(props.display);
|
||||
|
||||
watch(() => props.display, (n) => {
|
||||
console.log(n, props.display)
|
||||
show.value = n
|
||||
})
|
||||
watch(show, (n) => {
|
||||
emit('show', show.value)
|
||||
})
|
||||
watch(
|
||||
() => props.display,
|
||||
(n) => {
|
||||
console.log(n, props.display);
|
||||
show.value = n;
|
||||
},
|
||||
);
|
||||
watch(show, (n) => {
|
||||
emit('show', show.value);
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<Transition name="fade">
|
||||
<div class="modal" v-if="show">
|
||||
<span class="bi bi-x modal-close" @click="show = false"></span>
|
||||
<div class="modal-box">
|
||||
<div class="modal-title">{{ title }}</div>
|
||||
<div class="modal-content">
|
||||
<slot name="content"></slot>
|
||||
</div>
|
||||
<div class="modal-buttons">
|
||||
<slot name="buttons"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
<Transition name="fade">
|
||||
<div class="modal" v-if="show">
|
||||
<span class="bi bi-x modal-close" @click="show = false"></span>
|
||||
<div class="modal-box">
|
||||
<div class="modal-title">{{ title }}</div>
|
||||
<div class="modal-content">
|
||||
<slot name="content"></slot>
|
||||
</div>
|
||||
<div class="modal-buttons">
|
||||
<slot name="buttons"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.modal {
|
||||
display: flex;
|
||||
position: fixed;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #00000066;
|
||||
z-index: 9999;
|
||||
}
|
||||
.modal-box {
|
||||
width: 50vw;
|
||||
border-radius: .5rem;
|
||||
background-color: var(--color-background-soft);
|
||||
}
|
||||
.modal-title {
|
||||
font-size: 1.25rem;
|
||||
padding: 1rem 2rem;
|
||||
border-bottom: 1px solid var(--color-shadow);
|
||||
}
|
||||
.modal-content {
|
||||
padding: 1rem;
|
||||
}
|
||||
.modal-content * {
|
||||
width: 100%;
|
||||
padding: 1rem;
|
||||
}
|
||||
.modal-close {
|
||||
color: var(--color-background);
|
||||
font-size: 2rem;
|
||||
position: fixed;
|
||||
top: 1rem;
|
||||
right: 1rem;
|
||||
}
|
||||
.modal-buttons {
|
||||
width: 100%;
|
||||
border-top: 1px solid var(--color-shadow);
|
||||
}
|
||||
.modal-buttons button {
|
||||
padding: 1rem 2rem;
|
||||
color: var(--color-foreground);
|
||||
width: calc(100% / v-bind('n'));
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
border-right: 1px solid var(--color-shadow);
|
||||
}
|
||||
.modal-buttons button:first-child {
|
||||
color: indianred;
|
||||
border-bottom-left-radius: .5rem;
|
||||
}
|
||||
.modal-buttons button:last-child {
|
||||
border: none;
|
||||
border-bottom-right-radius: .5rem;
|
||||
}
|
||||
.modal-buttons button:hover {
|
||||
background-color: var(--color-background-mute);
|
||||
}
|
||||
.modal {
|
||||
display: flex;
|
||||
position: fixed;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #00000066;
|
||||
z-index: 9999;
|
||||
}
|
||||
.modal-box {
|
||||
width: 50vw;
|
||||
border-radius: 0.5rem;
|
||||
background-color: var(--color-background-soft);
|
||||
}
|
||||
.modal-title {
|
||||
font-size: 1.25rem;
|
||||
padding: 1rem 2rem;
|
||||
border-bottom: 1px solid var(--color-shadow);
|
||||
}
|
||||
.modal-content {
|
||||
padding: 1rem;
|
||||
}
|
||||
.modal-content * {
|
||||
width: 100%;
|
||||
padding: 1rem;
|
||||
}
|
||||
.modal-close {
|
||||
color: var(--color-background);
|
||||
font-size: 2rem;
|
||||
position: fixed;
|
||||
top: 1rem;
|
||||
right: 1rem;
|
||||
}
|
||||
.modal-buttons {
|
||||
width: 100%;
|
||||
border-top: 1px solid var(--color-shadow);
|
||||
}
|
||||
.modal-buttons button {
|
||||
padding: 1rem 2rem;
|
||||
color: var(--color-foreground);
|
||||
width: calc(100% / v-bind('n'));
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
border-right: 1px solid var(--color-shadow);
|
||||
}
|
||||
.modal-buttons button:first-child {
|
||||
color: indianred;
|
||||
border-bottom-left-radius: 0.5rem;
|
||||
}
|
||||
.modal-buttons button:last-child {
|
||||
border: none;
|
||||
border-bottom-right-radius: 0.5rem;
|
||||
}
|
||||
.modal-buttons button:hover {
|
||||
background-color: var(--color-background-mute);
|
||||
}
|
||||
|
||||
@media (max-width: 530px) {
|
||||
.modal-box {
|
||||
width: 80vw;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.modal-box {
|
||||
width: 40vw;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@media (max-width: 530px) {
|
||||
.modal-box {
|
||||
width: 80vw;
|
||||
}
|
||||
}
|
||||
@media (min-width: 1024px) {
|
||||
.modal-box {
|
||||
width: 40vw;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
<script setup>
|
||||
import { reactive } from 'vue'
|
||||
import { reactive } from 'vue';
|
||||
import SearchBar from '../components/SearchBar.vue';
|
||||
|
||||
const emit = defineEmits(['update-page', 'update-search']);
|
||||
const emit = defineEmits(['update-page', 'update-search']),
|
||||
|
||||
const page = reactive({
|
||||
page = reactive({
|
||||
home: true,
|
||||
playlist: false
|
||||
})
|
||||
playlist: false,
|
||||
}),
|
||||
|
||||
function Toggle(p) {
|
||||
Toggle = (p) => {
|
||||
for (let pg in page) {
|
||||
page[pg] = false
|
||||
page[pg] = false;
|
||||
}
|
||||
page[p] = true
|
||||
page[p] = true;
|
||||
emit('update-page', p);
|
||||
}
|
||||
function home() {
|
||||
history.pushState('', {}, '/')
|
||||
}
|
||||
},
|
||||
|
||||
home = () => {
|
||||
history.pushState('', {}, '/');
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -27,8 +27,12 @@ function home() {
|
|||
<h1 class="bi bi-vinyl" @click="home"></h1>
|
||||
|
||||
<div class="wrap">
|
||||
<span :class="'nav-ico bi bi-house ' + page.home" @click="Toggle('home')"></span>
|
||||
<span :class="'nav-ico bi bi-collection ' + page.playlist" @click="Toggle('playlist')"></span>
|
||||
<span
|
||||
:class="'nav-ico bi bi-house ' + page.home"
|
||||
@click="Toggle('home')"></span>
|
||||
<span
|
||||
:class="'nav-ico bi bi-collection ' + page.playlist"
|
||||
@click="Toggle('playlist')"></span>
|
||||
</div>
|
||||
|
||||
<div class="wrap">
|
||||
|
@ -53,14 +57,13 @@ h1.bi {
|
|||
font-size: calc(1.75rem + 1.5vw);
|
||||
}
|
||||
.bi {
|
||||
font-size: calc(1rem + 1vw);
|
||||
font-size: calc(1rem + 1.5vw);
|
||||
}
|
||||
.wrap {
|
||||
text-align: center;
|
||||
margin-left: auto;
|
||||
margin-right: .5rem;
|
||||
}
|
||||
.nav-ico {
|
||||
margin: 0 .5rem;
|
||||
margin: 0 0.5rem;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,90 +1,111 @@
|
|||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import AlbumItem from './AlbumItem.vue'
|
||||
import Modal from './Modal.vue'
|
||||
import { ref, onMounted } from 'vue';
|
||||
import AlbumItem from './AlbumItem.vue';
|
||||
import Modal from './Modal.vue';
|
||||
|
||||
import { useRand } from '../scripts/colors.js'
|
||||
import { useListPlaylists, useGetPlaylist, useCreatePlaylist } from '../scripts/db.js'
|
||||
import { useRand } from '../scripts/colors.js';
|
||||
|
||||
const emit = defineEmits(['play-urls'])
|
||||
import {
|
||||
useListPlaylists,
|
||||
useGetPlaylist,
|
||||
useCreatePlaylist,
|
||||
} from '../scripts/db.js';
|
||||
|
||||
const list = ref([]),
|
||||
show = ref(false),
|
||||
text = ref('');
|
||||
const emit = defineEmits(['play-urls']),
|
||||
|
||||
function Play(key) {
|
||||
console.log(key);
|
||||
list = ref([]),
|
||||
show = ref(false),
|
||||
text = ref(''),
|
||||
|
||||
useGetPlaylist(key, res => {
|
||||
console.log(res);
|
||||
emit('play-urls', res.urls)
|
||||
})
|
||||
}
|
||||
function List() {
|
||||
useListPlaylists((res) => {
|
||||
list.value = res
|
||||
})
|
||||
}
|
||||
function Create() {
|
||||
if (text.value) {
|
||||
useCreatePlaylist(text.value, [], () => {
|
||||
List()
|
||||
show.value = false
|
||||
})
|
||||
}
|
||||
}
|
||||
Play = (key) => {
|
||||
console.log(key);
|
||||
|
||||
onMounted(() => {
|
||||
List()
|
||||
})
|
||||
useGetPlaylist(key, (res) => {
|
||||
console.log(res);
|
||||
emit('play-urls', res.urls);
|
||||
});
|
||||
},
|
||||
|
||||
List = () => {
|
||||
useListPlaylists((res) => {
|
||||
list.value = res;
|
||||
});
|
||||
},
|
||||
|
||||
Create = () => {
|
||||
if (text.value) {
|
||||
useCreatePlaylist(text.value, [], () => {
|
||||
List();
|
||||
show.value = false;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
List();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="npl-wrap">
|
||||
|
||||
<Modal n="2" :display="show" title="Create a new Playlist..." @show="(e) => { show = e }" >
|
||||
<template #content>
|
||||
<input type="text" placeholder="Playlist name..." class="textbox" v-model="text" />
|
||||
</template>
|
||||
<template #buttons>
|
||||
<button @click="show = false">Cancel</button>
|
||||
<button @click="Create">Create</button>
|
||||
</template>
|
||||
</Modal>
|
||||
<div class="npl-wrap">
|
||||
<Modal
|
||||
n="2"
|
||||
:display="show"
|
||||
title="Create a new Playlist..."
|
||||
@show="
|
||||
(e) => {
|
||||
show = e;
|
||||
}
|
||||
">
|
||||
<template #content>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Playlist name..."
|
||||
class="textbox"
|
||||
v-model="text" />
|
||||
</template>
|
||||
<template #buttons>
|
||||
<button @click="show = false">Cancel</button>
|
||||
<button @click="Create">Create</button>
|
||||
</template>
|
||||
</Modal>
|
||||
|
||||
<div class="npl-box bi bi-plus-lg pop" @click="show = true"></div>
|
||||
<div class="grid-3">
|
||||
<template v-for="i in list">
|
||||
<AlbumItem :name="i.name" :grad="useRand()" @open-album="Play(i.name)" />
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="npl-box bi bi-plus-lg pop" @click="show = true"></div>
|
||||
<div class="grid-3">
|
||||
<template v-for="i in list">
|
||||
<AlbumItem
|
||||
:name="i.name"
|
||||
:grad="useRand()"
|
||||
@open-album="Play(i.name)" />
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.npl-wrap {
|
||||
padding-bottom: 5rem;
|
||||
}
|
||||
.npl-box {
|
||||
margin: 0 auto 5rem auto;
|
||||
border-radius: .5rem;
|
||||
background-color: var(--color-background-mute);
|
||||
padding: 2rem 3rem;
|
||||
font-size: 4rem;
|
||||
width: 10rem;
|
||||
}
|
||||
.npl-box:hover {
|
||||
background-color: var(--color-background-soft);
|
||||
}
|
||||
.npl-round {
|
||||
float: left;
|
||||
display: inline-block;
|
||||
height: 5rem;
|
||||
width: 5rem;
|
||||
border-radius: 50%;
|
||||
background: v-bind('bg');
|
||||
}
|
||||
.text-box {
|
||||
padding: 2rem;
|
||||
}
|
||||
</style>
|
||||
.npl-wrap {
|
||||
padding-bottom: 5rem;
|
||||
}
|
||||
.npl-box {
|
||||
margin: 0 auto 5rem auto;
|
||||
border-radius: 0.5rem;
|
||||
background-color: var(--color-background-mute);
|
||||
padding: 2rem 3rem;
|
||||
font-size: 4rem;
|
||||
width: 10rem;
|
||||
}
|
||||
.npl-box:hover {
|
||||
background-color: var(--color-background-soft);
|
||||
}
|
||||
.npl-round {
|
||||
float: left;
|
||||
display: inline-block;
|
||||
height: 5rem;
|
||||
width: 5rem;
|
||||
border-radius: 50%;
|
||||
background: v-bind('bg');
|
||||
}
|
||||
.text-box {
|
||||
padding: 2rem;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -8,13 +8,18 @@ defineProps({
|
|||
type: String,
|
||||
default: '',
|
||||
},
|
||||
artistUrl: {
|
||||
type: String,
|
||||
default: '',
|
||||
}
|
||||
});
|
||||
defineEmits(['get-artist'])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="title && artist" class="wrap">
|
||||
<h1>{{ title }}</h1>
|
||||
<h3>{{ artist }}</h3>
|
||||
<h3><a :href="artistUrl" @click.prevent="$emit('get-artist', artistUrl)">{{ artist }}</a></h3>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script setup>
|
||||
import { reactive, watch } from 'vue';
|
||||
import { ref, reactive, watch } from 'vue';
|
||||
import PlayBtn from './PlayBtn.vue';
|
||||
import SongItem from './SongItem.vue';
|
||||
import AlbumItem from './AlbumItem.vue';
|
||||
|
@ -7,39 +7,49 @@ import AlbumItem from './AlbumItem.vue';
|
|||
import { getJsonPiped, getPipedQuery } from '../scripts/fetch.js';
|
||||
import { useLazyLoad } from '../scripts/util.js';
|
||||
|
||||
const props = defineProps(['search', 'songItems', 'items']);
|
||||
const props = defineProps(['search', 'songItems', 'items']),
|
||||
|
||||
const emit = defineEmits(['get-album', 'get-artist', 'play-urls', 'add-song']);
|
||||
emit = defineEmits(['get-album', 'get-artist', 'play-urls', 'add-song']),
|
||||
|
||||
const data = reactive({
|
||||
filters = ['music_songs', 'music_albums', 'music_artists'],
|
||||
|
||||
filter = ref('music_songs'),
|
||||
|
||||
isSearch = ref(/search/.test(location.pathname)),
|
||||
|
||||
data = reactive({
|
||||
notes: null,
|
||||
albums: null,
|
||||
albumTitle: null,
|
||||
songs: null,
|
||||
artists: null,
|
||||
recommendedArtists: null,
|
||||
});
|
||||
}),
|
||||
|
||||
Reset = () => {
|
||||
isSearch.value = /search/.test(location.pathname);
|
||||
|
||||
function Reset() {
|
||||
for (let i in data) {
|
||||
data[i] = null;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
function playAlbum() {
|
||||
playAlbum = () => {
|
||||
const urls = data.songs.items.map((item) => {
|
||||
return { url: item.url, title: item.title };
|
||||
});
|
||||
|
||||
emit('play-urls', urls);
|
||||
}
|
||||
},
|
||||
|
||||
function getSearch(q) {
|
||||
getSearch = (q) => {
|
||||
if (q) {
|
||||
const pq = q.split(' ').join('+');
|
||||
|
||||
history.pushState({}, '', `/search/${pq + getPipedQuery()}`);
|
||||
|
||||
document.title = 'Search Results for ' + q;
|
||||
isSearch.value = /search/.test(location.pathname);
|
||||
|
||||
getResults(pq);
|
||||
useLazyLoad();
|
||||
|
@ -51,18 +61,17 @@ function getSearch(q) {
|
|||
|
||||
console.log('No Search');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
async function getResults(q) {
|
||||
const filters = ['music_songs', 'music_albums'];
|
||||
getResults = async (q) => {
|
||||
|
||||
for (let filter of filters) {
|
||||
const json = await getJsonPiped(`/search?q=${q}&filter=${filter}`);
|
||||
const f = filter.value || 'music_songs',
|
||||
|
||||
json = await getJsonPiped(`/search?q=${q}&filter=${f}`);
|
||||
|
||||
data[filter.split('_')[1]] = json;
|
||||
console.log(json, data);
|
||||
}
|
||||
}
|
||||
data[f.split('_')[1]] = json;
|
||||
console.log(json, data);
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.search,
|
||||
|
@ -115,6 +124,12 @@ watch(
|
|||
<span>{{ data.albumTitle }}</span>
|
||||
</div>
|
||||
|
||||
<div v-if="isSearch" class="filters">
|
||||
<button v-for="f in filters" class="filter caps" @click="filter = f; Reset(); getSearch(search)" :data-active="f == filter">
|
||||
{{ f.split('_')[1] }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="data.songs && data.songs.items[0]" class="search-songs">
|
||||
<h2>Songs</h2>
|
||||
<div class="grid">
|
||||
|
@ -129,7 +144,7 @@ watch(
|
|||
$emit('play-urls', [
|
||||
{
|
||||
url: song.url || '/watch?v=' + song.id,
|
||||
title: (song.title || song.name),
|
||||
title: song.title || song.name,
|
||||
},
|
||||
])
|
||||
"
|
||||
|
@ -178,16 +193,16 @@ watch(
|
|||
</div>
|
||||
|
||||
<div
|
||||
v-if="data.recommendedArtists && data.recommendedArtists.items[0]"
|
||||
v-if="( data.recommendedArtists && data.recommendedArtists.items[0] ) || ( data.artists && data.artists.items[0] )"
|
||||
class="search-artists">
|
||||
<h2>Similar Artists</h2>
|
||||
<h2>{{ data.artists ? 'Artists' : 'Similar Artists' }}</h2>
|
||||
<div class="grid-3 circle">
|
||||
<template v-for="artist in data.recommendedArtists.items">
|
||||
<template v-for="artist in ( data.artists ? data.artists.items : data.recommendedArtists.items)">
|
||||
<AlbumItem
|
||||
:author="artist.subtitle"
|
||||
:name="artist.title"
|
||||
:art="'url(' + artist.thumbnails[0].url + ')'"
|
||||
@open-album="$emit('get-artist', artist.id)" />
|
||||
:name="artist.name || artist.title"
|
||||
:art="'url(' + (artist.thumbnail || artist.thumbnails[0].url) + ')'"
|
||||
@open-album="$emit('get-artist', (artist.id || artist.url.replace('/channel/', '') ) )" />
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -208,6 +223,27 @@ watch(
|
|||
.search-artists {
|
||||
text-align: center;
|
||||
}
|
||||
.filters {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
margin-bottom: 5rem;
|
||||
}
|
||||
.filter {
|
||||
width: calc(80% / v-bind('filters.length'));
|
||||
max-width: 200px;
|
||||
margin: 1rem;
|
||||
padding: .5rem;
|
||||
font-size: 1.25rem;
|
||||
border-radius: .25rem;
|
||||
}
|
||||
.filter:hover {
|
||||
background: var(--color-background-mute);
|
||||
}
|
||||
.filter[data-active=true] {
|
||||
border-bottom: .125rem var(--color-text) solid;
|
||||
border-radius: .25rem .25rem 0 0;
|
||||
}
|
||||
.text-full {
|
||||
padding: 1rem;
|
||||
font-size: 1.5rem;
|
||||
|
|
|
@ -9,6 +9,7 @@ const show = ref(false);
|
|||
|
||||
<template>
|
||||
<button
|
||||
aria-label="Search Button"
|
||||
class="bi bi-search popup-wrap"
|
||||
@mouseenter="show = true"
|
||||
@mouseleave="show = false">
|
||||
|
@ -16,6 +17,7 @@ const show = ref(false);
|
|||
<div v-if="show" class="popup">
|
||||
<input
|
||||
type="text"
|
||||
aria-label="Search Input"
|
||||
placeholder="Search..."
|
||||
@change="$emit('update-search', $event.target.value)"
|
||||
:value="search" />
|
||||
|
|
|
@ -7,19 +7,19 @@ const props = defineProps({
|
|||
channel: String,
|
||||
play: String,
|
||||
art: String,
|
||||
});
|
||||
}),
|
||||
|
||||
const emit = defineEmits(['get-artist', 'open-song']);
|
||||
emit = defineEmits(['get-artist', 'open-song']),
|
||||
|
||||
const show = ref(false);
|
||||
show = ref(false),
|
||||
|
||||
function openSong(el) {
|
||||
openSong = (el) => {
|
||||
if (!el.classList.contains('ign')) {
|
||||
emit('open-song', props.play);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
async function Share() {
|
||||
Share = async () => {
|
||||
if ('share' in navigator) {
|
||||
const data = {
|
||||
title: `Listen to ${props.title} by ${props.author} on Hyperpipe`,
|
||||
|
@ -42,11 +42,11 @@ async function Share() {
|
|||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
console.log(props)
|
||||
})
|
||||
console.log(props);
|
||||
});
|
||||
</script>
|
||||
<template>
|
||||
<div class="song card flex pop" @click="openSong($event.target)">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import Modal from './Modal.vue'
|
||||
import { useListPlaylists } from '../scripts/db.js'
|
||||
import Modal from './Modal.vue';
|
||||
import { useListPlaylists } from '../scripts/db.js';
|
||||
|
||||
defineProps({
|
||||
state: String,
|
||||
|
@ -10,8 +10,20 @@ defineProps({
|
|||
loop: Boolean,
|
||||
});
|
||||
|
||||
const emit = defineEmits(['vol', 'play', 'list', 'loop', 'save', 'change-time']),
|
||||
showVol = ref(false), vol = ref(1), showmenu = ref(false), showpl = ref(false), pl = ref(''), list = ref([]);
|
||||
const emit = defineEmits([
|
||||
'vol',
|
||||
'play',
|
||||
'list',
|
||||
'loop',
|
||||
'save',
|
||||
'change-time',
|
||||
]),
|
||||
showVol = ref(false),
|
||||
vol = ref(1),
|
||||
showmenu = ref(false),
|
||||
showpl = ref(false),
|
||||
pl = ref(''),
|
||||
list = ref([]);
|
||||
|
||||
function Save() {
|
||||
showpl.value = true;
|
||||
|
@ -19,21 +31,39 @@ function Save() {
|
|||
console.log(res);
|
||||
list.value = res;
|
||||
showmenu.value = false;
|
||||
})
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<template>
|
||||
<Teleport to="body">
|
||||
<Transition name="fade">
|
||||
<Modal n="2" :display="showpl" title="Select Playlist to Add" @show="(e) => { showpl = e }">
|
||||
<Modal
|
||||
n="2"
|
||||
:display="showpl"
|
||||
title="Select Playlist to Add"
|
||||
@show="
|
||||
(e) => {
|
||||
showpl = e;
|
||||
}
|
||||
">
|
||||
<template #content>
|
||||
<template v-for="i in list">
|
||||
<div class="flex" @click="pl = i.name"><span>{{ i.name }}</span><span class="ml-auto">{{ i.urls.length || '' }}</span></div>
|
||||
<div class="flex item" @click="pl = i.name">
|
||||
<span>{{ i.name }}</span
|
||||
><span class="ml-auto">{{ i.urls.length || '' }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
<template #buttons>
|
||||
<button @click="showpl = false">Cancel</button>
|
||||
<button @click="if (pl) $emit('save', pl); showpl = false">Add</button>
|
||||
<button aria-label="Cancel" @click="showpl = false">Cancel</button>
|
||||
<button
|
||||
aria-label="Add Song"
|
||||
@click="
|
||||
if (pl) $emit('save', pl);
|
||||
showpl = false;
|
||||
">
|
||||
Add
|
||||
</button>
|
||||
</template>
|
||||
</Modal>
|
||||
</Transition>
|
||||
|
@ -43,6 +73,7 @@ function Save() {
|
|||
<div class="flex statusbar-left">
|
||||
<button
|
||||
id="btn-play-pause"
|
||||
aria-label="Play or Pause"
|
||||
:class="'bi bi-' + state"
|
||||
@click="$emit('play')"></button>
|
||||
|
||||
|
@ -51,6 +82,7 @@ function Save() {
|
|||
class="range-wrap"
|
||||
:style="'--fw:' + time + '%;'">
|
||||
<input
|
||||
aria-label="Change Time"
|
||||
:value="time"
|
||||
type="range"
|
||||
name="statusbar-progress"
|
||||
|
@ -62,31 +94,49 @@ function Save() {
|
|||
<div class="flex statusbar-right">
|
||||
<button
|
||||
id="vol-btn"
|
||||
aria-label="Volume Buttons"
|
||||
@click="showVol = !showVol"
|
||||
class="popup-wrap bi bi-volume-up">
|
||||
<Transition name="fade">
|
||||
<div v-if="showVol" id="vol" class="popup">
|
||||
<input
|
||||
id="vol-input"
|
||||
aria-label="Volume Input"
|
||||
type="range"
|
||||
:value="vol"
|
||||
max="1"
|
||||
step=".01"
|
||||
@input="$emit('vol', $event.target.value); vol = $event.target.value" />
|
||||
@input="
|
||||
$emit('vol', $event.target.value);
|
||||
vol = $event.target.value;
|
||||
" />
|
||||
</div>
|
||||
</Transition>
|
||||
</button>
|
||||
<button class="bi bi-three-dots" @click="showmenu = !showmenu; if (show) $emit('list', 'showplaylist')"></button>
|
||||
<button
|
||||
class="bi bi-three-dots"
|
||||
aria-label="More Controls"
|
||||
@click="
|
||||
showmenu = !showmenu;
|
||||
if (show) $emit('list', 'showplaylist');
|
||||
"></button>
|
||||
<div id="menu" v-if="showmenu" class="popup">
|
||||
<button id="addToPlaylist" title="Add Current Song to a Playlist" class="bi bi-collection" @click="Save"></button>
|
||||
<button
|
||||
id="addToPlaylist"
|
||||
title="Add Current Song to a Playlist"
|
||||
aria-label="Add Current Song to a Playlist"
|
||||
class="bi bi-collection"
|
||||
@click="Save"></button>
|
||||
<button
|
||||
id="list-btn"
|
||||
title="Current Playlist"
|
||||
aria-label="Current Playlist"
|
||||
:class="'bi bi-music-note-list ' + show"
|
||||
@click="$emit('list', 'showplaylist')"></button>
|
||||
<button
|
||||
id="loop-btn"
|
||||
title="Loop"
|
||||
aria-label="Loop"
|
||||
:class="'bi bi-infinity ' + loop"
|
||||
@click="$emit('loop', 'loop')"></button>
|
||||
</div>
|
||||
|
@ -125,16 +175,22 @@ function Save() {
|
|||
.ml-auto {
|
||||
margin-left: auto;
|
||||
}
|
||||
.item {
|
||||
border-radius: 50rem 0 0 50rem;
|
||||
}
|
||||
.item:hover {
|
||||
background-color: var(--color-background-mute);
|
||||
}
|
||||
#menu {
|
||||
bottom: 1.5rem;
|
||||
left: -1.75rem;
|
||||
box-shadow: .5rem .5rem 2rem var(--color-shadow);
|
||||
box-shadow: 0.5rem 0.5rem 2rem var(--color-shadow);
|
||||
}
|
||||
#vol {
|
||||
--h: 6.5rem;
|
||||
--w: 1rem;
|
||||
display: flex;
|
||||
box-shadow: -.5rem -.5rem 2rem var(--color-shadow);
|
||||
box-shadow: -0.5rem -0.5rem 2rem var(--color-shadow);
|
||||
transform: rotateZ(270deg) translateX(calc(calc(var(--h) / 2) - 0.5rem))
|
||||
translateY(calc(calc(var(--w) + 2rem) * -1));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue