rework player events to use properties object instead of flat value

This commit is contained in:
jeffvli
2025-11-02 18:52:59 -08:00
parent a980a8de0b
commit f30a706eef
3 changed files with 61 additions and 53 deletions
@@ -17,26 +17,32 @@ export interface PlayerEvents {
} }
export interface PlayerEventsCallbacks { export interface PlayerEventsCallbacks {
onCurrentTrackChange?: ( onCurrentSongChange?: (
track: { index: number; track: QueueSong | undefined }, properties: { index: number; song: QueueSong | undefined },
prevTrack: { index: number; track: QueueSong | undefined }, prev: { index: number; song: QueueSong | undefined },
) => void; ) => void;
onPlayerMute?: (muted: boolean, prevMuted: boolean) => void; onPlayerMute?: (properties: { muted: boolean }, prev: { muted: boolean }) => void;
onPlayerProgress?: (timestamp: number, prevTimestamp: number) => void; onPlayerProgress?: (properties: { timestamp: number }, prev: { timestamp: number }) => void;
onPlayerQueueChange?: (queue: QueueData, prevQueue: QueueData) => void; onPlayerQueueChange?: (queue: QueueData, prev: QueueData) => void;
onPlayerSeek?: (seconds: number, prevSeconds: number) => void; onPlayerSeek?: (properties: { seconds: number }, prev: { seconds: number }) => void;
onPlayerSeekToTimestamp?: (timestamp: number, prevTimestamp: number) => void; onPlayerSeekToTimestamp?: (
onPlayerSpeed?: (speed: number, prevSpeed: number) => void; properties: { timestamp: number },
onPlayerStatus?: (status: PlayerStatus, prevStatus: PlayerStatus) => void; prev: { timestamp: number },
onPlayerVolume?: (volume: number, prevVolume: number) => void; ) => void;
onPlayerSpeed?: (properties: { speed: number }, prev: { speed: number }) => void;
onPlayerStatus?: (
properties: { song: QueueSong | undefined; status: PlayerStatus },
prev: { song: QueueSong | undefined; status: PlayerStatus },
) => void;
onPlayerVolume?: (properties: { volume: number }, prev: { volume: number }) => void;
} }
export function createPlayerEvents(callbacks: PlayerEventsCallbacks): PlayerEvents { export function createPlayerEvents(callbacks: PlayerEventsCallbacks): PlayerEvents {
const unsubscribers: (() => void)[] = []; const unsubscribers: (() => void)[] = [];
// Subscribe to current track changes // Subscribe to current track changes
if (callbacks.onCurrentTrackChange) { if (callbacks.onCurrentSongChange) {
const unsubscribe = subscribeCurrentTrack(callbacks.onCurrentTrackChange); const unsubscribe = subscribeCurrentTrack(callbacks.onCurrentSongChange);
unsubscribers.push(unsubscribe); unsubscribers.push(unsubscribe);
} }
@@ -1,25 +1,11 @@
import { useEffect } from 'react'; import { useEffect } from 'react';
import { createPlayerEvents } from '/@/renderer/components/audio-player/listener/player-events'; import {
import { QueueData } from '/@/renderer/store'; createPlayerEvents,
import { QueueSong } from '/@/shared/types/domain-types'; PlayerEventsCallbacks,
import { PlayerStatus } from '/@/shared/types/types'; } from '/@/renderer/components/audio-player/listener/player-events';
export interface PlayerEvents { export function usePlayerEvents(callbacks: PlayerEventsCallbacks, deps: React.DependencyList) {
onCurrentTrackChange?: (
track: { index: number; track: QueueSong | undefined },
prevTrack: { index: number; track: QueueSong | undefined },
) => void;
onPlayerMute?: (muted: boolean, prevMuted: boolean) => void;
onPlayerProgress?: (timestamp: number, prevTimestamp: number) => void;
onPlayerQueueChange?: (queue: QueueData, prevQueue: QueueData) => void;
onPlayerSeekToTimestamp?: (timestamp: number, prevTimestamp: number) => void;
onPlayerSpeed?: (speed: number, prevSpeed: number) => void;
onPlayerStatus?: (status: PlayerStatus, prevStatus: PlayerStatus) => void;
onPlayerVolume?: (volume: number, prevVolume: number) => void;
}
export function usePlayerEvents(callbacks: PlayerEvents, deps: React.DependencyList) {
useEffect(() => { useEffect(() => {
const engine = createPlayerEvents(callbacks); const engine = createPlayerEvents(callbacks);
+37 -21
View File
@@ -54,7 +54,7 @@ interface Actions {
clearQueue: () => void; clearQueue: () => void;
clearSelected: (items: QueueSong[]) => void; clearSelected: (items: QueueSong[]) => void;
decreaseVolume: (value: number) => void; decreaseVolume: (value: number) => void;
getCurrentTrack: () => QueueSong | undefined; getCurrentSong: () => QueueSong | undefined;
getQueue: (groupBy?: QueueGroupingProperty) => GroupedQueue; getQueue: (groupBy?: QueueGroupingProperty) => GroupedQueue;
getQueueOrder: () => { getQueueOrder: () => {
groups: { count: number; name: string }[]; groups: { count: number; name: string }[];
@@ -411,7 +411,7 @@ export const usePlayerStoreBase = create<PlayerState>()(
state.player.volume = Math.max(0, state.player.volume - value); state.player.volume = Math.max(0, state.player.volume - value);
}); });
}, },
getCurrentTrack: () => { getCurrentSong: () => {
const queue = get().getQueue(); const queue = get().getQueue();
return queue.items[get().player.index]; return queue.items[get().player.index];
}, },
@@ -1127,52 +1127,64 @@ export const subscribePlayerQueue = (
export const subscribeCurrentTrack = ( export const subscribeCurrentTrack = (
onChange: ( onChange: (
track: { index: number; track: QueueSong | undefined }, properties: { index: number; song: QueueSong | undefined },
prevTrack: { index: number; track: QueueSong | undefined }, prev: { index: number; song: QueueSong | undefined },
) => void, ) => void,
) => { ) => {
return usePlayerStoreBase.subscribe( return usePlayerStoreBase.subscribe(
(state) => { (state) => {
const queue = state.getQueue(); const queue = state.getQueue();
const index = state.player.index; const index = state.player.index;
return { index, track: queue.items[index] }; return { index, song: queue.items[index] };
}, },
(track, prevTrack) => { (song, prevSong) => {
onChange(track, prevTrack); onChange(song, prevSong);
}, },
{ {
equalityFn: (a, b) => { equalityFn: (a, b) => {
return a.track?.uniqueId === b.track?.uniqueId; return a.song?.uniqueId === b.song?.uniqueId;
}, },
}, },
); );
}; };
export const subscribePlayerProgress = ( export const subscribePlayerProgress = (
onChange: (timestamp: number, prevTimestamp: number) => void, onChange: (properties: { timestamp: number }, prev: { timestamp: number }) => void,
) => { ) => {
return usePlayerStoreBase.subscribe( return usePlayerStoreBase.subscribe(
(state) => state.player.timestamp, (state) => state.player.timestamp,
(timestamp, prevTimestamp) => { (timestamp, prevTimestamp) => {
onChange(timestamp, prevTimestamp); onChange({ timestamp }, { timestamp: prevTimestamp });
}, },
); );
}; };
export const subscribePlayerVolume = (onChange: (volume: number, prevVolume: number) => void) => { export const subscribePlayerVolume = (
onChange: (properties: { volume: number }, prev: { volume: number }) => void,
) => {
return usePlayerStoreBase.subscribe( return usePlayerStoreBase.subscribe(
(state) => state.player.volume, (state) => state.player.volume,
(volume, prevVolume) => { (volume, prevVolume) => {
onChange(volume, prevVolume); onChange({ volume }, { volume: prevVolume });
}, },
); );
}; };
export const subscribePlayerStatus = ( export const subscribePlayerStatus = (
onChange: (status: PlayerStatus, prevStatus: PlayerStatus) => void, onChange: (
properties: { song: QueueSong | undefined; status: PlayerStatus },
prev: { song: QueueSong | undefined; status: PlayerStatus },
) => void,
) => { ) => {
return usePlayerStoreBase.subscribe( return usePlayerStoreBase.subscribe(
(state) => state.player.status, (state) => {
const currentSong = state.getCurrentSong();
return {
song: currentSong,
status: state.player.status,
};
},
(status, prevStatus) => { (status, prevStatus) => {
onChange(status, prevStatus); onChange(status, prevStatus);
}, },
@@ -1180,33 +1192,37 @@ export const subscribePlayerStatus = (
}; };
export const subscribePlayerSeekToTimestamp = ( export const subscribePlayerSeekToTimestamp = (
onChange: (timestamp: number, prevTimestamp: number) => void, onChange: (properties: { timestamp: number }, prev: { timestamp: number }) => void,
) => { ) => {
return usePlayerStoreBase.subscribe( return usePlayerStoreBase.subscribe(
(state) => state.player.seekToTimestamp, (state) => state.player.seekToTimestamp,
(timestamp, prevTimestamp) => { (timestamp, prevTimestamp) => {
onChange( onChange(
parseUniqueSeekToTimestamp(timestamp), { timestamp: parseUniqueSeekToTimestamp(timestamp) },
parseUniqueSeekToTimestamp(prevTimestamp), { timestamp: parseUniqueSeekToTimestamp(prevTimestamp) },
); );
}, },
); );
}; };
export const subscribePlayerMute = (onChange: (muted: boolean, prevMuted: boolean) => void) => { export const subscribePlayerMute = (
onChange: (properties: { muted: boolean }, prev: { muted: boolean }) => void,
) => {
return usePlayerStoreBase.subscribe( return usePlayerStoreBase.subscribe(
(state) => state.player.muted, (state) => state.player.muted,
(muted, prevMuted) => { (muted, prevMuted) => {
onChange(muted, prevMuted); onChange({ muted }, { muted: prevMuted });
}, },
); );
}; };
export const subscribePlayerSpeed = (onChange: (speed: number, prevSpeed: number) => void) => { export const subscribePlayerSpeed = (
onChange: (properties: { speed: number }, prev: { speed: number }) => void,
) => {
return usePlayerStoreBase.subscribe( return usePlayerStoreBase.subscribe(
(state) => state.player.speed, (state) => state.player.speed,
(speed, prevSpeed) => { (speed, prevSpeed) => {
onChange(speed, prevSpeed); onChange({ speed }, { speed: prevSpeed });
}, },
); );
}; };