mirror of
https://codeberg.org/Hyperpipe/Hyperpipe
synced 2025-06-28 05:08:00 +02:00
Changes:
- Search continuations (related to #46) - Search for Playlists (related to #46)
This commit is contained in:
parent
7905394b26
commit
2ff1308278
6 changed files with 104 additions and 38 deletions
16
src/App.vue
16
src/App.vue
|
@ -130,22 +130,6 @@ onMounted(() => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Media Controls */
|
|
||||||
if ('mediaSession' in navigator) {
|
|
||||||
navigator.mediaSession.setActionHandler('previoustrack', () => {
|
|
||||||
if (data.state.urls.length > 2) {
|
|
||||||
const i = data.state.urls.map(s => s.url).indexOf(data.state.url);
|
|
||||||
data.getSong(data.state.urls[i - 1].url);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
navigator.mediaSession.setActionHandler('nexttrack', () => {
|
|
||||||
if (data.state.urls.length > 2) {
|
|
||||||
const i = data.state.urls.map(s => s.url).indexOf(data.state.url);
|
|
||||||
data.getSong(data.state.urls[i + 1].url);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Setup IndexedDB for storing custom playlists */
|
/* Setup IndexedDB for storing custom playlists */
|
||||||
useSetupDB();
|
useSetupDB();
|
||||||
|
|
||||||
|
|
|
@ -97,12 +97,11 @@ async function Stream() {
|
||||||
if (quality == 'best') sel = Math.max(...bandwidths);
|
if (quality == 'best') sel = Math.max(...bandwidths);
|
||||||
else if (quality == 'worst') sel = Math.min(...bandwidths);
|
else if (quality == 'worst') sel = Math.min(...bandwidths);
|
||||||
|
|
||||||
if (sel) {
|
if (sel)
|
||||||
window.audioPlayer.selectVariantTrack(
|
window.audioPlayer.selectVariantTrack(
|
||||||
tracks[bandwidths.indexOf(sel)],
|
tracks[bandwidths.indexOf(sel)],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
console.error('Code: ' + err.code, err);
|
console.error('Code: ' + err.code, err);
|
||||||
|
@ -152,6 +151,30 @@ onMounted(() => {
|
||||||
audio.value.pause();
|
audio.value.pause();
|
||||||
player.state.status = 'play';
|
player.state.status = 'play';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
navigator.mediaSession.setActionHandler('previoustrack', () => {
|
||||||
|
if (data.state.urls.length > 2) {
|
||||||
|
const i = data.state.urls.map(s => s.url).indexOf(data.state.url);
|
||||||
|
|
||||||
|
data.getSong(data.state.urls[i - 1].url);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
navigator.mediaSession.setActionHandler('nexttrack', () => {
|
||||||
|
if (data.state.urls.length > 2) {
|
||||||
|
const i = data.state.urls.map(s => s.url).indexOf(data.state.url);
|
||||||
|
|
||||||
|
data.getSong(data.state.urls[i + 1].url);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
navigator.mediaSession.setActionHandler('seekbackward', () => {
|
||||||
|
audio.value.duration -= 10;
|
||||||
|
});
|
||||||
|
|
||||||
|
navigator.mediaSession.setActionHandler('seekforward', () => {
|
||||||
|
audio.value.duration += 10;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, reactive, watch, onUpdated } from 'vue';
|
import {
|
||||||
|
ref,
|
||||||
|
reactive,
|
||||||
|
watch,
|
||||||
|
onActivated,
|
||||||
|
onUpdated,
|
||||||
|
onDeactivated,
|
||||||
|
} from 'vue';
|
||||||
|
|
||||||
import Btn from './Btn.vue';
|
import Btn from './Btn.vue';
|
||||||
import SongItem from './SongItem.vue';
|
import SongItem from './SongItem.vue';
|
||||||
|
@ -20,7 +27,7 @@ const { t } = useI18n(),
|
||||||
artist = useArtist();
|
artist = useArtist();
|
||||||
|
|
||||||
const emit = defineEmits(['play-urls']),
|
const emit = defineEmits(['play-urls']),
|
||||||
filters = ['music_songs', 'music_albums', 'music_artists'],
|
filters = ['music_songs', 'music_albums', 'music_artists', 'music_playlists'],
|
||||||
filter = ref('music_songs'),
|
filter = ref('music_songs'),
|
||||||
isSearch = ref(/search/.test(location.pathname)),
|
isSearch = ref(/search/.test(location.pathname)),
|
||||||
albumMenu = ref(false);
|
albumMenu = ref(false);
|
||||||
|
@ -91,6 +98,32 @@ const shuffleAdd = () => {
|
||||||
console.log('No Search');
|
console.log('No Search');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
loading = ref(false),
|
||||||
|
next = ref(null),
|
||||||
|
getSearchNext = async () => {
|
||||||
|
if (!isSearch.value || loading.value || !next.value) return;
|
||||||
|
if (
|
||||||
|
window.innerHeight + window.scrollY >=
|
||||||
|
document.body.offsetHeight - window.innerHeight
|
||||||
|
) {
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
const f = filter.value || 'music_songs',
|
||||||
|
json = await getJsonPiped(
|
||||||
|
`/nextpage/search?nextpage=${encodeURIComponent(next.value)}&q=${
|
||||||
|
nav.state.search
|
||||||
|
}&filter=${f}`,
|
||||||
|
),
|
||||||
|
key = f.split('_')[1];
|
||||||
|
|
||||||
|
next.value = json.nextpage;
|
||||||
|
results.items[key].items.push(...json.items);
|
||||||
|
|
||||||
|
loading.value = false;
|
||||||
|
|
||||||
|
console.log(json, results.items);
|
||||||
|
}
|
||||||
|
},
|
||||||
getResults = async q => {
|
getResults = async q => {
|
||||||
results.resetItems();
|
results.resetItems();
|
||||||
|
|
||||||
|
@ -98,6 +131,8 @@ const shuffleAdd = () => {
|
||||||
json = await getJsonPiped(`/search?q=${q}&filter=${f}`),
|
json = await getJsonPiped(`/search?q=${q}&filter=${f}`),
|
||||||
key = f.split('_')[1];
|
key = f.split('_')[1];
|
||||||
|
|
||||||
|
next.value = json.nextpage;
|
||||||
|
|
||||||
results.setItem(key, json);
|
results.setItem(key, json);
|
||||||
console.log(json, key);
|
console.log(json, key);
|
||||||
};
|
};
|
||||||
|
@ -119,6 +154,14 @@ watch(
|
||||||
onUpdated(() => {
|
onUpdated(() => {
|
||||||
isSearch.value = /search/.test(location.pathname);
|
isSearch.value = /search/.test(location.pathname);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onActivated(() => {
|
||||||
|
window.addEventListener('scroll', getSearchNext);
|
||||||
|
});
|
||||||
|
|
||||||
|
onDeactivated(() => {
|
||||||
|
window.removeEventListener('scroll', getSearchNext);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -190,7 +233,7 @@ onUpdated(() => {
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="results.items.songs && results.items.songs.items[0]"
|
v-if="results.items.songs && results.items.songs.items[0]"
|
||||||
class="search-songs">
|
class="search-wrap">
|
||||||
<h2 v-if="!isSearch">{{ t('title.songs') }}</h2>
|
<h2 v-if="!isSearch">{{ t('title.songs') }}</h2>
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<template v-for="(song, index) in results.items.songs.items">
|
<template v-for="(song, index) in results.items.songs.items">
|
||||||
|
@ -236,7 +279,7 @@ onUpdated(() => {
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="results.items.albums && results.items.albums.items[0]"
|
v-if="results.items.albums && results.items.albums.items[0]"
|
||||||
class="search-albums">
|
class="search-wrap">
|
||||||
<h2 v-if="!isSearch">{{ t('title.albums') }}</h2>
|
<h2 v-if="!isSearch">{{ t('title.albums') }}</h2>
|
||||||
<div class="grid-3">
|
<div class="grid-3">
|
||||||
<template v-for="album in results.items.albums.items">
|
<template v-for="album in results.items.albums.items">
|
||||||
|
@ -251,9 +294,23 @@ onUpdated(() => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="results.items.playlists && results.items.playlists.items[0]"
|
||||||
|
class="search-wrap">
|
||||||
|
<h2>{{ t('title.playlists') }}</h2>
|
||||||
|
<div class="grid-3">
|
||||||
|
<AlbumItem
|
||||||
|
v-for="pl in results.items.playlists.items"
|
||||||
|
:author="pl.videos + ' Songs • ' + pl.uploaderName"
|
||||||
|
:name="pl.name"
|
||||||
|
:art="pl.thumbnail"
|
||||||
|
@open-album="results.getAlbum(pl.url)" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="results.items.singles && results.items.singles.items[0]"
|
v-if="results.items.singles && results.items.singles.items[0]"
|
||||||
class="search-albums">
|
class="search-wrap">
|
||||||
<h2>{{ t('title.singles') }}</h2>
|
<h2>{{ t('title.singles') }}</h2>
|
||||||
<div class="grid-3">
|
<div class="grid-3">
|
||||||
<template v-for="single in results.items.singles.items">
|
<template v-for="single in results.items.singles.items">
|
||||||
|
@ -272,7 +329,7 @@ onUpdated(() => {
|
||||||
results.items.recommendedArtists.items[0]) ||
|
results.items.recommendedArtists.items[0]) ||
|
||||||
(results.items.artists && results.items.artists.items[0])
|
(results.items.artists && results.items.artists.items[0])
|
||||||
"
|
"
|
||||||
class="search-artists">
|
class="search-wrap">
|
||||||
<h2 v-if="!isSearch">
|
<h2 v-if="!isSearch">
|
||||||
{{
|
{{
|
||||||
results.items.artists ? t('title.artists') : t('title.similar_artists')
|
results.items.artists ? t('title.artists') : t('title.similar_artists')
|
||||||
|
@ -296,18 +353,14 @@ onUpdated(() => {
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.search-albums,
|
.search-wrap {
|
||||||
.search-songs,
|
|
||||||
.search-artists {
|
|
||||||
place-items: start center;
|
place-items: start center;
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
}
|
}
|
||||||
.search-songs h2,
|
.search-wrap h2 {
|
||||||
.search-artists h2,
|
|
||||||
.search-albums h2 {
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
.search-artists {
|
.circle {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
:deep(.bi) {
|
:deep(.bi) {
|
||||||
|
@ -328,16 +381,17 @@ onUpdated(() => {
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
}
|
}
|
||||||
.filters {
|
.filters {
|
||||||
|
max-width: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
.filter {
|
.filter {
|
||||||
width: calc(80% / v-bind('filters.length'));
|
|
||||||
max-width: 200px;
|
max-width: 200px;
|
||||||
margin: 1rem;
|
margin: 0 0.25rem;
|
||||||
padding: 0.5rem;
|
padding: 0.5rem 1rem;
|
||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
border-radius: 0.25rem;
|
border-radius: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
|
@ -226,7 +226,9 @@ async function Like() {
|
||||||
|
|
||||||
<button
|
<button
|
||||||
id="btn-lyrics"
|
id="btn-lyrics"
|
||||||
class="bi bi-file-music clickable"
|
title="Lyrics"
|
||||||
|
aria-label="Lyrics"
|
||||||
|
class="bi bi-chat-square-quote clickable"
|
||||||
:data-active="player.state.lyrics"
|
:data-active="player.state.lyrics"
|
||||||
@click="player.toggle('lyrics')"></button>
|
@click="player.toggle('lyrics')"></button>
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
"singles": "Singles",
|
"singles": "Singles",
|
||||||
"artists": "Artists",
|
"artists": "Artists",
|
||||||
"similar_artists": "Similar Artists",
|
"similar_artists": "Similar Artists",
|
||||||
|
"playlists": "Playlists",
|
||||||
"moods": "Moods",
|
"moods": "Moods",
|
||||||
"genres": "Genres",
|
"genres": "Genres",
|
||||||
"featured": "Featured",
|
"featured": "Featured",
|
||||||
|
|
|
@ -24,9 +24,11 @@ export async function getJson(url) {
|
||||||
if (res && res.error) {
|
if (res && res.error) {
|
||||||
alert(
|
alert(
|
||||||
res.message
|
res.message
|
||||||
|
? res.message
|
||||||
.replaceAll('Video', 'Audio')
|
.replaceAll('Video', 'Audio')
|
||||||
.replaceAll('video', 'audio')
|
.replaceAll('video', 'audio')
|
||||||
.replaceAll('watched', 'heard'),
|
.replaceAll('watched', 'heard')
|
||||||
|
: res.error,
|
||||||
);
|
);
|
||||||
console.error(res.message);
|
console.error(res.message);
|
||||||
} else if (res) {
|
} else if (res) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue