- Added a few basic keybindings
- Closes #142
This commit is contained in:
Shiny Nematoda 2023-09-22 12:32:41 +00:00
parent 212a0e6dd6
commit b023b67e04
10 changed files with 502 additions and 325 deletions

743
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -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"
} }
} }

View file

@ -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>!');

View file

@ -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);
}); });
} }
} }

View file

@ -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"

View file

@ -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() {

View file

@ -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);
} }
}); });

View file

@ -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;

View file

@ -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', () => {

View file

@ -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);