mirror of
https://codeberg.org/Hyperpipe/Hyperpipe
synced 2025-06-28 05:08:00 +02:00
Added support for charts
This commit is contained in:
parent
0b159c9a42
commit
a9d7d07e7b
16 changed files with 213 additions and 66 deletions
|
@ -6,13 +6,6 @@ import { useResults, useArtist } from '@/stores/results.js';
|
|||
|
||||
const artist = useArtist(),
|
||||
results = useResults();
|
||||
|
||||
/*const show = ref(-1);
|
||||
show.value = location.pathname.indexOf('/channel/UC');
|
||||
|
||||
onUpdated(() => {
|
||||
show.value = location.pathname.indexOf('/channel/UC');
|
||||
});*/
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -4,7 +4,9 @@ defineEmits(['click']);
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<button :class="'bi clickable bi-' + (ico ? ico : 'play')" @click="$emit('click')">
|
||||
<button
|
||||
:class="'bi clickable bi-' + (ico ? ico : 'play')"
|
||||
@click="$emit('click')">
|
||||
<slot name="menu"></slot>
|
||||
</button>
|
||||
</template>
|
||||
|
@ -24,12 +26,18 @@ defineEmits(['click']);
|
|||
transition: background 0.4s ease;
|
||||
margin-right: auto;
|
||||
}
|
||||
.bi-play {
|
||||
color: var(--color-background-soft);
|
||||
box-shadow: 0 0 1rem var(--color-foreground);
|
||||
transition: all 0.4s ease;
|
||||
}
|
||||
.bi-play::before {
|
||||
padding-left: 0.2rem;
|
||||
}
|
||||
.bi:hover,
|
||||
.bi:not(.bi-play) {
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
.bi:not(.bi-play) {
|
||||
font-size: 1.75rem;
|
||||
|
|
79
src/components/Charts.vue
Normal file
79
src/components/Charts.vue
Normal file
|
@ -0,0 +1,79 @@
|
|||
<script setup>
|
||||
import { ref, reactive, watch, onMounted } from 'vue';
|
||||
|
||||
import AlbumItem from '@/components/AlbumItem.vue';
|
||||
import SongItem from '@/components/SongItem.vue';
|
||||
|
||||
import { getJsonHyp } from '@/scripts/fetch.js';
|
||||
|
||||
import { useResults, useArtist } from '@/stores/results.js';
|
||||
import { useI18n } from '@/stores/misc.js';
|
||||
|
||||
const { getArtist } = useArtist(),
|
||||
results = useResults(),
|
||||
{ t } = useI18n();
|
||||
|
||||
const id = ref(''),
|
||||
data = reactive({
|
||||
options: [],
|
||||
songs: [],
|
||||
artists: [],
|
||||
});
|
||||
|
||||
async function getCharts() {
|
||||
const json = await getJsonHyp(
|
||||
`/charts?params=${results.chartsId}&code=${id.value}`,
|
||||
);
|
||||
|
||||
console.log(json);
|
||||
|
||||
if (!id.value)
|
||||
id.value = json.options.all.filter(
|
||||
i => i.title == json.options.default,
|
||||
)[0].id;
|
||||
|
||||
data.options = json.options.all;
|
||||
data.songs = json.trending;
|
||||
data.artists = json.artists;
|
||||
}
|
||||
|
||||
watch(id, () => {
|
||||
getCharts();
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
getCharts();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<template v-if="data.options.length > 0">
|
||||
<select :value="id" class="input" @input="id = $event.target.value">
|
||||
<option v-for="i in data.options" :value="i.id">{{ i.title }}</option>
|
||||
</select>
|
||||
</template>
|
||||
|
||||
<template v-if="data.artists.length > 0">
|
||||
<h2 class="center">{{ t('title.artists') }}</h2>
|
||||
<div class="grid-3 circle">
|
||||
<AlbumItem
|
||||
v-for="i in data.artists"
|
||||
:name="i.title"
|
||||
:author="i.subtitle"
|
||||
:art="i.thumbnails[1].url"
|
||||
@open-album="getArtist(i.id)" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="data.songs.length > 0">
|
||||
<h2 class="center">{{ t('title.songs') }}</h2>
|
||||
<div class="grid">
|
||||
<SongItem
|
||||
v-for="i in data.songs"
|
||||
:title="i.title"
|
||||
:author="i.subtitle"
|
||||
:channel="'/channel/' + i.subId"
|
||||
:art="i.thumbnails[0].url" />
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
|
@ -20,7 +20,9 @@ watch(show, n => {
|
|||
<template>
|
||||
<Transition name="fade">
|
||||
<div class="modal" v-if="show">
|
||||
<span class="bi bi-x-lg clickable modal-close" @click="show = false"></span>
|
||||
<span
|
||||
class="bi bi-x-lg clickable modal-close"
|
||||
@click="show = false"></span>
|
||||
<div class="modal-box">
|
||||
<div class="modal-title">{{ title }}</div>
|
||||
<div class="modal-content">
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<script setup>
|
||||
import { reactive } from 'vue';
|
||||
import SearchBar from '../components/SearchBar.vue';
|
||||
|
||||
import SearchBar from '@/components/SearchBar.vue';
|
||||
import IcoHyp from '@/assets/icons/IcoHyp.vue';
|
||||
|
||||
import { useNav } from '@/stores/misc.js';
|
||||
|
||||
|
@ -33,12 +35,7 @@ function set(page) {
|
|||
<template>
|
||||
<nav>
|
||||
<h1 class="bi" @click="home">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<path
|
||||
d="M5.097 13.097a2.904 2.904 0 0 1 5.806 0A2.905 2.905 0 0 1 8 16a2.905 2.905 0 0 1-2.903-2.903Z" />
|
||||
<path
|
||||
d="M2.194 11.618a1.614 1.614 0 1 0 2.258 1.479c0-.661-.399-1.23-.968-1.479v-4.87l3.097 2.065v-4.31l1.432-2.18 1.406 2.09v4.4l3.097-2.065v4.87a1.614 1.614 0 1 0 2.258 1.479c0-.661-.398-1.23-.968-1.479v-7.27L10.71 6.413v-2.4L7.987 0 5.29 4.116v2.297L2.194 4.348v7.27Z" />
|
||||
</svg>
|
||||
<IcoHyp />
|
||||
</h1>
|
||||
|
||||
<div class="wrap">
|
||||
|
@ -50,6 +47,10 @@ function set(page) {
|
|||
class="nav-ico bi bi-compass clickable"
|
||||
:data-active="nav.state.page == 'explore'"
|
||||
@click="set('explore')"></span>
|
||||
<span
|
||||
class="nav-ico bi bi-graph-down clickable"
|
||||
:data-active="nav.state.page == 'charts'"
|
||||
@click="set('charts')"></span>
|
||||
<span
|
||||
class="nav-ico bi bi-collection clickable"
|
||||
:data-active="nav.state.page == 'library'"
|
||||
|
|
|
@ -7,6 +7,7 @@ import {
|
|||
onBeforeUnmount,
|
||||
onUnmounted,
|
||||
} from 'vue';
|
||||
|
||||
import muxjs from 'mux.js';
|
||||
window.muxjs = muxjs;
|
||||
|
||||
|
|
|
@ -14,7 +14,10 @@ defineEmits(['playthis']);
|
|||
<div class="pl-modal placeholder" :data-placeholder="t('playlist.add')">
|
||||
<template v-for="plurl in data.state.urls">
|
||||
<div class="pl-item" @click="$emit('playthis', plurl)">
|
||||
<span v-if="data.state.url == plurl.url" class="bars-wrap" :class="player.state.status">
|
||||
<span
|
||||
v-if="data.state.url == plurl.url"
|
||||
class="bars-wrap"
|
||||
:class="player.state.status">
|
||||
<div class="bars"></div>
|
||||
<div class="bars"></div>
|
||||
<div class="bars"></div>
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
|
||||
import { getJson } from '@/scripts/fetch.js';
|
||||
import { SUPPORTED_LOCALES, useI18n } from '@/stores/misc.js';
|
||||
import {
|
||||
PIPED_INSTANCE,
|
||||
HYPERPIPE_INSTANCE,
|
||||
getJson,
|
||||
} from '@/scripts/fetch.js';
|
||||
import { useStore } from '@/scripts/util.js';
|
||||
|
||||
import { SUPPORTED_LOCALES, useI18n } from '@/stores/misc.js';
|
||||
|
||||
const { t, setupLocale } = useI18n(),
|
||||
instances = ref([]),
|
||||
hypInstances = ref([]),
|
||||
|
@ -56,17 +61,17 @@ function getStoreBool(key, ele) {
|
|||
const verifyApi = computed(() =>
|
||||
hypInstances.value
|
||||
.map(i => i.api_url.replace('https://', '').replace('http://'))
|
||||
.includes(getStore('api') || 'hyperpipeapi.onrender.com'),
|
||||
.includes(getStore('api') || PIPED_INSTANCE),
|
||||
),
|
||||
verifyPipedApi = computed(() =>
|
||||
instances.value
|
||||
.map(i => i.api_url.replace('https://', ''))
|
||||
.includes(getStore('pipedapi') || 'pipedapi.kavin.rocks'),
|
||||
.includes(getStore('pipedapi') || PIPED_INSTANCE),
|
||||
),
|
||||
verifyAuthApi = computed(() =>
|
||||
instances.value
|
||||
.map(i => i.api_url.replace('https://', ''))
|
||||
.includes(getStore('authapi') || 'pipedapi.kavin.rocks'),
|
||||
.includes(getStore('authapi') || PIPED_INSTANCE),
|
||||
);
|
||||
|
||||
onMounted(() => {
|
||||
|
@ -78,6 +83,7 @@ onMounted(() => {
|
|||
<h2>{{ t('pref.theme') }}</h2>
|
||||
<select
|
||||
id="pref-theme"
|
||||
class="input"
|
||||
:value="getTheme()"
|
||||
@change="setTheme($event.target.value)">
|
||||
<option value="dark">Dark (Default)</option>
|
||||
|
@ -91,6 +97,7 @@ onMounted(() => {
|
|||
|
||||
<select
|
||||
id="pref-lang"
|
||||
class="input"
|
||||
:value="getStore('locale') || 'en'"
|
||||
@change="setLang($event.target.value)">
|
||||
<option v-for="i in SUPPORTED_LOCALES" :value="i.code">{{ i.name }}</option>
|
||||
|
@ -103,6 +110,7 @@ onMounted(() => {
|
|||
type="checkbox"
|
||||
name="pref-chk-next"
|
||||
id="pref-chk-next"
|
||||
class="input"
|
||||
@change="setStore('next', $event.target.checked)"
|
||||
v-model="next" />
|
||||
<label for="pref-chk-next">{{ t('pref.auto_queue') }}</label>
|
||||
|
@ -113,6 +121,7 @@ onMounted(() => {
|
|||
<select
|
||||
id="pref-codec"
|
||||
name="pref-codec"
|
||||
class="input"
|
||||
:value="getStore('codec') || 'opus:mp4a'"
|
||||
@change="setStore('codec', $event.target.value)">
|
||||
<option value="opus:mp4a">opus, mp4a</option>
|
||||
|
@ -127,6 +136,7 @@ onMounted(() => {
|
|||
<select
|
||||
id="pref-quality"
|
||||
name="pref-quality"
|
||||
class="input"
|
||||
:value="getStore('quality') || 'auto'"
|
||||
@change="setStore('quality', $event.target.value)">
|
||||
<option value="auto">{{ t('pref.auto') }}</option>
|
||||
|
@ -141,6 +151,7 @@ onMounted(() => {
|
|||
type="number"
|
||||
name="pref-volume"
|
||||
id="pref-volume"
|
||||
class="input"
|
||||
max="100"
|
||||
min="0"
|
||||
:value="getStore('vol') || 100"
|
||||
|
@ -151,7 +162,8 @@ onMounted(() => {
|
|||
|
||||
<select
|
||||
v-if="hypInstances"
|
||||
:value="getStore('api') || 'hyperpipeapi.onrender.com'"
|
||||
class="input"
|
||||
:value="getStore('api') || HYPERPIPE_INSTANCE"
|
||||
@change="setStore('api', $event.target.value)">
|
||||
<option
|
||||
v-for="i in hypInstances"
|
||||
|
@ -161,7 +173,7 @@ onMounted(() => {
|
|||
</option>
|
||||
|
||||
<option v-if="!verifyApi">
|
||||
{{ getStore('api') || 'hyperpipeapi.onrender.com' }}
|
||||
{{ getStore('api') || HYPERPIPE_INSTANCE }}
|
||||
</option>
|
||||
</select>
|
||||
|
||||
|
@ -189,7 +201,8 @@ onMounted(() => {
|
|||
<h2>{{ t('instances.piped') }}</h2>
|
||||
<select
|
||||
v-if="instances"
|
||||
:value="getStore('pipedapi') || 'pipedapi.kavin.rocks'"
|
||||
class="input"
|
||||
:value="getStore('pipedapi') || PIPED_INSTANCE"
|
||||
@change="setStore('pipedapi', $event.target.value)">
|
||||
<option
|
||||
v-for="i in instances"
|
||||
|
@ -199,7 +212,7 @@ onMounted(() => {
|
|||
</option>
|
||||
|
||||
<option v-if="!verifyPipedApi">
|
||||
{{ getStore('pipedapi') || 'pipedapi.kavin.rocks' }}
|
||||
{{ getStore('pipedapi') || PIPED_INSTANCE }}
|
||||
</option>
|
||||
</select>
|
||||
|
||||
|
@ -207,7 +220,8 @@ onMounted(() => {
|
|||
|
||||
<select
|
||||
v-if="instances"
|
||||
:value="getStore('authapi') || 'pipedapi.kavin.rocks'"
|
||||
class="input"
|
||||
:value="getStore('authapi') || PIPED_INSTANCE"
|
||||
@change="setStore('authapi', $event.target.value)">
|
||||
<option
|
||||
v-for="i in instances"
|
||||
|
@ -217,7 +231,7 @@ onMounted(() => {
|
|||
</option>
|
||||
|
||||
<option v-if="!verifyAuthApi">
|
||||
{{ getStore('authapi') || 'pipedapi.kavin.rocks' }}
|
||||
{{ getStore('authapi') || PIPED_INSTANCE }}
|
||||
</option>
|
||||
</select>
|
||||
|
||||
|
@ -274,17 +288,6 @@ label,
|
|||
footer {
|
||||
text-align: center;
|
||||
}
|
||||
select,
|
||||
input {
|
||||
font-size: 1rem;
|
||||
margin: 1rem auto;
|
||||
padding: 0.5rem 0.75rem;
|
||||
border: none;
|
||||
color: var(--color-text);
|
||||
max-width: 20rem;
|
||||
border-radius: 0.125rem;
|
||||
background-color: var(--color-background-mute);
|
||||
}
|
||||
input[type='number'] {
|
||||
width: 4.5rem;
|
||||
}
|
||||
|
|
|
@ -148,7 +148,9 @@ onUpdated(() => {
|
|||
<template #menu>
|
||||
<Transition name="fade">
|
||||
<div v-if="albumMenu" class="alb popup">
|
||||
<button class="bi bi-bookmark-plus clickable" @click="saveAlbum"></button>
|
||||
<button
|
||||
class="bi bi-bookmark-plus clickable"
|
||||
@click="saveAlbum"></button>
|
||||
|
||||
<button
|
||||
class="bi bi-plus-lg clickable"
|
||||
|
@ -162,7 +164,9 @@ onUpdated(() => {
|
|||
)
|
||||
"></button>
|
||||
|
||||
<button class="bi bi-shuffle clickable" @click="shuffleAdd"></button>
|
||||
<button
|
||||
class="bi bi-shuffle clickable"
|
||||
@click="shuffleAdd"></button>
|
||||
</div>
|
||||
</Transition>
|
||||
</template>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue