scroll.ts 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. import { Song } from '../../../../types';
  2. import { scrollThroughItems } from '../../../../utils/delta';
  3. import { getFilteredSongs } from '../selectors';
  4. import { CmusUIState, LibraryModeWindow, View } from '../types';
  5. import { getNextActiveArtistAndAlbum } from '../utils/scroll';
  6. export const scrollSongs = (state: CmusUIState, delta: number): CmusUIState =>
  7. state.library.activeArtist === null
  8. ? state
  9. : {
  10. ...state,
  11. library: {
  12. ...state.library,
  13. activeSongId: scrollThroughItems(
  14. getFilteredSongs(state),
  15. (compare) => compare.id === state.library.activeSongId,
  16. delta,
  17. ).id,
  18. },
  19. };
  20. function getActiveSongIdFromActiveArtistAlbum(
  21. activeArtist: string | null,
  22. activeAlbum: string | null,
  23. artistSongs: Record<string, Song[]>,
  24. ): number | null {
  25. if (activeArtist === null) {
  26. return null;
  27. }
  28. const songs = artistSongs[activeArtist] ?? [];
  29. if (!activeAlbum) {
  30. return songs[0]?.id ?? null;
  31. }
  32. return songs.find((compare) => compare.album === activeAlbum)?.id ?? null;
  33. }
  34. function scrollArtists(state: CmusUIState, delta: number): CmusUIState {
  35. const { artist, album } = getNextActiveArtistAndAlbum(
  36. state.artists,
  37. state.artistAlbums,
  38. state.library.activeArtist,
  39. state.library.activeAlbum,
  40. state.library.expandedArtists,
  41. delta,
  42. );
  43. return {
  44. ...state,
  45. library: {
  46. ...state.library,
  47. activeArtist: artist,
  48. activeAlbum: album,
  49. activeSongId: getActiveSongIdFromActiveArtistAlbum(artist, album, state.artistSongs),
  50. },
  51. };
  52. }
  53. function handleScrollLibrary(state: CmusUIState, delta: number): CmusUIState {
  54. switch (state.library.modeWindow) {
  55. case LibraryModeWindow.ArtistList:
  56. return scrollArtists(state, delta);
  57. case LibraryModeWindow.SongList:
  58. return scrollSongs(state, delta);
  59. default:
  60. return state;
  61. }
  62. }
  63. function handleScrollQueue(state: CmusUIState, delta: number): CmusUIState {
  64. const scrolledItem =
  65. scrollThroughItems(state.queue.info, (compare) => compare.id === state.queue.active, delta) ??
  66. state.queue.info[0];
  67. return {
  68. ...state,
  69. queue: {
  70. ...state.queue,
  71. active: scrolledItem?.id ?? null,
  72. },
  73. };
  74. }
  75. export function handleScroll(state: CmusUIState, delta: number): CmusUIState {
  76. switch (state.view) {
  77. case View.Library:
  78. return handleScrollLibrary(state, delta);
  79. case View.Queue:
  80. return handleScrollQueue(state, delta);
  81. default:
  82. return {
  83. ...state,
  84. scroll: { delta, serialNumber: state.scroll.serialNumber + 1 },
  85. };
  86. }
  87. }