mirror of
https://codeberg.org/Hyperpipe/Hyperpipe
synced 2025-06-27 20:58:01 +02:00
parent
212a0e6dd6
commit
b023b67e04
10 changed files with 502 additions and 325 deletions
743
package-lock.json
generated
743
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -10,12 +10,12 @@
|
||||||
"lint": "prettier --check ."
|
"lint": "prettier --check ."
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bootstrap-icons": "^1.10.5",
|
"bootstrap-icons": "^1.11.1",
|
||||||
"dompurify": "^3.0.5",
|
"dompurify": "^3.0.5",
|
||||||
"mux.js": "^6.3.0",
|
"mux.js": "^6.3.0",
|
||||||
"peerjs": "^1.4.7",
|
"peerjs": "^1.5.0",
|
||||||
"pinia": "^2.1.6",
|
"pinia": "^2.1.6",
|
||||||
"shaka-player": "^4.4.0",
|
"shaka-player": "^4.4.2",
|
||||||
"sortablejs": "^1.15.0",
|
"sortablejs": "^1.15.0",
|
||||||
"vue": "^3.2.38"
|
"vue": "^3.2.38"
|
||||||
},
|
},
|
||||||
|
@ -23,6 +23,6 @@
|
||||||
"@vitejs/plugin-vue": "^4.3.4",
|
"@vitejs/plugin-vue": "^4.3.4",
|
||||||
"prettier": "^3.0.3",
|
"prettier": "^3.0.3",
|
||||||
"vite": "^4.4.9",
|
"vite": "^4.4.9",
|
||||||
"vite-plugin-pwa": "^0.16.4"
|
"vite-plugin-pwa": "^0.16.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
26
src/App.vue
26
src/App.vue
|
@ -93,6 +93,31 @@ function parseUrl() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setupKeys() {
|
||||||
|
window.addEventListener('keydown', e => {
|
||||||
|
if (
|
||||||
|
!e.shiftKey ||
|
||||||
|
e.repeat ||
|
||||||
|
'string' == typeof e.target.value
|
||||||
|
) return
|
||||||
|
|
||||||
|
switch (e.code) {
|
||||||
|
case 'Space':
|
||||||
|
player.toggle('play')
|
||||||
|
break;
|
||||||
|
case 'Slash':
|
||||||
|
nav.show()
|
||||||
|
break;
|
||||||
|
case 'KeyN':
|
||||||
|
data.nextTrack()
|
||||||
|
break;
|
||||||
|
case 'KeyP':
|
||||||
|
data.prevTrack()
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
function playThis(t) {
|
function playThis(t) {
|
||||||
const i = data.state.urls.indexOf(t);
|
const i = data.state.urls.indexOf(t);
|
||||||
data.play(data.state.urls[i]);
|
data.play(data.state.urls[i]);
|
||||||
|
@ -134,6 +159,7 @@ onMounted(() => {
|
||||||
/* Setup IndexedDB for storing custom playlists */
|
/* Setup IndexedDB for storing custom playlists */
|
||||||
useSetupDB();
|
useSetupDB();
|
||||||
|
|
||||||
|
setupKeys();
|
||||||
parseUrl();
|
parseUrl();
|
||||||
|
|
||||||
console.log('Mounted <App>!');
|
console.log('Mounted <App>!');
|
||||||
|
|
|
@ -10,7 +10,8 @@ import { useAlert } from '@/stores/misc';
|
||||||
|
|
||||||
const player = usePlayer(),
|
const player = usePlayer(),
|
||||||
data = useData(),
|
data = useData(),
|
||||||
store = useStore();
|
store = useStore(),
|
||||||
|
a = useAlert();
|
||||||
|
|
||||||
const audio = ref(null);
|
const audio = ref(null);
|
||||||
|
|
||||||
|
@ -61,7 +62,7 @@ async function Stream() {
|
||||||
window.offline = new shaka.offline.Storage(audioPlayer);
|
window.offline = new shaka.offline.Storage(audioPlayer);
|
||||||
window.offline.configure({
|
window.offline.configure({
|
||||||
offline: {
|
offline: {
|
||||||
progressCallback: (data, prog) => console.log(data, prog),
|
progressCallback: ({ appMetadata: { title, artist } }, prog) => a.add(`${title} by ${artist}: ${Math.floor(prog*100)}%`),
|
||||||
trackSelectionCallback: tracks => [
|
trackSelectionCallback: tracks => [
|
||||||
tracks
|
tracks
|
||||||
.sort((a, b) => a.bandwidth - b.bandwidth)
|
.sort((a, b) => a.bandwidth - b.bandwidth)
|
||||||
|
@ -112,7 +113,7 @@ async function Stream() {
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
useAlert.add('error: ' + e.code);
|
a.add('Error: ' + err.code);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +1,38 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
import { useNav, useI18n } from '@/stores/misc.js';
|
import { useNav, useI18n } from '@/stores/misc.js';
|
||||||
|
|
||||||
const { t } = useI18n(),
|
const { t } = useI18n(),
|
||||||
show = ref(false),
|
show = ref(false),
|
||||||
nav = useNav();
|
nav = useNav(),
|
||||||
|
searchEl = ref(null);
|
||||||
|
|
||||||
function search(e) {
|
function search(e) {
|
||||||
nav.state.search = e.target.value;
|
nav.state.search = e.target.value;
|
||||||
nav.state.page = 'home';
|
nav.state.page = 'home';
|
||||||
e.target.blur();
|
e.target.blur();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => nav.state.show,
|
||||||
|
e => {
|
||||||
|
if (e === true) setTimeout(() => searchEl.value.focus(), 0)
|
||||||
|
}
|
||||||
|
)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<button
|
<button
|
||||||
class="bi bi-search popup-wrap"
|
class="bi bi-search popup-wrap"
|
||||||
@mouseenter="show = true"
|
@mouseenter="nav.state.show = true"
|
||||||
@mouseleave="show = false"
|
@mouseleave="nav.state.show = false"
|
||||||
@keydown.enter="show = !show">
|
@keydown.enter="nav.show()">
|
||||||
<Transition name="fade">
|
<Transition name="fade">
|
||||||
<div v-show="show" class="popup">
|
<div v-show="nav.state.show" class="popup">
|
||||||
<input
|
<input
|
||||||
type="search"
|
type="search"
|
||||||
|
ref="searchEl"
|
||||||
|
name="searchEl"
|
||||||
aria-label="Search Input"
|
aria-label="Search Input"
|
||||||
:placeholder="t('title.search') + '...'"
|
:placeholder="t('title.search') + '...'"
|
||||||
@change="search"
|
@change="search"
|
||||||
|
|
|
@ -9,12 +9,13 @@ import {
|
||||||
} from '@/scripts/fetch.js';
|
} from '@/scripts/fetch.js';
|
||||||
|
|
||||||
import { useData, usePlayer } from '@/stores/player.js';
|
import { useData, usePlayer } from '@/stores/player.js';
|
||||||
import { useI18n } from '@/stores/misc.js';
|
import { useI18n, useAlert } from '@/stores/misc.js';
|
||||||
|
|
||||||
const { t } = useI18n(),
|
const { t } = useI18n(),
|
||||||
data = useData(),
|
data = useData(),
|
||||||
player = usePlayer(),
|
player = usePlayer(),
|
||||||
store = useStore();
|
store = useStore(),
|
||||||
|
a = useAlert();
|
||||||
|
|
||||||
const showme = reactive({
|
const showme = reactive({
|
||||||
menu: false,
|
menu: false,
|
||||||
|
@ -44,8 +45,11 @@ async function Offline() {
|
||||||
url: data.state.url,
|
url: data.state.url,
|
||||||
artist: data.state.artist,
|
artist: data.state.artist,
|
||||||
artistUrl: data.state.artistUrl,
|
artistUrl: data.state.artistUrl,
|
||||||
|
}).promise.catch(e => {
|
||||||
|
console.error(e)
|
||||||
|
a.add('Error: ' + e.code)
|
||||||
});
|
});
|
||||||
} else console.error('no offline storage found');
|
} else a.add('offline storage not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
async function Like() {
|
async function Like() {
|
||||||
|
|
|
@ -12,7 +12,7 @@ export function useDash(streams, len) {
|
||||||
else {
|
else {
|
||||||
mimeTypes.push(stream.mimeType);
|
mimeTypes.push(stream.mimeType);
|
||||||
mimes.push([]);
|
mimes.push([]);
|
||||||
mimes.at(-1).push(stream);
|
mimes[mimeTypes.length - 1].push(stream);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ function useElems(json) {
|
||||||
export function useXML(json) {
|
export function useXML(json) {
|
||||||
json = JSON.parse(JSON.stringify(json));
|
json = JSON.parse(JSON.stringify(json));
|
||||||
|
|
||||||
let xml = '<?xml version="1.0" encoding="utf-8" ?>';
|
let xml = '<?xml version="1.0" encoding="utf-8"?>';
|
||||||
xml += useElems(json);
|
xml += useElems(json);
|
||||||
|
|
||||||
return xml;
|
return xml;
|
||||||
|
|
|
@ -139,9 +139,12 @@ export const useNav = defineStore('nav', () => {
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
search: '',
|
search: '',
|
||||||
page: 'home',
|
page: 'home',
|
||||||
|
show: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
return { state };
|
const show = () => state.show = !state.show
|
||||||
|
|
||||||
|
return { state, show };
|
||||||
});
|
});
|
||||||
|
|
||||||
export const useI18n = defineStore('i18n', () => {
|
export const useI18n = defineStore('i18n', () => {
|
||||||
|
|
|
@ -95,7 +95,7 @@ export const useData = defineStore('data', () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function playNext(u) {
|
function playNext() {
|
||||||
const i = state.urls.findIndex(s => s.url === state.url);
|
const i = state.urls.findIndex(s => s.url === state.url);
|
||||||
|
|
||||||
if (player.state.loop == 2) getSong(state.url);
|
if (player.state.loop == 2) getSong(state.url);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue