Switched to Composition API

This commit is contained in:
Shiny Nematoda 2022-04-15 15:29:43 +05:30
parent 75b0a9b319
commit 8ee03fa623
11 changed files with 705 additions and 647 deletions

View file

@ -7,6 +7,12 @@ defineProps({
default: '--art: linear-gradient(45deg, #88c0d0, #5e81ac);',
},
});
const emit = defineEmits(['open-album']);
function onClick() {
emit('open-album');
}
</script>
<template>
@ -20,16 +26,6 @@ defineProps({
</div>
</template>
<script>
export default {
methods: {
onClick() {
this.$emit('open-album');
},
},
};
</script>
<style scoped>
.card {
min-height: 17rem;

View file

@ -1,5 +1,4 @@
<script setup>
import { ref } from 'vue';
import PlayBtn from './PlayBtn.vue';
defineProps(['title', 'desc', 'subs', 'thumbs', 'play']);

View file

@ -1,6 +1,7 @@
<script setup>
defineEmits(['update-search']);
import SearchBar from '../components/SearchBar.vue';
defineEmits(['update-search']);
</script>
<template>

View file

@ -1,5 +1,9 @@
<script setup>
defineProps(['url', 'urls', 'show']);
defineProps({
url: String,
urls: Array,
show: Boolean,
});
defineEmits(['playthis']);
</script>
@ -56,34 +60,4 @@ defineEmits(['playthis']);
.pl-main {
padding-left: 3rem;
}
.bars-wrap {
position: absolute;
height: 1.5rem;
width: 2rem;
transform: rotateZ(180deg);
}
.bars {
position: relative;
height: 15%;
width: calc(calc(100% / 3) - 0.2rem);
margin-left: 0.1rem;
background: var(--color-foreground);
float: left;
animation: heightc 1s ease infinite;
}
.bars:first-child {
animation-delay: 0.25s;
}
.bars:nth-child(2) {
animation-delay: 0.5s;
}
.bars:last-child {
margin-left: none;
}
@keyframes heightc {
50% {
height: 100%;
}
}
</style>

View file

@ -1,44 +1,141 @@
<script setup>
defineProps([
'search',
'songItems',
'items'
]);
defineEmits([
'get-song',
import { reactive, watch } from 'vue';
import PlayBtn from './PlayBtn.vue';
import SongItem from './SongItem.vue';
import AlbumItem from './AlbumItem.vue';
import { getJsonPiped, getPipedQuery } from '../scripts/fetch.js'
const props = defineProps(['search', 'songItems', 'items']);
const emit = defineEmits([
'get-album',
'get-artist',
'lazy',
'play-urls',
'add-song',
]);
const data = reactive({
notes: null,
albums: null,
albumTitle: null,
songs: null,
recommendedArtists: null,
});
function Reset() {
for (let i in data) {
data[i] = null
}
}
function playAlbum() {
const urls = data.songs.items.map((item) => {
return { url: item.url, title: item.title };
});
emit('play-urls', urls);
}
function getSearch(q) {
if (q) {
const pq = q.split(' ').join('+');
history.pushState({}, '', `/search/${pq + getPipedQuery()}`);
document.title = 'Search Results for ' + q;
getResults(pq);
emit('lazy');
} else {
Reset();
history.pushState({}, '', '/');
document.title = 'Hyperpipe';
console.log('No Search');
}
}
async function getResults(q) {
const filters = ['music_songs', 'music_albums'];
for (let filter of filters) {
const json = await getJsonPiped(`/search?q=${q}&filter=${filter}`);
data[filter.split('_')[1]] = json;
console.log(json, data);
}
}
watch(
() => props.search,
(n) => {
if (n) {
n = n.replace(location.search || '', '');
console.log(n);
getSearch(n);
}
},
);
watch(
() => props.songItems,
(i) => {
console.log(i);
Reset();
data.songs = {}
data.songs.items = i.items;
data.albumTitle = i.title;
},
);
watch(
() => props.items,
(itms) => {
Reset();
for (let i in itms) {
data[i] = {}
data[i].items = itms[i];
console.log(data[i]);
}
},
);
</script>
<template>
<div v-if="songs && songs.corrected" class="text-full">
I Fixed your Typo, "<span class="caps">{{ songs.suggestion }}</span
<div v-if="data.songs && data.songs.corrected" class="text-full">
I Fixed your Typo, "<span class="caps">{{ data.songs.suggestion }}</span
>"!!
</div>
<div v-if="albumTitle" class="text-full flex">
<div v-if="data.albumTitle" class="text-full flex">
<PlayBtn @click="playAlbum" />
<span>{{ albumTitle }}</span>
<span>{{ data.albumTitle }}</span>
</div>
<div v-if="songs && songs.items[0]" class="search-songs">
<div v-if="data.songs && data.songs.items[0]" class="search-songs">
<h2>Top Songs</h2>
<div class="grid">
<template v-for="song in songs.items">
<template v-for="song in data.songs.items">
<SongItem
:author="song.uploaderName || ''"
:title="song.title || song.name"
:channel="song.uploaderUrl || ''"
:play="song.url || '/watch?v=' + song.videoId"
:play="song.url || '/watch?v=' + song.id"
@open-song="
$emit('get-song', {
$emit('play-urls', [{
url: song.url || '/watch?v=' + song.id,
title: song.title || song.name,
})
}])
"
@get-artist="
(e) => {
@ -56,17 +153,18 @@ defineEmits([
</template>
</div>
<a
v-if="notes"
@click.prevent="$emit('get-album', '/playlist?list=' + notes.items)"
v-if="data.notes"
@click.prevent="$emit('get-album', '/playlist?list=' + data.notes.items)"
class="more"
:href="'/playlist?list=' + data.notes.items"
>See All</a
>
</div>
<div v-if="albums && albums.items[0]" class="search-albums">
<div v-if="data.albums && data.albums.items[0]" class="search-albums">
<h2>Albums</h2>
<div class="grid-3">
<template v-for="album in albums.items">
<template v-for="album in data.albums.items">
<AlbumItem
:author="album.uploaderName || album.subtitle"
:name="album.name || album.title"
@ -81,11 +179,11 @@ defineEmits([
</div>
<div
v-if="recommendedArtists && recommendedArtists.items[0]"
v-if="data.recommendedArtists && data.recommendedArtists.items[0]"
class="search-artists">
<h2>Similar Artists</h2>
<div class="grid-3">
<template v-for="artist in recommendedArtists.items">
<template v-for="artist in data.recommendedArtists.items">
<AlbumItem
:author="artist.subtitle"
:name="artist.title"
@ -96,99 +194,6 @@ defineEmits([
</div>
</template>
<script>
import PlayBtn from './PlayBtn.vue';
import SongItem from './SongItem.vue';
import AlbumItem from './AlbumItem.vue';
export default {
components: {
PlayBtn,
SongItem,
AlbumItem,
},
data() {
return {
songs: null,
albums: null,
recommendedArtists: null,
albumTitle: null,
notes: null,
};
},
watch: {
search(NewSearch) {
console.log(NewSearch);
this.getSearch(NewSearch);
},
songItems(i) {
console.log(i);
this.Reset();
this.songs = {};
this.songs.items = i.items;
this.albumTitle = i.title;
},
items(itms) {
this.Reset();
for (let i in itms) {
this[i] = {};
this[i].items = itms[i];
console.log(this[i]);
}
},
},
methods: {
Reset() {
this.notes = null;
this.albums = null;
this.albumTitle = null;
this.songs = null;
this.recommendedArtists = null;
},
playAlbum() {
const urls = this.songs.items.map((item) => {
return { url: item.url, title: item.title };
});
this.$emit('play-urls', urls);
},
getSearch(q) {
if (q) {
history.pushState({}, '', `/search/${q}`);
document.title = 'Search Results for ' + q;
this.getResults(q.split(' ').join('+'));
this.$emit('lazy');
} else {
this.Reset();
history.pushState({}, '', '/');
document.title = 'Hyperpipe';
console.log('No Search');
}
},
getResults(q) {
const filters = ['music_songs', 'music_albums'];
for (let filter of filters) {
fetch(
`https://pipedapi.kavin.rocks/search?q=${q}&filter=${filter}`,
).then((res) => {
res.json().then((json) => {
this[filter.split('_')[1]] = json;
console.log(json);
});
});
}
},
},
};
</script>
<style scoped>
.search-albums,
.search-songs,
@ -196,11 +201,23 @@ export default {
place-items: start center;
margin-bottom: 2rem;
}
.search-songs h2,
.search-artists h2,
.search-albums h2 {
text-align: center;
}
.search-albums .grid-3,
.search-artists .grid-3 {
display: grid;
grid-template-columns: 1fr;
}
.search-artists {
text-align: center;
}
.search-artists .bg-img {
border-radius: 50%;
margin-bottom: 0.5rem;
}
.text-full {
padding: 1rem;
font-size: 1.5rem;

View file

@ -1,11 +1,43 @@
<script setup>
defineProps({
const props = defineProps({
author: String,
title: String,
channel: String,
play: String,
});
defineEmits(['get-artist']);
const emit = defineEmits(['get-artist', 'open-song']);
function openSong(el) {
if (!el.classList.contains('ign')) {
emit('open-song', props.play);
}
}
async function Share() {
if ('share' in navigator) {
const data = {
title: `Listen to ${props.title} by ${props.author} on Hyperpipe`,
url: location.origin + props.play,
};
try {
await navigator.share(data);
console.log('Done Sharing!');
} catch (err) {
console.log(err);
}
} else {
navigator.clipboard.writeText(location.host + props.play).then(
() => {
console.log('Copied to Clipboard');
},
(err) => {
console.log(err);
},
);
}
}
</script>
<template>
<div class="song card flex pop" @click="openSong($event.target)">
@ -35,42 +67,6 @@ defineEmits(['get-artist']);
</div>
</template>
<script>
export default {
methods: {
openSong(el) {
if (!el.classList.contains('ign')) {
this.$emit('open-song', this.play);
}
},
async Share() {
if ('share' in navigator) {
const data = {
title: `Listen to ${this.title} by ${this.author} on Hyperpipe`,
url: location.origin + this.play,
};
try {
await navigator.share(data);
console.log('Done Sharing!');
} catch (err) {
console.log(err);
}
} else {
navigator.clipboard.writeText(location.host + this.play).then(
() => {
console.log('Copied to Clipboard');
},
(err) => {
console.log(err);
},
);
}
},
},
};
</script>
<style scoped>
.card {
margin: 1rem 0;

View file

@ -1,13 +1,11 @@
<script setup>
const props = defineProps({
defineProps({
state: String,
time: Number,
show: Boolean,
loop: Boolean,
});
defineEmits(['vol', 'play', 'list', 'loop']);
console.log(props);
defineEmits(['vol', 'play', 'list', 'loop', 'change-time']);
</script>
<template>
<div id="statusbar" class="flex">
@ -19,9 +17,14 @@ console.log(props);
<div
id="statusbar-progress"
class="progress"
:style="'--tw: ' + time + '%;'">
<div class="progress-thumb"></div>
class="range-wrap"
:style="'--fw:' + time + '%;'">
<input
:value="time"
type="range"
name="statusbar-progress"
max="100"
@input="$emit('change-time', $event.target.value)" />
</div>
</div>
@ -77,38 +80,6 @@ console.log(props);
.bi-infinity {
font-size: 1.75rem !important;
}
.progress {
--h: 0.25rem;
--w: 5rem;
--th: 100%;
--tw: 75%;
background: var(--color-border);
height: var(--h);
width: var(--w);
transition: width 0.4s ease;
}
.progress.v {
--th: 75%;
--tw: 100%;
--h: 5rem;
--w: 0.25rem;
transform: rotateZ(180deg);
z-index: 999999;
}
.progress-thumb {
width: var(--tw);
height: var(--th);
background: var(--color-foreground);
overflow: hidden;
transition: width 0.4s ease;
}
.progress-thumb:after {
content: '';
background-color: #fff;
height: 0.5rem;
width: 0.5rem;
border-radius: 50%;
}
.popup {
--h: 6.5rem;
--w: 1rem;
@ -125,6 +96,7 @@ input[type='range'] {
background: transparent;
color: transparent;
cursor: pointer;
position: relative;
}
input[type='range']:focus {
outline: none;
@ -132,16 +104,49 @@ input[type='range']:focus {
input[type='range']::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
opacity: 0;
transition: opacity 0.4s ease;
}
input[type='range']:hover::-webkit-slider-thumb,
#vol input[type='range']::-webkit-slider-thumb {
background-color: var(--color-foreground);
opacity: 1;
height: 1rem;
width: 1rem;
border-radius: 50%;
margin-top: -0.45rem;
}
input[type='range']::-webkit-slider-runnable-track {
height: 0.1rem;
height: 100%;
background-color: var(--color-border);
}
#vol input[type='range']::-webkit-slider-runnable-track {
height: 0.1rem;
}
.range-wrap {
--fw: 0%;
display: flex;
align-items: center;
position: relative;
height: 0.25rem;
display: inline-block;
}
.range-wrap:before {
content: '';
width: var(--fw);
position: absolute;
left: 0;
bottom: 0;
height: 0.25rem;
background-color: var(--color-foreground);
transition: width 0.4s ease;
}
.range-wrap input[type='range'] {
--w: 100%;
--h: 100%;
position: absolute;
top: 0;
}
#statusbar-progress {
width: 50vw;
min-width: 200px;