feat: add some keyboard controls
This commit is contained in:
parent
1dfc0dc01e
commit
c5f7b1797b
@ -20,6 +20,7 @@
|
|||||||
</Link>
|
</Link>
|
||||||
{#if link.id === 'search' && $page.route.id === '/'}
|
{#if link.id === 'search' && $page.route.id === '/'}
|
||||||
<input
|
<input
|
||||||
|
id="search-input"
|
||||||
class="input rounded-none"
|
class="input rounded-none"
|
||||||
bind:value={$searchText}
|
bind:value={$searchText}
|
||||||
on:input={(ev) => search(ev.currentTarget.value)}
|
on:input={(ev) => search(ev.currentTarget.value)}
|
||||||
|
@ -72,18 +72,8 @@
|
|||||||
currentTime = ev.seekTime;
|
currentTime = ev.seekTime;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mediaSession.setActionHandler('seekbackward', () => {
|
mediaSession.setActionHandler('seekbackward', () => (currentTime -= 5));
|
||||||
currentTime -= 5;
|
mediaSession.setActionHandler('seekforward', () => (currentTime += 5));
|
||||||
if (currentTime < 0) {
|
|
||||||
currentTime = 0;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
mediaSession.setActionHandler('seekforward', () => {
|
|
||||||
currentTime += 5;
|
|
||||||
if (currentTime > duration) {
|
|
||||||
currentTime = duration;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}}
|
}}
|
||||||
on:timeupdate={(_) => {
|
on:timeupdate={(_) => {
|
||||||
navigator.mediaSession.setPositionState({ position: currentTime, duration });
|
navigator.mediaSession.setPositionState({ position: currentTime, duration });
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import IconRepeat from '~icons/mdi/repeat';
|
import IconRepeat from '~icons/mdi/repeat';
|
||||||
import IconRepeatOff from '~icons/mdi/repeat-off';
|
import IconRepeatOff from '~icons/mdi/repeat-off';
|
||||||
import IconRepeatOnce from '~icons/mdi/repeat-once';
|
import IconRepeatOnce from '~icons/mdi/repeat-once';
|
||||||
import { loop } from '../stores';
|
import { changeLoop, loop } from '../stores';
|
||||||
import { LoopKind } from '../types';
|
import { LoopKind } from '../types';
|
||||||
|
|
||||||
function getIcon(kind: LoopKind) {
|
function getIcon(kind: LoopKind) {
|
||||||
@ -16,20 +16,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeLoop() {
|
|
||||||
switch ($loop) {
|
|
||||||
case LoopKind.Always:
|
|
||||||
loop.set(LoopKind.Off);
|
|
||||||
break;
|
|
||||||
case LoopKind.Off:
|
|
||||||
loop.set(LoopKind.Once);
|
|
||||||
break;
|
|
||||||
case LoopKind.Once:
|
|
||||||
loop.set(LoopKind.Always);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function loopKindToString(kind: LoopKind) {
|
function loopKindToString(kind: LoopKind) {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case LoopKind.Off:
|
case LoopKind.Off:
|
||||||
|
@ -8,7 +8,10 @@
|
|||||||
import { AppShell, Toast, toastStore } from '@skeletonlabs/skeleton';
|
import { AppShell, Toast, toastStore } from '@skeletonlabs/skeleton';
|
||||||
import {
|
import {
|
||||||
address,
|
address,
|
||||||
|
changeLoop,
|
||||||
currentTrack,
|
currentTrack,
|
||||||
|
getAudioElement,
|
||||||
|
muted,
|
||||||
paused,
|
paused,
|
||||||
queuePosition,
|
queuePosition,
|
||||||
token,
|
token,
|
||||||
@ -81,10 +84,37 @@
|
|||||||
<svelte:window
|
<svelte:window
|
||||||
on:keydown={(event) => {
|
on:keydown={(event) => {
|
||||||
const tagName = document.activeElement?.tagName ?? '';
|
const tagName = document.activeElement?.tagName ?? '';
|
||||||
if (tagName !== 'INPUT' && event.code === 'Space') {
|
const actions = new Map([
|
||||||
|
['Space', () => ($paused = !$paused)],
|
||||||
|
['KeyL', changeLoop],
|
||||||
|
['KeyM', () => ($muted = !$muted)],
|
||||||
|
['KeyS', () => document.getElementById('search-input')?.focus()],
|
||||||
|
[
|
||||||
|
'ArrowLeft',
|
||||||
|
() => {
|
||||||
|
const audio = getAudioElement();
|
||||||
|
if (audio !== null) {
|
||||||
|
audio.currentTime -= 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'ArrowRight',
|
||||||
|
() => {
|
||||||
|
const audio = getAudioElement();
|
||||||
|
if (audio !== null) {
|
||||||
|
audio.currentTime += 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
if (tagName !== 'INPUT' && actions.has(event.code)) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
paused.set(!$paused);
|
const action = actions.get(event.code) ?? null;
|
||||||
|
if (action !== null) {
|
||||||
|
action();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -87,6 +87,20 @@ export const volume = writable<number>(1.0);
|
|||||||
export const muted = writable<boolean>(false);
|
export const muted = writable<boolean>(false);
|
||||||
export const loop = writable<LoopKind>(LoopKind.Off);
|
export const loop = writable<LoopKind>(LoopKind.Off);
|
||||||
|
|
||||||
|
export function changeLoop() {
|
||||||
|
switch (get(loop)) {
|
||||||
|
case LoopKind.Always:
|
||||||
|
loop.set(LoopKind.Off);
|
||||||
|
break;
|
||||||
|
case LoopKind.Off:
|
||||||
|
loop.set(LoopKind.Once);
|
||||||
|
break;
|
||||||
|
case LoopKind.Once:
|
||||||
|
loop.set(LoopKind.Always);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const searchText = writable<string>("");
|
export const searchText = writable<string>("");
|
||||||
|
|
||||||
export function search(q: string) {
|
export function search(q: string) {
|
||||||
|
Loading…
Reference in New Issue
Block a user