queue.ts 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. import { AxiosInstance, AxiosResponse } from 'axios';
  2. import { useCallback, useContext, useEffect } from 'react';
  3. import { stateSet } from '../actions';
  4. import { DispatchContext } from '../context/state';
  5. import { NullSong, Song, songExists } from '../types';
  6. import { getApiUrl } from '../utils/url';
  7. import { useRequestCallback } from './request';
  8. function useNextOrPrevSong(
  9. key: 'next' | 'prev',
  10. ): [(songId: number) => void, Song | NullSong | null, boolean] {
  11. const sendRequest = useCallback(
  12. (axios: AxiosInstance, id: number): Promise<AxiosResponse<Song | NullSong>> =>
  13. axios.get(`${getApiUrl()}/${key}-song?id=${id}`),
  14. [key],
  15. );
  16. return useRequestCallback<number, Song | NullSong>({
  17. sendRequest,
  18. });
  19. }
  20. export function usePlayQueue(): {
  21. onNext: (songId: number) => void;
  22. onPrev: (songId: number) => void;
  23. loading: boolean;
  24. } {
  25. const dispatch = useContext(DispatchContext);
  26. const [onRequestNext, nextSong, loadingNext] = useNextOrPrevSong('next');
  27. const [onRequestPrev, prevSong, loadingPrev] = useNextOrPrevSong('prev');
  28. const response = nextSong ?? prevSong;
  29. useEffect(() => {
  30. if (response) {
  31. if (songExists(response)) {
  32. dispatch(stateSet({ songId: response.id, seekTime: 0, playing: true }));
  33. } else {
  34. dispatch(stateSet({ songId: null, playing: false, seekTime: -1 }));
  35. }
  36. }
  37. }, [dispatch, response]);
  38. return { onNext: onRequestNext, onPrev: onRequestPrev, loading: loadingNext || loadingPrev };
  39. }