app.tsx 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import React, { Suspense, useCallback, useContext } from 'react';
  2. import { StateInspector } from 'reinspect';
  3. import { stateSet } from '../actions';
  4. import { DispatchContext, StateContext } from '../context/state';
  5. import { useMaster } from '../hooks/master';
  6. import { usePlayQueue } from '../hooks/queue';
  7. import { useKeepalive } from '../hooks/socket';
  8. import { useCurrentlyPlayingSongInfo } from '../hooks/status';
  9. import { isMaster } from '../selectors';
  10. import { getSongUrl } from '../utils/url';
  11. import { LoadingWrapper } from './identify';
  12. import { Player } from './player';
  13. import { uiProviders } from './ui';
  14. import { UIProvider } from './ui/types';
  15. export type Props = {
  16. socket: WebSocket;
  17. };
  18. const uiProvider = UIProvider.Cmus;
  19. const UI = uiProviders[uiProvider];
  20. export const App: React.FC<Props> = ({ socket }) => {
  21. useKeepalive(socket);
  22. useMaster();
  23. useCurrentlyPlayingSongInfo();
  24. const state = useContext(StateContext);
  25. const dispatch = useContext(DispatchContext);
  26. const onTimeUpdate = useCallback(
  27. (currentTime: number): void => {
  28. dispatch(stateSet({ currentTime }));
  29. },
  30. [dispatch],
  31. );
  32. const { onNext, onPrev, loading: loadingQueue } = usePlayQueue();
  33. const onEnded = useCallback(() => {
  34. if (state.player.songId) {
  35. onNext(state.player.songId);
  36. }
  37. }, [onNext, state.player.songId]);
  38. const nextSong = useCallback(() => {
  39. if (loadingQueue || !state.player.songId) {
  40. return;
  41. }
  42. onNext(state.player.songId);
  43. }, [loadingQueue, onNext, state.player.songId]);
  44. const prevSong = useCallback(() => {
  45. if (loadingQueue || !state.player.songId) {
  46. return;
  47. }
  48. onPrev(state.player.songId);
  49. }, [loadingQueue, onPrev, state.player.songId]);
  50. return (
  51. <>
  52. {isMaster(state) && !!state.player.songId && (
  53. <Player
  54. src={getSongUrl(state.player.songId)}
  55. playing={state.player.playing}
  56. seekTime={state.player.seekTime}
  57. onTimeUpdate={onTimeUpdate}
  58. timeUpdateFPS={1}
  59. onEnded={onEnded}
  60. />
  61. )}
  62. <StateInspector name="ui">
  63. <Suspense fallback={<LoadingWrapper />}>
  64. <UI
  65. isMaster={isMaster(state)}
  66. currentSong={state.songInfo}
  67. nextSong={nextSong}
  68. prevSong={prevSong}
  69. />
  70. </Suspense>
  71. </StateInspector>
  72. </>
  73. );
  74. };