import React, { CSSProperties, useContext, useMemo, useRef } from 'react'; import AutoSizer from 'react-virtualized-auto-sizer'; import { FixedSizeList as List } from 'react-window'; import { StateContext } from '../../../../context/state'; import { Song } from '../../../../types'; import { namedMemo } from '../../../../utils/component'; import { CmusUIStateContext } from '../reducer'; import { getFilteredSongs } from '../selectors'; import { NoWrapFill } from '../styled/layout'; import { AsciiSpinner } from '../styled/spinner'; import { getSongScrollIndex, lineHeight, useAutoJumpyScroll } from '../utils/scroll'; import * as Styled from './songs.styles'; type Props = { active: boolean; }; type SongData = { song: Song; active: boolean; parentActive: boolean; highlight: boolean; }; const itemKey = (index: number, data: SongData[]): number => data[index].song.id; const Row = namedMemo<{ index: number; data: SongData[]; style: CSSProperties }>( 'Song', ({ index, data, style }) => { const { song, active, parentActive, highlight } = data[index]; return ( {song.track} - {song.title || 'Untitled Track'} ); }, ); export const Songs: React.FC = ({ active: parentActive }) => { const globalState = useContext(StateContext); const { songId: playingSongId } = globalState.player; const state = useContext(CmusUIStateContext); const { activeArtist, activeSongId } = state.library; const filteredSongs = getFilteredSongs(state); const itemData = useMemo( () => filteredSongs.map((song) => ({ song, active: song.id === activeSongId, parentActive, highlight: song.id === playingSongId, })), [parentActive, activeSongId, playingSongId, filteredSongs], ); const windowRef = useRef(null); const scrollIndex = getSongScrollIndex(filteredSongs, activeSongId); useAutoJumpyScroll(windowRef, scrollIndex); if (activeArtist !== null && !(activeArtist in state.artistSongs)) { return ( ); } return ( {({ height, width }): React.ReactElement => ( {Row} )} ); };