| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- import {
- ActionQueueOrdered,
- ActionQueuePushed,
- ActionStateSetLocal,
- ActionTypeLocal,
- ActionTypeRemote,
- LocalAction,
- RemoteAction,
- } from '../actions';
- import { GlobalState } from '../reducer/types';
- import { getNextPlayerStateFromAction, isMaster } from '../selectors';
- const reverseInArray = <T>(array: T[], index: number): T[] => [
- ...array.slice(0, Math.max(0, index)),
- ...array.slice(Math.max(0, index), index + 2).reverse(),
- ...array.slice(index + 2),
- ];
- function reorderQueue(queue: number[], action: ActionQueueOrdered): number[] {
- const currentIndex = queue.indexOf(action.payload.songId);
- if (currentIndex === -1) {
- return queue;
- }
- const reverseIndex = action.payload.delta === 1 ? currentIndex : currentIndex - 1;
- return reverseInArray(queue, reverseIndex);
- }
- function pushToQueue(state: GlobalState, action: ActionQueuePushed): RemoteAction | null {
- const nextQueue = Array.from(new Set([...state.player.queue, ...action.payload]));
- if (!state.player.master || nextQueue.length === state.player.queue.length) {
- return null;
- }
- return {
- type: ActionTypeRemote.StateSet,
- payload: {
- ...state.player,
- queue: nextQueue,
- },
- };
- }
- function sendStateUpdateToServer(
- state: GlobalState,
- action: ActionStateSetLocal,
- ): RemoteAction | null {
- const nextPlayer = getNextPlayerStateFromAction(state.player, action.payload);
- if (!state.player.master && !nextPlayer?.master) {
- return null;
- }
- return {
- type: ActionTypeRemote.StateSet,
- payload: nextPlayer,
- };
- }
- export function globalEffects(state: GlobalState, action: LocalAction): RemoteAction | null {
- switch (action.type) {
- case ActionTypeLocal.StateSet:
- return sendStateUpdateToServer(state, action);
- case ActionTypeLocal.Seeked:
- if (!state.player.master) {
- return null;
- }
- return {
- type: ActionTypeRemote.StateSet,
- payload: { ...state.player, seekTime: action.payload },
- };
- case ActionTypeLocal.MasterSet:
- if (action.payload) {
- return {
- type: ActionTypeRemote.StateSet,
- payload: {
- ...state.player,
- seekTime: state.player.currentTime,
- master: action.payload,
- },
- };
- }
- return {
- type: ActionTypeRemote.StateSet,
- payload: {
- ...state.player,
- playing: false,
- seekTime: -1,
- master: state.myClientName,
- },
- };
- case ActionTypeLocal.ActiveClientToggled:
- return {
- type: ActionTypeRemote.StateSet,
- payload: {
- ...state.player,
- activeClients: state.player.activeClients.includes(action.payload)
- ? state.player.activeClients.filter((client) => client !== action.payload)
- : [...state.player.activeClients, action.payload],
- },
- };
- case ActionTypeLocal.PlayPaused:
- return {
- type: ActionTypeRemote.StateSet,
- payload: {
- ...state.player,
- playing: !state.player.playing,
- },
- };
- case ActionTypeLocal.SongInfoFetched:
- if (isMaster(state) || !action.payload.replace || !state.player.master) {
- return null;
- }
- return {
- type: ActionTypeRemote.StateSet,
- payload: {
- ...state.player,
- songId: action.payload.song?.id ?? null,
- playing: !!action.payload.song,
- currentTime: 0,
- seekTime: 0,
- },
- };
- case ActionTypeLocal.QueuePushed:
- return pushToQueue(state, action);
- case ActionTypeLocal.QueueShifted:
- if (!state.player.master) {
- return null;
- }
- return {
- type: ActionTypeRemote.StateSet,
- payload: {
- ...state.player,
- queue: state.player.queue.slice(1),
- playing: !!state.player.queue[0],
- songId: state.player.queue[0],
- currentTime: 0,
- seekTime: 0,
- },
- };
- case ActionTypeLocal.QueueRemoved:
- if (!state.player.master) {
- return null;
- }
- return {
- type: ActionTypeRemote.StateSet,
- payload: {
- ...state.player,
- queue: state.player.queue.filter((id) => id !== action.payload),
- },
- };
- case ActionTypeLocal.QueueOrdered:
- return {
- type: ActionTypeRemote.StateSet,
- payload: { ...state.player, queue: reorderQueue(state.player.queue, action) },
- };
- default:
- return null;
- }
- }
|