From 025a69f344a11c8875409382d0042b4bd84827ff Mon Sep 17 00:00:00 2001 From: sleepyfran Date: Thu, 12 Sep 2024 01:35:05 +0200 Subject: [PATCH] Implement skip/previous --- packages/components/player/src/player.ts | 29 +++++++++++++--- packages/services/player/src/player.ts | 42 ++++++++++++++++++++++-- 2 files changed, 65 insertions(+), 6 deletions(-) diff --git a/packages/components/player/src/player.ts b/packages/components/player/src/player.ts index 9f1e233..7ee29d1 100644 --- a/packages/components/player/src/player.ts +++ b/packages/components/player/src/player.ts @@ -15,6 +15,8 @@ export class EchoPlayer extends LitElement { this, () => PlayerService.togglePlayback, ); + private _previousTrack = new EffectFn(this, () => PlayerService.previous); + private _skipTrack = new EffectFn(this, () => PlayerService.skip); render() { return this._player.render({ @@ -30,7 +32,10 @@ export class EchoPlayer extends LitElement { )}
- - +

Previously played tracks: - ${JSON.stringify(player.previouslyPlayedTracks)} + ${player.previouslyPlayedTracks.map((t) => t.name).join(", ")} +

+

+ Coming up tracks: + ${player.comingUpTracks.map((t) => t.name).join(", ")}

-

Coming up tracks: ${player.comingUpTracks}

`, }); @@ -67,6 +80,14 @@ export class EchoPlayer extends LitElement { private _onTogglePlayback() { this._togglePlayback.run({}); } + + private _onPreviousTrack() { + this._previousTrack.run({}); + } + + private _onSkipTrack() { + this._skipTrack.run({}); + } } declare global { diff --git a/packages/services/player/src/player.ts b/packages/services/player/src/player.ts index 76dd8e8..113f90e 100644 --- a/packages/services/player/src/player.ts +++ b/packages/services/player/src/player.ts @@ -13,6 +13,7 @@ import { type Track, } from "@echo/core-types"; import { + Array, Data, Effect, Exit, @@ -86,8 +87,45 @@ const makePlayer = Effect.gen(function* () { yield* mediaPlayer.value.player.togglePlayback; }), - previous: Effect.void, - skip: Effect.void, + previous: Effect.gen(function* () { + // TODO: Refactor this to avoid duplication with other play commands. + const { previouslyPlayedTracks, comingUpTracks, status } = + yield* Ref.get(state); + const lastPlayedTrack = Array.last(previouslyPlayedTracks); + if (Option.isNone(lastPlayedTrack)) { + yield* Effect.logWarning( + "Attempted to play previous track, but the previous queue is empty", + ); + return; + } + + const { provider, player } = yield* resolveDependenciesForTrack( + providerCache, + lastPlayedTrack.value, + ); + + const currentTrack = Match.value(status).pipe( + Match.tag("Playing", ({ track }) => [track]), + Match.tag("Paused", ({ track }) => [track]), + Match.tag("Stopped", () => []), + Match.exhaustive, + ); + const previousWithoutLast = Array.dropRight(previouslyPlayedTracks, 1); + const comingUpWithCurrent = [...currentTrack, ...comingUpTracks]; + + yield* playTrack(provider, player, lastPlayedTrack.value); + yield* commandQueue.offer( + UpdateState({ + updateFn: (state) => ({ + ...state, + status: Playing({ track: lastPlayedTrack.value }), + previouslyPlayedTracks: previousWithoutLast, + comingUpTracks: comingUpWithCurrent, + }), + }), + ); + }), + skip: commandQueue.offer(NextTrack()), observe: state, }); });