147 lines
3.8 KiB
TypeScript
147 lines
3.8 KiB
TypeScript
import { useCallback, useMemo, useState } from 'react';
|
|
|
|
import { ObjectId, Track } from '@/back-api';
|
|
import { useServiceContext } from '@/service/ServiceContext';
|
|
|
|
import { TrackServiceProps } from './Track';
|
|
|
|
export type PlaylistElement = {
|
|
trackId: ObjectId;
|
|
};
|
|
|
|
export type ActivePlaylistServiceProps = {
|
|
playTrackList: ObjectId[];
|
|
trackOffset?: number;
|
|
trackActive?: Track;
|
|
setNewPlaylist: (listIds: ObjectId[]) => void;
|
|
setNewPlaylistShuffle: (listIds: ObjectId[]) => void;
|
|
playInList: (id: number | undefined, listIds: ObjectId[]) => void;
|
|
play: (id: ObjectId) => void;
|
|
previous: () => void;
|
|
next: () => void;
|
|
first: () => void;
|
|
};
|
|
|
|
export const useActivePlaylistService = (): ActivePlaylistServiceProps => {
|
|
const { activePlaylist } = useServiceContext();
|
|
return activePlaylist;
|
|
};
|
|
|
|
export function localShuffle<T>(array: T[]): T[] {
|
|
let currentIndex = array.length,
|
|
randomIndex;
|
|
// While there remain elements to shuffle.
|
|
while (currentIndex != 0) {
|
|
// Pick a remaining element.
|
|
randomIndex = Math.floor(Math.random() * currentIndex);
|
|
currentIndex--;
|
|
// And swap it with the current element.
|
|
[array[currentIndex], array[randomIndex]] = [
|
|
array[randomIndex],
|
|
array[currentIndex],
|
|
];
|
|
}
|
|
return array;
|
|
}
|
|
|
|
export const useActivePlaylistServiceWrapped = (
|
|
track: TrackServiceProps
|
|
): ActivePlaylistServiceProps => {
|
|
const [playTrackList, setPlayTrackList] = useState<ObjectId[]>([]);
|
|
const [trackOffset, setTrackOffset] = useState<number | undefined>();
|
|
const trackActive = useMemo(() => {
|
|
return track.store.get(
|
|
trackOffset !== undefined ? playTrackList[trackOffset] : undefined
|
|
);
|
|
}, [track.store.data, playTrackList, trackOffset]);
|
|
|
|
const clear = useCallback(() => {
|
|
setPlayTrackList([]);
|
|
setTrackOffset(undefined);
|
|
}, [setPlayTrackList, setTrackOffset]);
|
|
|
|
const play = useCallback(
|
|
(id: ObjectId) => {
|
|
setPlayTrackList([id]);
|
|
setTrackOffset(0);
|
|
},
|
|
[setPlayTrackList, setTrackOffset]
|
|
);
|
|
const playInList = useCallback(
|
|
(id: number | undefined, listIds: ObjectId[]) => {
|
|
console.log(`Request play in list: ${id} in ${listIds?.length}`);
|
|
setPlayTrackList(listIds);
|
|
setTrackOffset(id);
|
|
},
|
|
[setPlayTrackList, setTrackOffset]
|
|
);
|
|
|
|
const setNewPlaylist = useCallback(
|
|
(listIds: ObjectId[]) => {
|
|
if (listIds.length == 0) {
|
|
clear();
|
|
return;
|
|
}
|
|
setPlayTrackList(listIds);
|
|
setTrackOffset(0);
|
|
},
|
|
[setPlayTrackList, setTrackOffset, clear]
|
|
);
|
|
|
|
const setNewPlaylistShuffle = useCallback(
|
|
(listIds: ObjectId[]) => {
|
|
if (listIds.length == 0) {
|
|
clear();
|
|
return;
|
|
}
|
|
const newList = localShuffle(listIds);
|
|
setPlayTrackList(newList);
|
|
setTrackOffset(0);
|
|
},
|
|
[setPlayTrackList, setTrackOffset, clear]
|
|
);
|
|
const previous = useCallback(() => {
|
|
setTrackOffset((previous) => {
|
|
if (previous === undefined) {
|
|
return previous;
|
|
}
|
|
if (previous === 0) {
|
|
return previous;
|
|
}
|
|
return previous - 1;
|
|
});
|
|
}, [setTrackOffset]);
|
|
const next = useCallback(() => {
|
|
setTrackOffset((previous) => {
|
|
if (previous === undefined || playTrackList.length === 0) {
|
|
return previous;
|
|
}
|
|
if (previous >= playTrackList.length - 1) {
|
|
return previous;
|
|
}
|
|
return previous + 1;
|
|
});
|
|
}, [playTrackList, setTrackOffset]);
|
|
const first = useCallback(() => {
|
|
setTrackOffset((previous) => {
|
|
if (previous === undefined || playTrackList.length === 0) {
|
|
return previous;
|
|
}
|
|
return 0;
|
|
});
|
|
}, [playTrackList, setTrackOffset]);
|
|
|
|
return {
|
|
playTrackList,
|
|
trackOffset,
|
|
setNewPlaylist,
|
|
setNewPlaylistShuffle,
|
|
playInList,
|
|
play,
|
|
previous,
|
|
next,
|
|
trackActive,
|
|
first,
|
|
};
|
|
};
|