mirror of
https://codeberg.org/Hyperpipe/Hyperpipe
synced 2025-06-27 20:58:01 +02:00
parent
7e88b8e73a
commit
cdded78de8
10 changed files with 653 additions and 598 deletions
1025
package-lock.json
generated
1025
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -14,15 +14,15 @@
|
|||
"dompurify": "^3.0.6",
|
||||
"mux.js": "^6.3.0",
|
||||
"peerjs": "^1.5.1",
|
||||
"pinia": "^2.1.6",
|
||||
"pinia": "^2.1.7",
|
||||
"shaka-player": "^4.5.0",
|
||||
"sortablejs": "^1.15.0",
|
||||
"vue": "^3.2.38"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-vue": "^4.4.0",
|
||||
"@vitejs/plugin-vue": "^4.4.1",
|
||||
"prettier": "^3.0.3",
|
||||
"vite": "^4.4.11",
|
||||
"vite-plugin-pwa": "^0.16.5"
|
||||
"vite": "^4.5.0",
|
||||
"vite-plugin-pwa": "^0.16.7"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -204,6 +204,7 @@ button {
|
|||
background: transparent;
|
||||
color: var(--color-text);
|
||||
appearance: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
button:focus {
|
||||
outline: none;
|
||||
|
@ -398,6 +399,23 @@ img {
|
|||
}
|
||||
}
|
||||
|
||||
/* Table */
|
||||
th,
|
||||
td {
|
||||
margin: 0.25rem 0.5rem;
|
||||
padding: 0.5rem 0.75rem;
|
||||
border-radius: 0.125rem;
|
||||
background-color: var(--color-background-mute);
|
||||
}
|
||||
th {
|
||||
font-weight: bolder;
|
||||
}
|
||||
td {
|
||||
text-align: center;
|
||||
max-width: 40vw;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
/* Animations */
|
||||
.bars-wrap {
|
||||
flex-shrink: 0;
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
{
|
||||
"date": "2023-10-08"
|
||||
"date": "2023-11-12"
|
||||
}
|
||||
|
|
|
@ -488,7 +488,9 @@ onMounted(async () => {
|
|||
</p>
|
||||
</form>
|
||||
|
||||
<button v-if="auth" @click="Logout" class="logout textbox">{{ t('title.logout') }}</button>
|
||||
<button v-if="auth" @click="Logout" class="logout textbox">
|
||||
{{ t('title.logout') }}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ function set(page) {
|
|||
@click="set('library')"
|
||||
@keydown.enter="set('library')"></span>
|
||||
<span
|
||||
role="button"
|
||||
role="menuitem"
|
||||
tabindex="0"
|
||||
class="nav-ico bi bi-gear clickable"
|
||||
:data-active="nav.state.page == 'prefs'"
|
||||
|
@ -104,6 +104,9 @@ h1.bi svg {
|
|||
text-align: center;
|
||||
margin-left: auto;
|
||||
}
|
||||
[role='menuitem'] {
|
||||
cursor: pointer;
|
||||
}
|
||||
.nav-ico {
|
||||
margin: 0 0.5rem;
|
||||
}
|
||||
|
|
|
@ -29,67 +29,63 @@ function audioCanPlay() {
|
|||
|
||||
async function Stream() {
|
||||
const res = player.state,
|
||||
shaka = import('shaka-player/dist/shaka-player.compiled.js');
|
||||
shaka = await import('shaka-player/dist/shaka-player.compiled.js').then(
|
||||
mod => mod.default,
|
||||
);
|
||||
|
||||
const { url, mime } = await useManifest(res);
|
||||
|
||||
if (!window.audioPlayer) {
|
||||
shaka
|
||||
.then(shaka => shaka.default)
|
||||
.then(shaka => {
|
||||
shaka.polyfill.installAll();
|
||||
shaka.polyfill.installAll();
|
||||
|
||||
if (shaka.Player.isBrowserSupported()) {
|
||||
const audioPlayer = new shaka.Player(audio.value),
|
||||
codecs = store.getItem('codec');
|
||||
if (shaka.Player.isBrowserSupported()) {
|
||||
const audioPlayer = new shaka.Player(audio.value),
|
||||
codecs = store.getItem('codec');
|
||||
|
||||
audioPlayer
|
||||
.getNetworkingEngine()
|
||||
.registerRequestFilter((_type, req) => {
|
||||
const headers = req.headers;
|
||||
audioPlayer.getNetworkingEngine().registerRequestFilter((_type, req) => {
|
||||
const headers = req.headers;
|
||||
|
||||
let url = new URL(req.uris[0]);
|
||||
let url = new URL(req.uris[0]);
|
||||
|
||||
if (url.pathname.indexOf('/videoplayback') > -1) {
|
||||
if (headers.Range) {
|
||||
url.searchParams.set('range', headers.Range.split('=')[1]);
|
||||
req.headers = {};
|
||||
req.uris[0] = url.toString();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
window.offline = new shaka.offline.Storage(audioPlayer);
|
||||
window.offline.configure({
|
||||
offline: {
|
||||
progressCallback: ({ appMetadata: { title, artist } }, prog) =>
|
||||
a.add(`${title} by ${artist}: ${Math.floor(prog * 100)}%`),
|
||||
trackSelectionCallback: tracks => [
|
||||
tracks
|
||||
.sort((a, b) => a.bandwidth - b.bandwidth)
|
||||
.find(i => i.type == 'variant'),
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
audioPlayer.configure({
|
||||
preferredAudioCodecs: codecs ? codecs.split(':') : ['opus', 'mp4a'],
|
||||
manifest: {
|
||||
disableVideo: true,
|
||||
},
|
||||
streaming: {
|
||||
segmentPrefetchLimit: 2,
|
||||
},
|
||||
});
|
||||
|
||||
window.audioPlayer = audioPlayer;
|
||||
if (url.pathname.indexOf('/videoplayback') > -1) {
|
||||
if (headers.Range) {
|
||||
url.searchParams.set('range', headers.Range.split('=')[1]);
|
||||
req.headers = {};
|
||||
req.uris[0] = url.toString();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
window.offline = new shaka.offline.Storage(audioPlayer);
|
||||
window.offline.configure({
|
||||
offline: {
|
||||
progressCallback: ({ appMetadata: { title, artist } }, prog) =>
|
||||
a.add(`${title} by ${artist}: ${Math.floor(prog * 100)}%`),
|
||||
trackSelectionCallback: tracks => [
|
||||
tracks
|
||||
.sort((a, b) => a.bandwidth - b.bandwidth)
|
||||
.find(i => i.type == 'variant'),
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
audioPlayer.configure({
|
||||
preferredAudioCodecs: codecs ? codecs.split(':') : ['opus', 'mp4a'],
|
||||
manifest: {
|
||||
disableVideo: true,
|
||||
},
|
||||
streaming: {
|
||||
segmentPrefetchLimit: 2,
|
||||
},
|
||||
});
|
||||
|
||||
window.audioPlayer = audioPlayer;
|
||||
}
|
||||
}
|
||||
|
||||
const quality = store.getItem('quality');
|
||||
|
||||
if (url) {
|
||||
if (url)
|
||||
window.audioPlayer
|
||||
.load(url, 0, mime)
|
||||
.then(() => {
|
||||
|
@ -116,7 +112,6 @@ async function Stream() {
|
|||
console.error(err);
|
||||
a.add('Error: ' + err.code);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function destroy() {
|
||||
|
|
|
@ -46,11 +46,10 @@ const getRestoreUrl = () => {
|
|||
Object.keys(window.localStorage).forEach(key => {
|
||||
params.set(key, window.localStorage.getItem(key));
|
||||
});
|
||||
restoreUrl.value = window.location.origin + '/restore/?' + params;
|
||||
params.size == 0 ||
|
||||
(restoreUrl.value = window.location.origin + '/restore/?' + params);
|
||||
};
|
||||
|
||||
getRestoreUrl();
|
||||
|
||||
function getBool(val) {
|
||||
return 'bi ' + (val ? 'bi-check2' : 'bi-x-lg');
|
||||
}
|
||||
|
@ -61,6 +60,7 @@ function getStore(key) {
|
|||
|
||||
function setStore(key, value) {
|
||||
store.setItem(key, value);
|
||||
getRestoreUrl();
|
||||
}
|
||||
|
||||
function getTheme() {
|
||||
|
@ -125,6 +125,7 @@ const verifyApi = computed(() =>
|
|||
);
|
||||
|
||||
onMounted(() => {
|
||||
getRestoreUrl();
|
||||
getStoreBool('next', next, true);
|
||||
getStoreBool('compact', compact, false);
|
||||
getStoreBool('prm', prm, false);
|
||||
|
@ -377,8 +378,10 @@ onMounted(() => {
|
|||
</table>
|
||||
</div>
|
||||
|
||||
<h2>{{ t('title.restore_prefs') }}</h2>
|
||||
<a :href="restoreUrl">{{ restoreUrl }}</a>
|
||||
<template v-if="restoreUrl">
|
||||
<h2>{{ t('title.restore_prefs') }}</h2>
|
||||
<a :href="restoreUrl" class="restore">{{ restoreUrl }}</a>
|
||||
</template>
|
||||
|
||||
<footer>
|
||||
{{ date }}
|
||||
|
@ -402,8 +405,18 @@ h2 {
|
|||
h2,
|
||||
h3,
|
||||
label,
|
||||
footer {
|
||||
footer,
|
||||
.restore {
|
||||
text-align: center;
|
||||
word-break: break-word;
|
||||
}
|
||||
.restore {
|
||||
padding: 0.5rem;
|
||||
margin: 1rem 0;
|
||||
background: var(--color-background-mute);
|
||||
border-radius: 0.25rem;
|
||||
font-weight: bold;
|
||||
letter-spacing: 0.05rem;
|
||||
}
|
||||
input[type='number'] {
|
||||
width: 4.5rem;
|
||||
|
@ -445,21 +458,6 @@ label[for^='pref-chk'] {
|
|||
table {
|
||||
width: 100%;
|
||||
}
|
||||
th,
|
||||
td {
|
||||
margin: 0.25rem 0.5rem;
|
||||
padding: 0.5rem 0.75rem;
|
||||
border-radius: 0.125rem;
|
||||
background-color: var(--color-background-mute);
|
||||
}
|
||||
th {
|
||||
font-weight: bolder;
|
||||
}
|
||||
td {
|
||||
text-align: center;
|
||||
max-width: 40vw;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
td.bi {
|
||||
color: indianred;
|
||||
font-size: 1.25rem;
|
||||
|
@ -468,7 +466,7 @@ td.bi[data-active='true'] {
|
|||
color: var(--color-foreground);
|
||||
}
|
||||
footer {
|
||||
margin-bottom: 2rem;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
footer .bi::before {
|
||||
font-size: 1.75rem;
|
||||
|
|
|
@ -4,23 +4,18 @@ import { ref, onMounted } from 'vue';
|
|||
|
||||
const { t } = useI18n();
|
||||
|
||||
const urlParamKeys = ref([]),
|
||||
urlParamValues = ref([]),
|
||||
const params = ref({}),
|
||||
restorePrefs = () => {
|
||||
for (let i = 0; i < urlParamKeys.value.length; i++) {
|
||||
window.localStorage.setItem(
|
||||
urlParamKeys.value[i],
|
||||
urlParamValues.value[i],
|
||||
);
|
||||
}
|
||||
for (const i in params.value)
|
||||
window.localStorage.setItem(i, params.value[i]);
|
||||
|
||||
window.location.href = '/';
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
urlParams.forEach((val, key) => {
|
||||
urlParamKeys.value.push(key);
|
||||
urlParamValues.value.push(val);
|
||||
params.value[key] = val
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
@ -28,16 +23,18 @@ onMounted(() => {
|
|||
<template>
|
||||
<h2>{{ t('title.restore_prefs') }}</h2>
|
||||
|
||||
<div class="table">
|
||||
<span v-for="(key, index) in urlParamKeys">
|
||||
<div class="table-row">
|
||||
<span>{{ key }}</span>
|
||||
<hr />
|
||||
<span>{{ urlParamValues[index] }}</span>
|
||||
</div>
|
||||
<hr />
|
||||
</span>
|
||||
</div>
|
||||
<table>
|
||||
<thead>
|
||||
<th>Key</th>
|
||||
<th>Value</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(val, key) in params">
|
||||
<td>{{ key }}</td>
|
||||
<td>{{ val }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<button @click="restorePrefs" class="input">
|
||||
{{ t('title.restore_prefs') }}
|
||||
|
@ -49,25 +46,11 @@ h2 {
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
.table {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
table {
|
||||
width: 100%;
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.table-row {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
padding: 0.5rem 0;
|
||||
}
|
||||
|
||||
.table-row > span {
|
||||
td {
|
||||
width: 50%;
|
||||
padding-left: 0.5rem;
|
||||
}
|
||||
|
||||
button {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -157,6 +157,7 @@ onMounted(() => {
|
|||
.card {
|
||||
margin: 1rem 0;
|
||||
justify-content: initial;
|
||||
cursor: pointer;
|
||||
}
|
||||
.song h4 {
|
||||
overflow-wrap: anywhere;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue