From 59a21e1e6aaba3283fc112c381dde4fe823b07b9 Mon Sep 17 00:00:00 2001 From: jeffvli Date: Wed, 18 Oct 2023 17:33:51 -0700 Subject: [PATCH] Add current song styles for all song tables --- .../virtual-table/cells/row-index-cell.tsx | 19 ++++++ .../hooks/use-current-song-row-styles.ts | 62 +++++++++++++++++-- .../components/virtual-table/index.tsx | 51 +++++++++++++-- .../components/album-detail-content.tsx | 14 +++-- .../now-playing/components/play-queue.tsx | 6 +- .../playlist-detail-song-list-content.tsx | 11 +++- .../songs/components/song-list-table-view.tsx | 10 ++- src/renderer/themes/default.scss | 32 ++++++++++ 8 files changed, 190 insertions(+), 15 deletions(-) create mode 100644 src/renderer/components/virtual-table/cells/row-index-cell.tsx diff --git a/src/renderer/components/virtual-table/cells/row-index-cell.tsx b/src/renderer/components/virtual-table/cells/row-index-cell.tsx new file mode 100644 index 000000000..32721b0ae --- /dev/null +++ b/src/renderer/components/virtual-table/cells/row-index-cell.tsx @@ -0,0 +1,19 @@ +import type { ICellRendererParams } from '@ag-grid-community/core'; +import { Text } from '/@/renderer/components/text'; +import { CellContainer } from '/@/renderer/components/virtual-table/cells/generic-cell'; + +export const RowIndexCell = ({ value }: ICellRendererParams) => { + return ( + + + {value} + + + ); +}; diff --git a/src/renderer/components/virtual-table/hooks/use-current-song-row-styles.ts b/src/renderer/components/virtual-table/hooks/use-current-song-row-styles.ts index 1ad467f24..046314275 100644 --- a/src/renderer/components/virtual-table/hooks/use-current-song-row-styles.ts +++ b/src/renderer/components/virtual-table/hooks/use-current-song-row-styles.ts @@ -1,7 +1,8 @@ import { RowClassRules, RowNode } from '@ag-grid-community/core'; import type { AgGridReact as AgGridReactType } from '@ag-grid-community/react/lib/agGridReact'; -import { MutableRefObject, useEffect, useMemo } from 'react'; +import { MutableRefObject, useEffect, useMemo, useRef } from 'react'; import { Song } from '/@/renderer/api/types'; +import { useAppFocus } from '/@/renderer/hooks'; import { useCurrentSong, usePlayerStore } from '/@/renderer/store'; interface UseCurrentSongRowStylesProps { @@ -10,17 +11,43 @@ interface UseCurrentSongRowStylesProps { export const useCurrentSongRowStyles = ({ tableRef }: UseCurrentSongRowStylesProps) => { const currentSong = useCurrentSong(); + const isFocused = useAppFocus(); + const isFocusedRef = useRef(isFocused); + + useEffect(() => { + // Redraw rows if the app focus changes + if (isFocusedRef.current !== isFocused) { + isFocusedRef.current = isFocused; + if (tableRef?.current) { + const { api, columnApi } = tableRef?.current || {}; + if (api == null || columnApi == null) { + return; + } + + const currentNode = currentSong?.id ? api.getRowNode(currentSong.id) : undefined; + + const rowNodes = [currentNode].filter((e) => e !== undefined) as RowNode[]; + + if (rowNodes) { + api.redrawRows({ rowNodes }); + } + } + } + }, [currentSong?.id, isFocused, tableRef]); const rowClassRules = useMemo | undefined>(() => { return { 'current-song': (params) => { - return params?.data?.id === currentSong?.id; + return ( + params?.data?.id === currentSong?.id && + params?.data?.albumId === currentSong?.albumId + ); }, }; - }, [currentSong?.id]); + }, [currentSong?.albumId, currentSong?.id]); - // Redraw song rows when current song changes useEffect(() => { + // Redraw song rows when current song changes const unsubSongChange = usePlayerStore.subscribe( (state) => state.current.song, (song, previousSong) => { @@ -46,8 +73,35 @@ export const useCurrentSongRowStyles = ({ tableRef }: UseCurrentSongRowStylesPro { equalityFn: (a, b) => a?.id === b?.id }, ); + // Redraw song rows when the status changes + const unsubStatusChange = usePlayerStore.subscribe( + (state) => state.current.song, + (song, previousSong) => { + if (tableRef?.current) { + const { api, columnApi } = tableRef?.current || {}; + if (api == null || columnApi == null) { + return; + } + + const currentNode = song?.id ? api.getRowNode(song.id) : undefined; + + const previousNode = previousSong?.id + ? api.getRowNode(previousSong?.id) + : undefined; + + const rowNodes = [currentNode, previousNode].filter( + (e) => e !== undefined, + ) as RowNode[]; + + api.redrawRows({ rowNodes }); + } + }, + { equalityFn: (a, b) => a?.id === b?.id }, + ); + return () => { unsubSongChange(); + unsubStatusChange(); }; }, [tableRef]); diff --git a/src/renderer/components/virtual-table/index.tsx b/src/renderer/components/virtual-table/index.tsx index 0478b7c73..e67a5fadb 100644 --- a/src/renderer/components/virtual-table/index.tsx +++ b/src/renderer/components/virtual-table/index.tsx @@ -29,7 +29,11 @@ import { GenreCell } from '/@/renderer/components/virtual-table/cells/genre-cell import { GenericTableHeader } from '/@/renderer/components/virtual-table/headers/generic-table-header'; import { AppRoute } from '/@/renderer/router/routes'; import { PersistedTableColumn } from '/@/renderer/store/settings.store'; -import { TableColumn, TablePagination as TablePaginationType } from '/@/renderer/types'; +import { + PlayerStatus, + TableColumn, + TablePagination as TablePaginationType, +} from '/@/renderer/types'; import { FavoriteCell } from '/@/renderer/components/virtual-table/cells/favorite-cell'; import { RatingCell } from '/@/renderer/components/virtual-table/cells/rating-cell'; import { TablePagination } from '/@/renderer/components/virtual-table/table-pagination'; @@ -37,6 +41,7 @@ import { ActionsCell } from '/@/renderer/components/virtual-table/cells/actions- import { TitleCell } from '/@/renderer/components/virtual-table/cells/title-cell'; import { useFixedTableHeader } from '/@/renderer/components/virtual-table/hooks/use-fixed-table-header'; import { NoteCell } from '/@/renderer/components/virtual-table/cells/note-cell'; +import { RowIndexCell } from '/@/renderer/components/virtual-table/cells/row-index-cell'; export * from './table-config-dropdown'; export * from './table-pagination'; @@ -261,7 +266,15 @@ const tableColumns: { [key: string]: ColDef } = { }, rowIndex: { cellClass: 'row-index', - cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'right' }), + cellClassRules: { + focused: (params) => { + return params.context?.isFocused; + }, + playing: (params) => { + return params.context?.status === PlayerStatus.PLAYING; + }, + }, + cellRenderer: RowIndexCell, colId: TableColumn.ROW_INDEX, headerComponent: (params: IHeaderParams) => GenericTableHeader(params, { position: 'right', preset: 'rowIndex' }), @@ -324,6 +337,27 @@ const tableColumns: { [key: string]: ColDef } = { params.data ? params.data.trackNumber : undefined, width: 80, }, + trackNumberDetail: { + cellClass: 'row-index', + cellClassRules: { + focused: (params) => { + return params.context?.isFocused; + }, + playing: (params) => { + return params.context?.status === PlayerStatus.PLAYING; + }, + }, + cellRenderer: RowIndexCell, + colId: TableColumn.TRACK_NUMBER, + field: 'trackNumber', + headerComponent: (params: IHeaderParams) => + GenericTableHeader(params, { position: 'center' }), + headerName: 'Track', + suppressSizeToFit: true, + valueGetter: (params: ValueGetterParams) => + params.data ? params.data.trackNumber : undefined, + width: 80, + }, userFavorite: { cellClass: (params) => (params.value ? 'visible ag-cell-favorite' : 'ag-cell-favorite'), cellRenderer: FavoriteCell, @@ -356,10 +390,19 @@ export const getColumnDef = (column: TableColumn) => { return tableColumns[column as keyof typeof tableColumns]; }; -export const getColumnDefs = (columns: PersistedTableColumn[], useWidth?: boolean) => { +export const getColumnDefs = ( + columns: PersistedTableColumn[], + useWidth?: boolean, + type?: 'albumDetail', +) => { const columnDefs: ColDef[] = []; for (const column of columns) { - const presetColumn = tableColumns[column.column as keyof typeof tableColumns]; + let presetColumn = tableColumns[column.column as keyof typeof tableColumns]; + + if (type === 'albumDetail' && column.column === TableColumn.TRACK_NUMBER) { + presetColumn = tableColumns['trackNumberDetail' as keyof typeof tableColumns]; + } + if (presetColumn) { columnDefs.push({ ...presetColumn, diff --git a/src/renderer/features/albums/components/album-detail-content.tsx b/src/renderer/features/albums/components/album-detail-content.tsx index 74156c7dc..2d363032d 100644 --- a/src/renderer/features/albums/components/album-detail-content.tsx +++ b/src/renderer/features/albums/components/album-detail-content.tsx @@ -31,9 +31,9 @@ import { import { usePlayQueueAdd } from '/@/renderer/features/player'; import { PlayButton, useCreateFavorite, useDeleteFavorite } from '/@/renderer/features/shared'; import { LibraryBackgroundOverlay } from '/@/renderer/features/shared/components/library-background-overlay'; -import { useContainerQuery } from '/@/renderer/hooks'; +import { useAppFocus, useContainerQuery } from '/@/renderer/hooks'; import { AppRoute } from '/@/renderer/router/routes'; -import { useCurrentServer } from '/@/renderer/store'; +import { useCurrentServer, useCurrentStatus } from '/@/renderer/store'; import { usePlayButtonBehavior, useSettingsStoreActions, @@ -70,8 +70,13 @@ export const AlbumDetailContent = ({ tableRef, background }: AlbumDetailContentP const handlePlayQueueAdd = usePlayQueueAdd(); const tableConfig = useTableSettings('albumDetail'); const { setTable } = useSettingsStoreActions(); + const status = useCurrentStatus(); + const isFocused = useAppFocus(); - const columnDefs = useMemo(() => getColumnDefs(tableConfig.columns), [tableConfig.columns]); + const columnDefs = useMemo( + () => getColumnDefs(tableConfig.columns, false, 'albumDetail'), + [tableConfig.columns], + ); const getRowHeight = useCallback( (params: RowHeightParams) => { @@ -394,10 +399,11 @@ export const AlbumDetailContent = ({ tableRef, background }: AlbumDetailContentP suppressLoadingOverlay suppressRowDrag autoFitColumns={tableConfig.autoFit} - className="album-table" columnDefs={columnDefs} context={{ + isFocused, onCellContextMenu, + status, }} enableCellChangeFlash={false} fullWidthCellRenderer={FullWidthDiscCell} diff --git a/src/renderer/features/now-playing/components/play-queue.tsx b/src/renderer/features/now-playing/components/play-queue.tsx index 6fbb1110d..d1df1b5d8 100644 --- a/src/renderer/features/now-playing/components/play-queue.tsx +++ b/src/renderer/features/now-playing/components/play-queue.tsx @@ -35,6 +35,7 @@ import { LibraryItem, QueueSong } from '/@/renderer/api/types'; import { useHandleTableContextMenu } from '/@/renderer/features/context-menu'; import { QUEUE_CONTEXT_MENU_ITEMS } from '/@/renderer/features/context-menu/context-menu-items'; import { VirtualGridAutoSizerContainer } from '/@/renderer/components/virtual-grid'; +import { useAppFocus } from '/@/renderer/hooks'; const mpvPlayer = isElectron() ? window.electron.mpvPlayer : null; const remote = isElectron() ? window.electron.remote : null; @@ -58,6 +59,7 @@ export const PlayQueue = forwardRef(({ type }: QueueProps, ref: Ref) => { const playerType = usePlayerType(); const { play } = usePlayerControls(); const volume = useVolume(); + const isFocused = useAppFocus(); useEffect(() => { if (tableRef.current) { @@ -206,7 +208,7 @@ export const PlayQueue = forwardRef(({ type }: QueueProps, ref: Ref) => { } } } - }, [currentSong, previousSong, tableConfig.followCurrentSong, status]); + }, [currentSong, previousSong, tableConfig.followCurrentSong, status, isFocused]); const onCellContextMenu = useHandleTableContextMenu(LibraryItem.SONG, QUEUE_CONTEXT_MENU_ITEMS); @@ -221,7 +223,9 @@ export const PlayQueue = forwardRef(({ type }: QueueProps, ref: Ref) => { autoFitColumns={tableConfig.autoFit} columnDefs={columnDefs} context={{ + isFocused, onCellContextMenu, + status, }} deselectOnClickOutside={type === 'fullScreen'} getRowId={(data) => data.data.uniqueId} diff --git a/src/renderer/features/playlists/components/playlist-detail-song-list-content.tsx b/src/renderer/features/playlists/components/playlist-detail-song-list-content.tsx index f10202419..7365d886b 100644 --- a/src/renderer/features/playlists/components/playlist-detail-song-list-content.tsx +++ b/src/renderer/features/playlists/components/playlist-detail-song-list-content.tsx @@ -22,7 +22,7 @@ import { SortOrder, } from '/@/renderer/api/types'; import { VirtualGridAutoSizerContainer } from '/@/renderer/components/virtual-grid'; -import { getColumnDefs, TablePagination, VirtualTable } from '/@/renderer/components/virtual-table'; +import { TablePagination, VirtualTable, getColumnDefs } from '/@/renderer/components/virtual-table'; import { useCurrentSongRowStyles } from '/@/renderer/components/virtual-table/hooks/use-current-song-row-styles'; import { useHandleTableContextMenu } from '/@/renderer/features/context-menu'; import { @@ -34,6 +34,7 @@ import { usePlaylistDetail } from '/@/renderer/features/playlists/queries/playli import { usePlaylistSongList } from '/@/renderer/features/playlists/queries/playlist-song-list-query'; import { useCurrentServer, + useCurrentStatus, usePlaylistDetailStore, usePlaylistDetailTablePagination, useSetPlaylistDetailTable, @@ -41,6 +42,7 @@ import { } from '/@/renderer/store'; import { usePlayButtonBehavior } from '/@/renderer/store/settings.store'; import { ListDisplayType } from '/@/renderer/types'; +import { useAppFocus } from '/@/renderer/hooks'; interface PlaylistDetailContentProps { tableRef: MutableRefObject; @@ -49,6 +51,8 @@ interface PlaylistDetailContentProps { export const PlaylistDetailSongListContent = ({ tableRef }: PlaylistDetailContentProps) => { const { playlistId } = useParams() as { playlistId: string }; const queryClient = useQueryClient(); + const status = useCurrentStatus(); + const isFocused = useAppFocus(); const server = useCurrentServer(); const page = usePlaylistDetailStore(); const filters: Partial = useMemo(() => { @@ -236,6 +240,11 @@ export const PlaylistDetailSongListContent = ({ tableRef }: PlaylistDetailConten alwaysShowHorizontalScroll autoFitColumns={page.table.autoFit} columnDefs={columnDefs} + context={{ + isFocused, + onCellContextMenu: handleContextMenu, + status, + }} getRowId={(data) => data.data.uniqueId} infiniteInitialRowCount={checkPlaylistList.data?.totalRecordCount || 100} pagination={isPaginationEnabled} diff --git a/src/renderer/features/songs/components/song-list-table-view.tsx b/src/renderer/features/songs/components/song-list-table-view.tsx index 36ad27b44..06de099d5 100644 --- a/src/renderer/features/songs/components/song-list-table-view.tsx +++ b/src/renderer/features/songs/components/song-list-table-view.tsx @@ -8,7 +8,8 @@ import { useCurrentSongRowStyles } from '/@/renderer/components/virtual-table/ho import { useVirtualTable } from '/@/renderer/components/virtual-table/hooks/use-virtual-table'; import { useListContext } from '/@/renderer/context/list-context'; import { SONG_CONTEXT_MENU_ITEMS } from '/@/renderer/features/context-menu/context-menu-items'; -import { useCurrentServer, usePlayButtonBehavior } from '/@/renderer/store'; +import { useAppFocus } from '/@/renderer/hooks'; +import { useCurrentServer, useCurrentStatus, usePlayButtonBehavior } from '/@/renderer/store'; interface SongListTableViewProps { itemCount?: number; @@ -18,6 +19,8 @@ interface SongListTableViewProps { export const SongListTableView = ({ tableRef, itemCount }: SongListTableViewProps) => { const server = useCurrentServer(); const { pageKey, id, handlePlay, customFilters } = useListContext(); + const isFocused = useAppFocus(); + const status = useCurrentStatus(); const { rowClassRules } = useCurrentSongRowStyles({ tableRef }); @@ -46,6 +49,11 @@ export const SongListTableView = ({ tableRef, itemCount }: SongListTableViewProp key={`table-${tableProps.rowHeight}-${server?.id}`} ref={tableRef} {...tableProps} + context={{ + ...tableProps.context, + isFocused, + status, + }} rowClassRules={rowClassRules} onRowDoubleClicked={handleRowDoubleClick} /> diff --git a/src/renderer/themes/default.scss b/src/renderer/themes/default.scss index 44410c909..709e06061 100644 --- a/src/renderer/themes/default.scss +++ b/src/renderer/themes/default.scss @@ -101,6 +101,8 @@ --card-poster-bg-hover: transparent; --card-poster-radius: 3px; --background-noise: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMDAiIGhlaWdodD0iMzAwIj48ZmlsdGVyIGlkPSJhIiB4PSIwIiB5PSIwIj48ZmVUdXJidWxlbmNlIHR5cGU9ImZyYWN0YWxOb2lzZSIgYmFzZUZyZXF1ZW5jeT0iLjc1IiBzdGl0Y2hUaWxlcz0ic3RpdGNoIi8+PGZlQ29sb3JNYXRyaXggdHlwZT0ic2F0dXJhdGUiIHZhbHVlcz0iMCIvPjwvZmlsdGVyPjxwYXRoIGZpbHRlcj0idXJsKCNhKSIgb3BhY2l0eT0iLjA1IiBkPSJNMCAwaDMwMHYzMDBIMHoiLz48L3N2Zz4='); + --current-song-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB2aWV3Qm94PSIxMDAgMTMwIDU3IDgwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxyZWN0IHg9IjEwMCIgeT0iMTMwIiB3aWR0aD0iMTIiIGhlaWdodD0iMjAiIHN0eWxlPSJmaWxsOiByZ2IoMjE2LCAyMTYsIDIxNik7IHN0cm9rZTogcmdiKDAsIDAsIDApOyB0cmFuc2Zvcm0tb3JpZ2luOiAxMDZweCAxNDBweDsiLz4KICA8cmVjdCB4PSIxMTUiIHk9IjEzMCIgd2lkdGg9IjEyIiBoZWlnaHQ9IjYwIiBzdHlsZT0iZmlsbDogcmdiKDIxNiwgMjE2LCAyMTYpOyBzdHJva2U6IHJnYigwLCAwLCAwKTsgdHJhbnNmb3JtLW9yaWdpbjogMTIxcHggMTYwcHg7Ii8+CiAgPHJlY3QgeD0iMTMwIiB5PSIxMzAiIHdpZHRoPSIxMiIgaGVpZ2h0PSI4MCIgc3R5bGU9ImZpbGw6IHJnYigyMTYsIDIxNiwgMjE2KTsgc3Ryb2tlOiByZ2IoMCwgMCwgMCk7IHRyYW5zZm9ybS1vcmlnaW46IDEzNnB4IDE3MHB4OyIvPgogIDxyZWN0IHg9IjE0NSIgeT0iMTMwIiB3aWR0aD0iMTIiIGhlaWdodD0iNDUiIHN0eWxlPSJmaWxsOiByZ2IoMjE2LCAyMTYsIDIxNik7IHN0cm9rZTogcmdiKDAsIDAsIDApOyB0cmFuc2Zvcm0tb3JpZ2luOiAxNTFweCAxNTIuNXB4OyIvPgo8L3N2Zz4='); + --current-song-image-animated: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB2aWV3Qm94PSIxMDAgMTMwIDU3IDgwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxyZWN0IHg9IjEwMCIgeT0iMTMwIiB3aWR0aD0iMTIiIGhlaWdodD0iODAiIHN0eWxlPSJmaWxsOiByZ2IoMjE2LCAyMTYsIDIxNik7IHN0cm9rZTogcmdiKDAsIDAsIDApOyB0cmFuc2Zvcm0tb3JpZ2luOiAxMDZweCAxNzBweDsiPgogICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0iaGVpZ2h0IiB2YWx1ZXM9IjgwOzE1OzgwIiBiZWdpbj0iMC4xcyIgZHVyPSIwLjk1cyIga2V5VGltZXM9IjA7IDAuNDczNjg7IDEiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBjYWxjTW9kZT0ic3BsaW5lIiBrZXlTcGxpbmVzPSIwLjQyIDAgMC41OCAxOyAwLjQyIDAgMC41OCAxIi8+CiAgPC9yZWN0PgogIDxyZWN0IHg9IjExNSIgeT0iMTMwIiB3aWR0aD0iMTIiIGhlaWdodD0iODAiIHN0eWxlPSJmaWxsOiByZ2IoMjE2LCAyMTYsIDIxNik7IHN0cm9rZTogcmdiKDAsIDAsIDApOyB0cmFuc2Zvcm0tb3JpZ2luOiAxMjFweCAxNzBweDsiPgogICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0iaGVpZ2h0IiB2YWx1ZXM9IjI1OzgwOzI1IiBiZWdpbj0iMC4xcyIgZHVyPSIwLjk1cyIga2V5VGltZXM9IjA7IDAuNDQ0NDQ7IDEiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBjYWxjTW9kZT0ic3BsaW5lIiBrZXlTcGxpbmVzPSIwLjQ1IDAgMC41NSAxOyAwLjQ1IDAgMC41NSAxIi8+CiAgPC9yZWN0PgogIDxyZWN0IHg9IjEzMCIgeT0iMTMwIiB3aWR0aD0iMTIiIGhlaWdodD0iODAiIHN0eWxlPSJmaWxsOiByZ2IoMjE2LCAyMTYsIDIxNik7IHN0cm9rZTogcmdiKDAsIDAsIDApOyB0cmFuc2Zvcm0tb3JpZ2luOiAxMzZweCAxNzBweDsiPgogICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0iaGVpZ2h0IiB2YWx1ZXM9IjgwOzEwOzgwIiBiZWdpbj0iMC4xcyIgZHVyPSIwLjg1cyIga2V5VGltZXM9IjA7IDAuNDIxMDU7IDEiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBjYWxjTW9kZT0ic3BsaW5lIiBrZXlTcGxpbmVzPSIwLjY1IDAgMC4zNSAxOyAwLjY1IDAgMC4zNSAxIi8+CiAgPC9yZWN0PgogIDxyZWN0IHg9IjE0NSIgeT0iMTMwIiB3aWR0aD0iMTIiIGhlaWdodD0iODAiIHN0eWxlPSJmaWxsOiByZ2IoMjE2LCAyMTYsIDIxNik7IHN0cm9rZTogcmdiKDAsIDAsIDApOyB0cmFuc2Zvcm0tb3JpZ2luOiAxNTFweCAxNzBweDsiPgogICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0iaGVpZ2h0IiB2YWx1ZXM9IjMwOzgwOzMwIiBiZWdpbj0iMC4xcyIgZHVyPSIxLjA1cyIga2V5VGltZXM9IjA7IDAuMzE1Nzk7IDEiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiBjYWxjTW9kZT0ic3BsaW5lIiBrZXlTcGxpbmVzPSIwLjQyIDAgMC41OCAxOyAwLjQyIDAgMC41OCAxIi8+CiAgPC9yZWN0Pgo8L3N2Zz4='); --bg-header-overlay: linear-gradient(transparent 0%, rgba(0, 0, 0, 50%) 100%), var(--background-noise); --bg-subheader-overlay: linear-gradient(180deg, rgba(0, 0, 0, 5%) 0%, var(--main-bg) 100%), @@ -190,4 +192,34 @@ color: var(--primary-color) !important; } } + + .current-song > .row-index.playing .current-song-index { + display: none; + } + + .current-song > .row-index.playing.focused ::before { + content: ' '; + display: block; + height: 1rem; + width: 1rem; + background-color: var(--primary-color); + -webkit-mask-image: var(--current-song-image-animated); + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; + transform: rotate(180deg); + mask-image: var(--current-song-image-animated); + } + + .current-song > .row-index.playing ::before { + content: ' '; + display: block; + height: 1rem; + width: 1rem; + background-color: var(--primary-color); + -webkit-mask-image: var(--current-song-image); + -webkit-mask-repeat: no-repeat; + mask-repeat: no-repeat; + transform: rotate(180deg); + mask-image: var(--current-song-image); + } }