Skip to content

Commit

Permalink
feat: initial previous/next buttons support
Browse files Browse the repository at this point in the history
  • Loading branch information
Bellisario committed Apr 26, 2024
1 parent 399f273 commit daf33b5
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 31 deletions.
51 changes: 26 additions & 25 deletions src/components/PlayNextView/PlayNextController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
currentID,
albumsAddedToPlayNext,
favoritesPlayStatus,
playNextIndex,
} from '$lib/player';

import { wantPlay } from '$lib/wantPlay';
Expand Down Expand Up @@ -65,7 +66,7 @@ playNextList.subscribe((list) => {
&& get(currentID) === '' // 2.
)
playNext();

playNextWasEmpty = list.length === 0;
});

Expand All @@ -78,35 +79,35 @@ playNextList.subscribe((list) => {
favoritesPlayStatus.set(-1);
});

if ('mediaSession' in navigator) {
navigator.mediaSession.setActionHandler('previoustrack', () => {
// if there is no song in playNextList, return
if (get(playNextList).length === 0) return;
export function playPreviousSong() {
const index = get(playNextIndex);
// if there is no song in playNextList, return
if (index === null) return;

// find the index of the last Play Next song
const index = get(playNextList).findIndex((item) => {
return item.id === lastPlayNextID;
});
// if the index is the first index, it means the song is already the first song
if (index === 0) return;

// if the index is the first index, it means the song is the first song
if (index === 0) return;
// play the previous song
wantPlay(get(playNextList)[index - 1]);
}

// play the previous song
wantPlay(get(playNextList)[index - 1]);
});
navigator.mediaSession.setActionHandler('nexttrack', () => {
// if there is no song in playNextList, return
if (get(playNextList).length === 0) return;
export function playNextSong() {
const index = get(playNextIndex);
// if there is no song in playNextList, return
if (index === null) return;

// find the index of the last Play Next song
const index = get(playNextList).findIndex((item) => {
return item.id === lastPlayNextID;
});
// if the index is the last index, it means the song is the last song
if (index === get(playNextList).length - 1) return;

// if the index is the last index, it means the song is the last song
if (index === get(playNextList).length - 1) return;
// play the next song
wantPlay(get(playNextList)[index + 1]);
}

// play the next song
wantPlay(get(playNextList)[index + 1]);
if ('mediaSession' in navigator) {
navigator.mediaSession.setActionHandler('previoustrack', () => {
playPreviousSong();
});
navigator.mediaSession.setActionHandler('nexttrack', () => {
playNextSong();
});
}
77 changes: 72 additions & 5 deletions src/components/PlayerControls/PlayerControls.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,20 @@
artist,
poster,
volume,
playNextList,
} from '$lib/player';
import { play, pause } from '$lib/AudioPlayer.svelte';
import { fade } from 'svelte/transition';
import clickOutside from '$lib/clickOutside';
import { tweened } from 'svelte/motion';
import { cubicOut } from 'svelte/easing';
import {
playNextSong,
playPreviousSong,
} from '$components/PlayNextView/PlayNextController';
let smallScreen = false;
window.addEventListener('resize', () => {
Expand All @@ -32,6 +40,18 @@
let resetStatus: 'none' | 'working' | 'done' = 'none';
let resetTimeout: NodeJS.Timeout;
// expressed in REMs
let playerButtonsWidth = tweened(1.75, {
duration: 300,
easing: cubicOut,
});
playNextList.subscribe((val) => {
if (val.length === 0) return playerButtonsWidth.set(1.75);
playerButtonsWidth.set(1.75 /*rem*/ * 3 /* buttons*/ + 2 /*rem for gap*/);
});
paused.subscribe(() => {
if ('mediaSession' in navigator) {
navigator.mediaSession.metadata = new MediaMetadata({
Expand Down Expand Up @@ -177,10 +197,26 @@
: 'Keep pressing to reset playing time...'}
</div>
{/if}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div class="player__play-pause" on:click={toggle}>
<div class="play-pause__icon" class:pause={!$paused} />
<div class="player__buttons" style="--buttons-width:{$playerButtonsWidth}rem">
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div class="player__previous-button" on:click={playPreviousSong}>
<svg class="double-arrow-icon">
<use xlink:href="#double-arrow" />
</svg>
</div>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div class="player__play-pause" on:click={toggle}>
<div class="play-pause__icon" class:pause={!$paused} />
</div>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div class="player__next-button" on:click={playNextSong}>
<svg class="double-arrow-icon">
<use xlink:href="#double-arrow" />
</svg>
</div>
</div>
<Range />
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
Expand Down Expand Up @@ -216,6 +252,18 @@
d="M6 7l8-5v20l-8-5v-10zm-6 10h4v-10h-4v10zm20.264-13.264l-1.497 1.497c1.847 1.783 2.983 4.157 2.983 6.767 0 2.61-1.135 4.984-2.983 6.766l1.498 1.498c2.305-2.153 3.735-5.055 3.735-8.264s-1.43-6.11-3.736-8.264zm-.489 8.264c0-2.084-.915-3.967-2.384-5.391l-1.503 1.503c1.011 1.049 1.637 2.401 1.637 3.888 0 1.488-.623 2.841-1.634 3.891l1.503 1.503c1.468-1.424 2.381-3.309 2.381-5.394z"
/>
</symbol>
<symbol id="double-arrow" viewBox="0 0 24 24">
<g id="layer1" transform="translate(-1.2345222e-7,-2.9999998)">
<path
d="m 18.292605,7.7669902 -7.574831,4.3733308 0,-8.7466618 z"
transform="matrix(1.9802421,0,0,2.057928,-12.223787,-3.9839066)"
/>
<path
d="m 18.292605,7.7669902 -7.574831,4.3733308 0,-8.7466618 z"
transform="matrix(1.9802421,0,0,2.057928,-21.223787,-3.9839066)"
/>
</g>
</symbol>
</svg>

<style>
Expand All @@ -240,6 +288,17 @@
color: var(--theme-color);
font-weight: 800;
}
.player__buttons {
display: flex;
align-items: center;
justify-content: center;
gap: 1rem;
overflow: hidden;
height: auto;
animation: width 250ms ease;
width: var(--buttons-width, 1.75rem);
}
.player__play-pause {
display: inline-block;
position: relative;
Expand Down Expand Up @@ -281,13 +340,21 @@
5% 0%
);
}
.volume-icon {
.player__previous-button {
transform: scaleX(-1);
}
.volume-icon,
.double-arrow-icon {
display: inline-block;
width: 1.75em;
height: 1.75em;
fill: var(--theme-color);
vertical-align: middle;
}
.double-arrow-icon {
/* quick alignment fix */
transform: translateY(0.2rem);
}
.player__volume {
position: relative;
isolation: isolate;
Expand Down
14 changes: 13 additions & 1 deletion src/lib/player.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { get, writable } from 'svelte/store';
import { derived, get, writable } from 'svelte/store';
import type { FavoriteStore } from '$types/FavoritesStore';
import { type MenuEntry } from '$types/MenuEntry';

Expand All @@ -25,6 +25,18 @@ export const menuEntries = writable<MenuEntry[]>([])

export const playNextList = writable<FavoriteStore[]>([]);

export const playNextIndex = derived([playNextList, currentID], ([$playNextList, $currentID]) => {
// if there is no song in playNextList, return
if ($playNextList.length === 0) return null;

// find the index of the last Play Next song
const index = $playNextList.findIndex((item) => {
return item.id === $currentID;
});

return index;
});

export const currentSearchType = writable<number>(0);

interface AlbumsAddedToPlayNext {
Expand Down

0 comments on commit daf33b5

Please sign in to comment.