From 1497e43455f3decf34521bcf71b65a7ea6c063f8 Mon Sep 17 00:00:00 2001 From: Kendall Garner <17521368+kgarner7@users.noreply.github.com> Date: Sat, 7 Oct 2023 00:38:44 -0700 Subject: [PATCH 01/16] add more emphasis to current song --- src/renderer/themes/default.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/renderer/themes/default.scss b/src/renderer/themes/default.scss index c8c64b5f0..951f405d4 100644 --- a/src/renderer/themes/default.scss +++ b/src/renderer/themes/default.scss @@ -184,6 +184,9 @@ } .current-song { + background: var(--table-row-hover-bg); + border: 1px solid var(--primary-color) !important; + .current-song-child { color: var(--primary-color) !important; } From 9dff3a21ab882fe7e9c907ee24c35a5d48094f4d Mon Sep 17 00:00:00 2001 From: Kendall Garner <17521368+kgarner7@users.noreply.github.com> Date: Sat, 7 Oct 2023 23:36:04 -0700 Subject: [PATCH 02/16] add css indicator (rivolumelineup) --- .../components/virtual-table/index.tsx | 4 ++- src/renderer/store/settings.store.ts | 6 +++- src/renderer/themes/default.scss | 30 ++++++++++++++++++- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/src/renderer/components/virtual-table/index.tsx b/src/renderer/components/virtual-table/index.tsx index f59ec520d..881d87811 100644 --- a/src/renderer/components/virtual-table/index.tsx +++ b/src/renderer/components/virtual-table/index.tsx @@ -260,6 +260,7 @@ const tableColumns: { [key: string]: ColDef } = { width: 80, }, rowIndex: { + cellClass: 'row-index', cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'right' }), colId: TableColumn.ROW_INDEX, headerComponent: (params: IHeaderParams) => @@ -268,7 +269,7 @@ const tableColumns: { [key: string]: ColDef } = { valueGetter: (params) => { return (params.node?.rowIndex || 0) + 1; }, - width: 65, + width: 71, }, songCount: { cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }), @@ -311,6 +312,7 @@ const tableColumns: { [key: string]: ColDef } = { width: 250, }, trackNumber: { + cellClass: 'track-number', cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }), colId: TableColumn.TRACK_NUMBER, field: 'trackNumber', diff --git a/src/renderer/store/settings.store.ts b/src/renderer/store/settings.store.ts index bfe33ab6b..7b455036f 100644 --- a/src/renderer/store/settings.store.ts +++ b/src/renderer/store/settings.store.ts @@ -343,6 +343,10 @@ const initialState: SettingsState = { fullScreen: { autoFit: true, columns: [ + { + column: TableColumn.ROW_INDEX, + width: 80, + }, { column: TableColumn.TITLE_COMBINED, width: 500, @@ -364,7 +368,7 @@ const initialState: SettingsState = { columns: [ { column: TableColumn.ROW_INDEX, - width: 50, + width: 80, }, { column: TableColumn.TITLE, diff --git a/src/renderer/themes/default.scss b/src/renderer/themes/default.scss index 951f405d4..5b12ab45e 100644 --- a/src/renderer/themes/default.scss +++ b/src/renderer/themes/default.scss @@ -101,6 +101,7 @@ --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,PHN2ZyBzdHJva2U9ImN1cnJlbnRDb2xvciIgZmlsbD0iY3VycmVudENvbG9yIiBzdHJva2Utd2lkdGg9IjAiIHZpZXdCb3g9IjAgMCAyNCAyNCIgaGVpZ2h0PSIxLjJyZW0iIHdpZHRoPSIxLjJyZW0iIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTIgMTYuMDAwMUg1Ljg4ODg5TDExLjE4MzQgMjAuMzMxOUMxMS4yNzI3IDIwLjQwNSAxMS4zODQ2IDIwLjQ0NDkgMTEuNSAyMC40NDQ5QzExLjc3NjEgMjAuNDQ0OSAxMiAyMC4yMjExIDEyIDE5Ljk0NDlWNC4wNTUxOUMxMiAzLjkzOTc3IDExLjk2MDEgMy44Mjc5IDExLjg4NyAzLjczODU3QzExLjcxMjEgMy41MjQ4NSAxMS4zOTcxIDMuNDkzMzUgMTEuMTgzNCAzLjY2ODIxTDUuODg4ODkgOC4wMDAwN0gyQzEuNDQ3NzIgOC4wMDAwNyAxIDguNDQ3NzggMSA5LjAwMDA3VjE1LjAwMDFDMSAxNS41NTI0IDEuNDQ3NzIgMTYuMDAwMSAyIDE2LjAwMDFaTTIzIDEyQzIzIDE1LjI5MiAyMS41NTM5IDE4LjI0NjMgMTkuMjYyMiAyMC4yNjIyTDE3Ljg0NDUgMTguODQ0NEMxOS43NzU4IDE3LjE5MzcgMjEgMTQuNzM5OCAyMSAxMkMyMSA5LjI2MDE2IDE5Ljc3NTggNi44MDYyOSAxNy44NDQ1IDUuMTU1NTdMMTkuMjYyMiAzLjczNzc5QzIxLjU1MzkgNS43NTM2OCAyMyA4LjcwNzk1IDIzIDEyWk0xOCAxMkMxOCAxMC4wODgzIDE3LjEwNiA4LjM4NTQ4IDE1LjcxMzMgNy4yODY3M0wxNC4yODQyIDguNzE1ODRDMTUuMzIxMyA5LjQzODU1IDE2IDEwLjY0IDE2IDEyQzE2IDEzLjM2IDE1LjMyMTMgMTQuNTYxNCAxNC4yODQyIDE1LjI4NDFMMTUuNzEzMyAxNi43MTMyQzE3LjEwNiAxNS42MTQ1IDE4IDEzLjkxMTYgMTggMTJaIi8+PC9zdmc+'); --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%), @@ -183,9 +184,36 @@ border: 1px var(--table-border-color) solid !important; } + .row-index > div { + width: 45px; + } + .current-song { background: var(--table-row-hover-bg); - border: 1px solid var(--primary-color) !important; + + .row-index > ::after { + @keyframes pulse { + 0% { + opacity: 0.5; + } + 50% { + opacity: 1; + } + 100% { + opacity: 0.5; + } + } + + position: absolute; + right: 0px; + height: 18px; + width: 18px; + content: ''; + background-color: var(--primary-color); + mask-image: var(--current-song-image); + -webkit-mask-image: var(--current-song-image); + animation: pulse 3s infinite; + } .current-song-child { color: var(--primary-color) !important; From fb1f80fa4b654b3516dade8532f8abae8c5b7fd7 Mon Sep 17 00:00:00 2001 From: Kendall Garner <17521368+kgarner7@users.noreply.github.com> Date: Mon, 9 Oct 2023 18:40:40 -0700 Subject: [PATCH 03/16] don't use absolute position, support album track number --- .../components/virtual-table/index.tsx | 4 +- .../components/album-detail-content.tsx | 1 + src/renderer/themes/default.scss | 52 +++++++++---------- 3 files changed, 27 insertions(+), 30 deletions(-) diff --git a/src/renderer/components/virtual-table/index.tsx b/src/renderer/components/virtual-table/index.tsx index 881d87811..0478b7c73 100644 --- a/src/renderer/components/virtual-table/index.tsx +++ b/src/renderer/components/virtual-table/index.tsx @@ -269,7 +269,7 @@ const tableColumns: { [key: string]: ColDef } = { valueGetter: (params) => { return (params.node?.rowIndex || 0) + 1; }, - width: 71, + width: 80, }, songCount: { cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }), @@ -313,7 +313,7 @@ const tableColumns: { [key: string]: ColDef } = { }, trackNumber: { cellClass: 'track-number', - cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }), + cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'right' }), colId: TableColumn.TRACK_NUMBER, field: 'trackNumber', headerComponent: (params: IHeaderParams) => diff --git a/src/renderer/features/albums/components/album-detail-content.tsx b/src/renderer/features/albums/components/album-detail-content.tsx index 04ac7361f..2e9e65265 100644 --- a/src/renderer/features/albums/components/album-detail-content.tsx +++ b/src/renderer/features/albums/components/album-detail-content.tsx @@ -359,6 +359,7 @@ export const AlbumDetailContent = ({ tableRef, background }: AlbumDetailContentP suppressLoadingOverlay suppressRowDrag autoFitColumns={tableConfig.autoFit} + className="album-table" columnDefs={columnDefs} enableCellChangeFlash={false} fullWidthCellRenderer={FullWidthDiscCell} diff --git a/src/renderer/themes/default.scss b/src/renderer/themes/default.scss index 5b12ab45e..8c19e2065 100644 --- a/src/renderer/themes/default.scss +++ b/src/renderer/themes/default.scss @@ -184,39 +184,35 @@ border: 1px var(--table-border-color) solid !important; } - .row-index > div { - width: 45px; - } - .current-song { background: var(--table-row-hover-bg); - .row-index > ::after { - @keyframes pulse { - 0% { - opacity: 0.5; - } - 50% { - opacity: 1; - } - 100% { - opacity: 0.5; - } - } - - position: absolute; - right: 0px; - height: 18px; - width: 18px; - content: ''; - background-color: var(--primary-color); - mask-image: var(--current-song-image); - -webkit-mask-image: var(--current-song-image); - animation: pulse 3s infinite; - } - .current-song-child { color: var(--primary-color) !important; } } + + .current-song > .row-index > ::before, + .album-table .current-song .track-number > ::before { + @keyframes pulse { + 0% { + opacity: 0.5; + } + 50% { + opacity: 1; + } + 100% { + opacity: 0.5; + } + } + display: block; + margin-right: 3px; + height: 19px; + width: 19px; + content: ''; + background-color: var(--primary-color); + mask-image: var(--current-song-image); + -webkit-mask-image: var(--current-song-image); + animation: pulse 3s infinite; + } } From 01d4a6598c5e064b6b2afc03887e306f2fb69b80 Mon Sep 17 00:00:00 2001 From: jeffvli Date: Sat, 7 Oct 2023 16:46:23 -0700 Subject: [PATCH 04/16] Respect order of set-queue function (fix race condition) --- src/main/features/core/player/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/features/core/player/index.ts b/src/main/features/core/player/index.ts index 847f518cf..facd1b1a1 100644 --- a/src/main/features/core/player/index.ts +++ b/src/main/features/core/player/index.ts @@ -112,7 +112,7 @@ ipcMain.on('player-set-queue', async (_event, data: PlayerData, pause?: boolean) try { if (data.queue.current) { - getMpvInstance() + await getMpvInstance() ?.load(data.queue.current.streamUrl, 'replace') .catch((err) => { console.log('MPV failed to load song', err); @@ -120,7 +120,7 @@ ipcMain.on('player-set-queue', async (_event, data: PlayerData, pause?: boolean) }); if (data.queue.next) { - getMpvInstance()?.load(data.queue.next.streamUrl, 'append'); + await getMpvInstance()?.load(data.queue.next.streamUrl, 'append'); } } } catch (err) { From f101426e691857171adea3107ba9b5d92fa1479c Mon Sep 17 00:00:00 2001 From: jeffvli Date: Sat, 7 Oct 2023 17:32:59 -0700 Subject: [PATCH 05/16] Fix table row actions button on album detail and play queue --- .../features/albums/components/album-detail-content.tsx | 7 +++++-- .../features/now-playing/components/play-queue.tsx | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/renderer/features/albums/components/album-detail-content.tsx b/src/renderer/features/albums/components/album-detail-content.tsx index 2e9e65265..df2a23fb5 100644 --- a/src/renderer/features/albums/components/album-detail-content.tsx +++ b/src/renderer/features/albums/components/album-detail-content.tsx @@ -216,7 +216,7 @@ export const AlbumDetailContent = ({ tableRef, background }: AlbumDetailContentP }); }; - const handleContextMenu = useHandleTableContextMenu(LibraryItem.SONG, SONG_CONTEXT_MENU_ITEMS); + const onCellContextMenu = useHandleTableContextMenu(LibraryItem.SONG, SONG_CONTEXT_MENU_ITEMS); const handleRowDoubleClick = (e: RowDoubleClickedEvent) => { if (!e.data || e.node.isFullWidthCell()) return; @@ -361,6 +361,9 @@ export const AlbumDetailContent = ({ tableRef, background }: AlbumDetailContentP autoFitColumns={tableConfig.autoFit} className="album-table" columnDefs={columnDefs} + context={{ + onCellContextMenu, + }} enableCellChangeFlash={false} fullWidthCellRenderer={FullWidthDiscCell} getRowHeight={getRowHeight} @@ -375,7 +378,7 @@ export const AlbumDetailContent = ({ tableRef, background }: AlbumDetailContentP rowClassRules={rowClassRules} rowData={songsRowData} rowSelection="multiple" - onCellContextMenu={handleContextMenu} + onCellContextMenu={onCellContextMenu} onRowDoubleClicked={handleRowDoubleClick} /> diff --git a/src/renderer/features/now-playing/components/play-queue.tsx b/src/renderer/features/now-playing/components/play-queue.tsx index d101588dd..62253305d 100644 --- a/src/renderer/features/now-playing/components/play-queue.tsx +++ b/src/renderer/features/now-playing/components/play-queue.tsx @@ -206,7 +206,7 @@ export const PlayQueue = forwardRef(({ type }: QueueProps, ref: Ref) => { } }, [currentSong, previousSong, tableConfig.followCurrentSong]); - const handleContextMenu = useHandleTableContextMenu(LibraryItem.SONG, QUEUE_CONTEXT_MENU_ITEMS); + const onCellContextMenu = useHandleTableContextMenu(LibraryItem.SONG, QUEUE_CONTEXT_MENU_ITEMS); return ( @@ -218,6 +218,9 @@ export const PlayQueue = forwardRef(({ type }: QueueProps, ref: Ref) => { rowDragMultiRow autoFitColumns={tableConfig.autoFit} columnDefs={columnDefs} + context={{ + onCellContextMenu, + }} deselectOnClickOutside={type === 'fullScreen'} getRowId={(data) => data.data.uniqueId} rowBuffer={50} @@ -225,7 +228,7 @@ export const PlayQueue = forwardRef(({ type }: QueueProps, ref: Ref) => { rowData={queue} rowHeight={tableConfig.rowHeight || 40} suppressCellFocus={type === 'fullScreen'} - onCellContextMenu={handleContextMenu} + onCellContextMenu={onCellContextMenu} onCellDoubleClicked={handleDoubleClick} onColumnMoved={handleColumnChange} onColumnResized={debouncedColumnChange} From 35bb8c14874a5400449b47a52c867cdd9cb400c9 Mon Sep 17 00:00:00 2001 From: jeffvli Date: Sat, 7 Oct 2023 18:11:02 -0700 Subject: [PATCH 06/16] Fix album detail table customizations --- .../virtual-table/table-config-dropdown.tsx | 1 + .../components/album-detail-content.tsx | 52 ++++++++++++++++--- src/renderer/store/settings.store.ts | 6 +++ 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/src/renderer/components/virtual-table/table-config-dropdown.tsx b/src/renderer/components/virtual-table/table-config-dropdown.tsx index 06be7ebcf..fb0dcbcc9 100644 --- a/src/renderer/components/virtual-table/table-config-dropdown.tsx +++ b/src/renderer/components/virtual-table/table-config-dropdown.tsx @@ -87,6 +87,7 @@ export const GENRE_TABLE_COLUMNS = [ ]; interface TableConfigDropdownProps { + // tableRef?: MutableRefObject | null>; type: TableType; } diff --git a/src/renderer/features/albums/components/album-detail-content.tsx b/src/renderer/features/albums/components/album-detail-content.tsx index df2a23fb5..74156c7dc 100644 --- a/src/renderer/features/albums/components/album-detail-content.tsx +++ b/src/renderer/features/albums/components/album-detail-content.tsx @@ -12,9 +12,9 @@ import { AlbumListSort, LibraryItem, QueueSong, SortOrder } from '/@/renderer/ap import { Button, Popover } from '/@/renderer/components'; import { MemoizedSwiperGridCarousel } from '/@/renderer/components/grid-carousel'; import { - getColumnDefs, TableConfigDropdown, VirtualTable, + getColumnDefs, } from '/@/renderer/components/virtual-table'; import { FullWidthDiscCell } from '/@/renderer/components/virtual-table/cells/full-width-disc-cell'; import { useCurrentSongRowStyles } from '/@/renderer/components/virtual-table/hooks/use-current-song-row-styles'; @@ -34,7 +34,11 @@ import { LibraryBackgroundOverlay } from '/@/renderer/features/shared/components import { useContainerQuery } from '/@/renderer/hooks'; import { AppRoute } from '/@/renderer/router/routes'; import { useCurrentServer } from '/@/renderer/store'; -import { usePlayButtonBehavior, useTableSettings } from '/@/renderer/store/settings.store'; +import { + usePlayButtonBehavior, + useSettingsStoreActions, + useTableSettings, +} from '/@/renderer/store/settings.store'; import { Play } from '/@/renderer/types'; const isFullWidthRow = (node: RowNode) => { @@ -65,16 +69,20 @@ export const AlbumDetailContent = ({ tableRef, background }: AlbumDetailContentP const cq = useContainerQuery(); const handlePlayQueueAdd = usePlayQueueAdd(); const tableConfig = useTableSettings('albumDetail'); + const { setTable } = useSettingsStoreActions(); const columnDefs = useMemo(() => getColumnDefs(tableConfig.columns), [tableConfig.columns]); - const getRowHeight = useCallback((params: RowHeightParams) => { - if (isFullWidthRow(params.node)) { - return 45; - } + const getRowHeight = useCallback( + (params: RowHeightParams) => { + if (isFullWidthRow(params.node)) { + return 45; + } - return 60; - }, []); + return tableConfig.rowHeight; + }, + [tableConfig.rowHeight], + ); const songsRowData = useMemo(() => { if (!detailQuery.data?.songs) { @@ -266,6 +274,32 @@ export const AlbumDetailContent = ({ tableRef, background }: AlbumDetailContentP ALBUM_CONTEXT_MENU_ITEMS, ); + const onColumnMoved = useCallback(() => { + const { columnApi } = tableRef?.current || {}; + const columnsOrder = columnApi?.getAllGridColumns(); + + if (!columnsOrder) return; + + const columnsInSettings = tableConfig.columns; + const updatedColumns = []; + for (const column of columnsOrder) { + const columnInSettings = columnsInSettings.find( + (c) => c.column === column.getColDef().colId, + ); + + if (columnInSettings) { + updatedColumns.push({ + ...columnInSettings, + ...(!tableConfig.autoFit && { + width: column.getActualWidth(), + }), + }); + } + } + + setTable('albumDetail', { ...tableConfig, columns: updatedColumns }); + }, [setTable, tableConfig, tableRef]); + const { rowClassRules } = useCurrentSongRowStyles({ tableRef }); return ( @@ -352,6 +386,7 @@ export const AlbumDetailContent = ({ tableRef, background }: AlbumDetailContentP )} diff --git a/src/renderer/store/settings.store.ts b/src/renderer/store/settings.store.ts index 7b455036f..b1650afaa 100644 --- a/src/renderer/store/settings.store.ts +++ b/src/renderer/store/settings.store.ts @@ -196,6 +196,7 @@ export interface SettingsSlice extends SettingsState { reset: () => void; setSettings: (data: Partial) => void; setSidebarItems: (items: SidebarItemType[]) => void; + setTable: (type: TableType, data: DataTableProps) => void; }; } @@ -497,6 +498,11 @@ export const useSettingsStore = create()( state.general.sidebarItems = items; }); }, + setTable: (type: TableType, data: DataTableProps) => { + set((state) => { + state.tables[type] = data; + }); + }, }, ...initialState, })), From 40d40eb1468d27ea9af6788c2e56ee4107239103 Mon Sep 17 00:00:00 2001 From: jeffvli Date: Sat, 7 Oct 2023 19:06:30 -0700 Subject: [PATCH 07/16] Bump to v0.4.1 --- package-lock.json | 4 ++-- package.json | 2 +- release/app/package-lock.json | 4 ++-- release/app/package.json | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 898e470b5..d80a2202a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "feishin", - "version": "0.4.0", + "version": "0.4.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "feishin", - "version": "0.4.0", + "version": "0.4.1", "hasInstallScript": true, "license": "GPL-3.0", "dependencies": { diff --git a/package.json b/package.json index aa621d671..890af11fd 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "feishin", "productName": "Feishin", "description": "Feishin music server", - "version": "0.4.0", + "version": "0.4.1", "scripts": { "build": "concurrently \"npm run build:main\" \"npm run build:renderer\" \"npm run build:remote\"", "build:main": "cross-env NODE_ENV=production TS_NODE_TRANSPILE_ONLY=true webpack --config ./.erb/configs/webpack.config.main.prod.ts", diff --git a/release/app/package-lock.json b/release/app/package-lock.json index 2d080e1f8..c0c67d4e1 100644 --- a/release/app/package-lock.json +++ b/release/app/package-lock.json @@ -1,12 +1,12 @@ { "name": "feishin", - "version": "0.4.0", + "version": "0.4.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "feishin", - "version": "0.4.0", + "version": "0.4.1", "hasInstallScript": true, "license": "GPL-3.0", "dependencies": { diff --git a/release/app/package.json b/release/app/package.json index c2bb54cd5..0ceba24c2 100644 --- a/release/app/package.json +++ b/release/app/package.json @@ -1,6 +1,6 @@ { "name": "feishin", - "version": "0.4.0", + "version": "0.4.1", "description": "", "main": "./dist/main/main.js", "author": { From 1dc1c823de4fd7ac663d2ba002a5616c56317253 Mon Sep 17 00:00:00 2001 From: jeffvli Date: Sat, 7 Oct 2023 19:58:04 -0700 Subject: [PATCH 08/16] Fix opacity mask for unsynced lyrics container --- src/renderer/features/lyrics/unsynchronized-lyrics.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/renderer/features/lyrics/unsynchronized-lyrics.tsx b/src/renderer/features/lyrics/unsynchronized-lyrics.tsx index 023ce859d..23532559d 100644 --- a/src/renderer/features/lyrics/unsynchronized-lyrics.tsx +++ b/src/renderer/features/lyrics/unsynchronized-lyrics.tsx @@ -18,6 +18,14 @@ const UnsynchronizedLyricsContainer = styled.div<{ $gap: number }>` overflow: scroll; transform: translateY(-2rem); + -webkit-mask-image: linear-gradient( + 180deg, + transparent 5%, + rgb(0 0 0 / 100%) 20%, + rgb(0 0 0 / 100%) 85%, + transparent 95% + ); + mask-image: linear-gradient( 180deg, transparent 5%, From bb68e49fcc4b5d2015502ab15fb2381224a4f8d3 Mon Sep 17 00:00:00 2001 From: jeffvli Date: Tue, 17 Oct 2023 05:46:42 -0700 Subject: [PATCH 09/16] Separate sidebar icons to new component - Fixes react render issue --- .../sidebar/components/collapsed-sidebar.tsx | 98 +++------------ .../sidebar/components/sidebar-icon.tsx | 68 ++++++++++ .../features/sidebar/components/sidebar.tsx | 116 ++++-------------- 3 files changed, 109 insertions(+), 173 deletions(-) create mode 100644 src/renderer/features/sidebar/components/sidebar-icon.tsx diff --git a/src/renderer/features/sidebar/components/collapsed-sidebar.tsx b/src/renderer/features/sidebar/components/collapsed-sidebar.tsx index 45371547e..b39f195ea 100644 --- a/src/renderer/features/sidebar/components/collapsed-sidebar.tsx +++ b/src/renderer/features/sidebar/components/collapsed-sidebar.tsx @@ -1,42 +1,16 @@ import { Group, UnstyledButton } from '@mantine/core'; import { motion } from 'framer-motion'; import { useMemo } from 'react'; -import { IconType } from 'react-icons'; -import { - RiUserVoiceLine, - RiMenuFill, - RiFolder3Line, - RiPlayListLine, - RiAlbumLine, - RiHome6Line, - RiMusic2Line, - RiHome6Fill, - RiAlbumFill, - RiMusic2Fill, - RiUserVoiceFill, - RiFlag2Fill, - RiFolder3Fill, - RiPlayListFill, - RiSearchLine, - RiSearchFill, - RiPlayFill, - RiPlayLine, - RiSettings2Fill, - RiSettings2Line, - RiFlag2Line, - RiArrowLeftSLine, - RiArrowRightSLine, -} from 'react-icons/ri'; -import { generatePath, NavLink, useNavigate } from 'react-router-dom'; +import { RiArrowLeftSLine, RiArrowRightSLine, RiMenuFill } from 'react-icons/ri'; +import { NavLink, useNavigate } from 'react-router-dom'; import styled from 'styled-components'; -import { LibraryItem } from '/@/renderer/api/types'; import { DropdownMenu, ScrollArea } from '/@/renderer/components'; +import { CollapsedSidebarButton } from '/@/renderer/features/sidebar/components/collapsed-sidebar-button'; import { CollapsedSidebarItem } from '/@/renderer/features/sidebar/components/collapsed-sidebar-item'; +import { SidebarIcon } from '/@/renderer/features/sidebar/components/sidebar-icon'; import { AppMenu } from '/@/renderer/features/titlebar/components/app-menu'; -import { AppRoute } from '/@/renderer/router/routes'; import { SidebarItemType, useGeneralSettings, useWindowSettings } from '/@/renderer/store'; import { Platform } from '/@/renderer/types'; -import { CollapsedSidebarButton } from '/@/renderer/features/sidebar/components/collapsed-sidebar-button'; const SidebarContainer = styled(motion.div)<{ $windowBarStyle: Platform }>` display: flex; @@ -49,65 +23,18 @@ const SidebarContainer = styled(motion.div)<{ $windowBarStyle: Platform }>` user-select: none; `; -const sidebarItemMap = { - [AppRoute.HOME]: { - activeIcon: RiHome6Fill, - icon: RiHome6Line, - }, - [AppRoute.LIBRARY_ALBUMS]: { - activeIcon: RiAlbumFill, - icon: RiAlbumLine, - }, - [AppRoute.LIBRARY_ALBUM_ARTISTS]: { - activeIcon: RiUserVoiceFill, - icon: RiUserVoiceLine, - }, - [AppRoute.PLAYLISTS]: { - activeIcon: RiPlayListFill, - icon: RiPlayListLine, - }, - [AppRoute.LIBRARY_SONGS]: { - activeIcon: RiMusic2Fill, - icon: RiMusic2Line, - }, - [AppRoute.LIBRARY_FOLDERS]: { - activeIcon: RiFolder3Fill, - icon: RiFolder3Line, - }, - [AppRoute.LIBRARY_GENRES]: { - activeIcon: RiFlag2Fill, - icon: RiFlag2Line, - }, - [generatePath(AppRoute.SEARCH, { itemType: LibraryItem.SONG })]: { - activeIcon: RiSearchFill, - icon: RiSearchLine, - }, - [AppRoute.SETTINGS]: { - activeIcon: RiSettings2Fill, - icon: RiSettings2Line, - }, - [AppRoute.NOW_PLAYING]: { - activeIcon: RiPlayFill, - icon: RiPlayLine, - }, -}; - export const CollapsedSidebar = () => { const navigate = useNavigate(); const { windowBarStyle } = useWindowSettings(); const { sidebarItems, sidebarCollapsedNavigation } = useGeneralSettings(); - const sidebarItemsWithRoute: (SidebarItemType & { - activeIcon: IconType; - icon: IconType; - })[] = useMemo(() => { + const sidebarItemsWithRoute: SidebarItemType[] = useMemo(() => { if (!sidebarItems) return []; const items = sidebarItems .filter((item) => !item.disabled) .map((item) => ({ ...item, - ...sidebarItemMap[item.route as keyof typeof sidebarItemMap], })); return items; @@ -157,9 +84,20 @@ export const CollapsedSidebar = () => { {sidebarItemsWithRoute.map((item) => ( } + activeIcon={ + + } component={NavLink} - icon={} + icon={ + + } label={item.label} route={item.route} to={item.route} diff --git a/src/renderer/features/sidebar/components/sidebar-icon.tsx b/src/renderer/features/sidebar/components/sidebar-icon.tsx new file mode 100644 index 000000000..7d48e7236 --- /dev/null +++ b/src/renderer/features/sidebar/components/sidebar-icon.tsx @@ -0,0 +1,68 @@ +import { + RiAlbumFill, + RiAlbumLine, + RiFlag2Fill, + RiFlag2Line, + RiFolder3Fill, + RiFolder3Line, + RiHome6Fill, + RiHome6Line, + RiMusic2Fill, + RiMusic2Line, + RiPlayFill, + RiPlayLine, + RiPlayListFill, + RiPlayListLine, + RiSearchFill, + RiSearchLine, + RiSettings2Fill, + RiSettings2Line, + RiUserVoiceFill, + RiUserVoiceLine, +} from 'react-icons/ri'; +import { AppRoute } from '/@/renderer/router/routes'; +import { generatePath } from 'react-router'; +import { LibraryItem } from '/@/renderer/api/types'; + +interface SidebarIconProps { + active?: boolean; + route: string; + size?: string; +} + +export const SidebarIcon = ({ active, route, size }: SidebarIconProps) => { + switch (route) { + case AppRoute.HOME: + if (active) return ; + return ; + case AppRoute.LIBRARY_ALBUMS: + if (active) return ; + return ; + case AppRoute.LIBRARY_ARTISTS: + if (active) return ; + return ; + case AppRoute.PLAYLISTS: + if (active) return ; + return ; + case AppRoute.LIBRARY_SONGS: + if (active) return ; + return ; + case AppRoute.LIBRARY_FOLDERS: + if (active) return ; + return ; + case AppRoute.LIBRARY_GENRES: + if (active) return ; + return ; + case generatePath(AppRoute.SEARCH, { itemType: LibraryItem.SONG }): + if (active) return ; + return ; + case AppRoute.SETTINGS: + if (active) return ; + return ; + case AppRoute.NOW_PLAYING: + if (active) return ; + return ; + default: + return ; + } +}; diff --git a/src/renderer/features/sidebar/components/sidebar.tsx b/src/renderer/features/sidebar/components/sidebar.tsx index c3784db6d..810e4c07f 100644 --- a/src/renderer/features/sidebar/components/sidebar.tsx +++ b/src/renderer/features/sidebar/components/sidebar.tsx @@ -1,45 +1,20 @@ -import { MouseEvent, useMemo } from 'react'; import { Box, Center, Divider, Group, Stack } from '@mantine/core'; import { closeAllModals, openModal } from '@mantine/modals'; import { AnimatePresence, motion } from 'framer-motion'; -import { IconType } from 'react-icons'; -import { - RiAddFill, - RiAlbumFill, - RiAlbumLine, - RiArrowDownSLine, - RiDiscLine, - RiFlag2Fill, - RiFlagLine, - RiFolder3Fill, - RiFolder3Line, - RiHome6Fill, - RiHome6Line, - RiListUnordered, - RiMusic2Fill, - RiMusic2Line, - RiPlayLine, - RiSearchFill, - RiUserVoiceFill, - RiUserVoiceLine, - RiSearchLine, - RiPlayFill, - RiSettings2Line, - RiSettings2Fill, - RiPlayListLine, - RiPlayListFill, -} from 'react-icons/ri'; -import { generatePath, Link, useLocation } from 'react-router-dom'; +import { MouseEvent, useMemo } from 'react'; +import { RiAddFill, RiArrowDownSLine, RiDiscLine, RiListUnordered } from 'react-icons/ri'; +import { Link, useLocation } from 'react-router-dom'; import styled from 'styled-components'; import { SidebarItemType, useGeneralSettings, useWindowSettings, } from '../../../store/settings.store'; -import { LibraryItem, PlaylistListSort, ServerType, SortOrder } from '/@/renderer/api/types'; +import { PlaylistListSort, ServerType, SortOrder } from '/@/renderer/api/types'; import { Button, MotionStack, Spinner, Tooltip } from '/@/renderer/components'; import { CreatePlaylistForm, usePlaylistList } from '/@/renderer/features/playlists'; import { ActionBar } from '/@/renderer/features/sidebar/components/action-bar'; +import { SidebarIcon } from '/@/renderer/features/sidebar/components/sidebar-icon'; import { SidebarItem } from '/@/renderer/features/sidebar/components/sidebar-item'; import { SidebarPlaylistList } from '/@/renderer/features/sidebar/components/sidebar-playlist-list'; import { useContainerQuery } from '/@/renderer/hooks'; @@ -92,49 +67,6 @@ const SidebarImage = styled.img` background: var(--placeholder-bg); `; -const sidebarItemMap = { - [AppRoute.HOME]: { - activeIcon: RiHome6Fill, - icon: RiHome6Line, - }, - [AppRoute.LIBRARY_ALBUMS]: { - activeIcon: RiAlbumFill, - icon: RiAlbumLine, - }, - [AppRoute.LIBRARY_ALBUM_ARTISTS]: { - activeIcon: RiUserVoiceFill, - icon: RiUserVoiceLine, - }, - [AppRoute.PLAYLISTS]: { - activeIcon: RiPlayListFill, - icon: RiPlayListLine, - }, - [AppRoute.LIBRARY_SONGS]: { - activeIcon: RiMusic2Fill, - icon: RiMusic2Line, - }, - [AppRoute.LIBRARY_FOLDERS]: { - activeIcon: RiFolder3Fill, - icon: RiFolder3Line, - }, - [AppRoute.LIBRARY_GENRES]: { - activeIcon: RiFlag2Fill, - icon: RiFlagLine, - }, - [generatePath(AppRoute.SEARCH, { itemType: LibraryItem.SONG })]: { - activeIcon: RiSearchFill, - icon: RiSearchLine, - }, - [AppRoute.SETTINGS]: { - activeIcon: RiSettings2Fill, - icon: RiSettings2Line, - }, - [AppRoute.NOW_PLAYING]: { - activeIcon: RiPlayFill, - icon: RiPlayLine, - }, -}; - export const Sidebar = () => { const location = useLocation(); const sidebar = useSidebarStore(); @@ -180,17 +112,13 @@ export const Sidebar = () => { const { sidebarItems } = useGeneralSettings(); - const sidebarItemsWithRoute: (SidebarItemType & { - activeIcon: IconType; - icon: IconType; - })[] = useMemo(() => { + const sidebarItemsWithRoute: SidebarItemType[] = useMemo(() => { if (!sidebarItems) return []; const items = sidebarItems .filter((item) => !item.disabled) .map((item) => ({ ...item, - ...sidebarItemMap[item.route as keyof typeof sidebarItemMap], })); return items; @@ -214,21 +142,23 @@ export const Sidebar = () => { sx={{ maxHeight: showImage ? `calc(100% - ${sidebar.leftWidth})` : '100%' }} > - {sidebarItemsWithRoute.map((item) => ( - - - {location.pathname === item.route ? ( - - ) : ( - - )} - {item.label} - - - ))} + {sidebarItemsWithRoute.map((item) => { + return ( + + + + {item.label} + + + ); + })} Date: Wed, 18 Oct 2023 15:05:07 -0700 Subject: [PATCH 10/16] Add app focus hook --- src/renderer/hooks/index.ts | 1 + src/renderer/hooks/use-app-focus.ts | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 src/renderer/hooks/use-app-focus.ts diff --git a/src/renderer/hooks/index.ts b/src/renderer/hooks/index.ts index e0f836c14..82dd033a4 100644 --- a/src/renderer/hooks/index.ts +++ b/src/renderer/hooks/index.ts @@ -4,3 +4,4 @@ export * from './use-should-pad-titlebar'; export * from './use-container-query'; export * from './use-fast-average-color'; export * from './use-hide-scrollbar'; +export * from './use-app-focus'; diff --git a/src/renderer/hooks/use-app-focus.ts b/src/renderer/hooks/use-app-focus.ts new file mode 100644 index 000000000..72e163f88 --- /dev/null +++ b/src/renderer/hooks/use-app-focus.ts @@ -0,0 +1,22 @@ +// From https://learnersbucket.com/examples/interview/usehasfocus-hook-in-react/ + +import { useState, useEffect } from 'react'; + +export const useAppFocus = () => { + const [focus, setFocus] = useState(document.hasFocus()); + + useEffect(() => { + const onFocus = () => setFocus(true); + const onBlur = () => setFocus(false); + + window.addEventListener('focus', onFocus); + window.addEventListener('blur', onBlur); + + return () => { + window.removeEventListener('focus', onFocus); + window.removeEventListener('blur', onBlur); + }; + }, []); + + return focus; +}; From 2ec42fe83693a600ad8a55a497ae010ce0a6db47 Mon Sep 17 00:00:00 2001 From: jeffvli Date: Wed, 18 Oct 2023 15:06:44 -0700 Subject: [PATCH 11/16] Remove css play image --- src/renderer/themes/default.scss | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/src/renderer/themes/default.scss b/src/renderer/themes/default.scss index 8c19e2065..44410c909 100644 --- a/src/renderer/themes/default.scss +++ b/src/renderer/themes/default.scss @@ -101,7 +101,6 @@ --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,PHN2ZyBzdHJva2U9ImN1cnJlbnRDb2xvciIgZmlsbD0iY3VycmVudENvbG9yIiBzdHJva2Utd2lkdGg9IjAiIHZpZXdCb3g9IjAgMCAyNCAyNCIgaGVpZ2h0PSIxLjJyZW0iIHdpZHRoPSIxLjJyZW0iIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTIgMTYuMDAwMUg1Ljg4ODg5TDExLjE4MzQgMjAuMzMxOUMxMS4yNzI3IDIwLjQwNSAxMS4zODQ2IDIwLjQ0NDkgMTEuNSAyMC40NDQ5QzExLjc3NjEgMjAuNDQ0OSAxMiAyMC4yMjExIDEyIDE5Ljk0NDlWNC4wNTUxOUMxMiAzLjkzOTc3IDExLjk2MDEgMy44Mjc5IDExLjg4NyAzLjczODU3QzExLjcxMjEgMy41MjQ4NSAxMS4zOTcxIDMuNDkzMzUgMTEuMTgzNCAzLjY2ODIxTDUuODg4ODkgOC4wMDAwN0gyQzEuNDQ3NzIgOC4wMDAwNyAxIDguNDQ3NzggMSA5LjAwMDA3VjE1LjAwMDFDMSAxNS41NTI0IDEuNDQ3NzIgMTYuMDAwMSAyIDE2LjAwMDFaTTIzIDEyQzIzIDE1LjI5MiAyMS41NTM5IDE4LjI0NjMgMTkuMjYyMiAyMC4yNjIyTDE3Ljg0NDUgMTguODQ0NEMxOS43NzU4IDE3LjE5MzcgMjEgMTQuNzM5OCAyMSAxMkMyMSA5LjI2MDE2IDE5Ljc3NTggNi44MDYyOSAxNy44NDQ1IDUuMTU1NTdMMTkuMjYyMiAzLjczNzc5QzIxLjU1MzkgNS43NTM2OCAyMyA4LjcwNzk1IDIzIDEyWk0xOCAxMkMxOCAxMC4wODgzIDE3LjEwNiA4LjM4NTQ4IDE1LjcxMzMgNy4yODY3M0wxNC4yODQyIDguNzE1ODRDMTUuMzIxMyA5LjQzODU1IDE2IDEwLjY0IDE2IDEyQzE2IDEzLjM2IDE1LjMyMTMgMTQuNTYxNCAxNC4yODQyIDE1LjI4NDFMMTUuNzEzMyAxNi43MTMyQzE3LjEwNiAxNS42MTQ1IDE4IDEzLjkxMTYgMTggMTJaIi8+PC9zdmc+'); --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%), @@ -191,28 +190,4 @@ color: var(--primary-color) !important; } } - - .current-song > .row-index > ::before, - .album-table .current-song .track-number > ::before { - @keyframes pulse { - 0% { - opacity: 0.5; - } - 50% { - opacity: 1; - } - 100% { - opacity: 0.5; - } - } - display: block; - margin-right: 3px; - height: 19px; - width: 19px; - content: ''; - background-color: var(--primary-color); - mask-image: var(--current-song-image); - -webkit-mask-image: var(--current-song-image); - animation: pulse 3s infinite; - } } From c0dce3c8651dc35f8363f54e5ae6554860c524b9 Mon Sep 17 00:00:00 2001 From: jeffvli Date: Wed, 18 Oct 2023 15:43:58 -0700 Subject: [PATCH 12/16] Add player status as cell refresh condition for queue --- src/renderer/features/now-playing/components/play-queue.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/renderer/features/now-playing/components/play-queue.tsx b/src/renderer/features/now-playing/components/play-queue.tsx index 62253305d..6fbb1110d 100644 --- a/src/renderer/features/now-playing/components/play-queue.tsx +++ b/src/renderer/features/now-playing/components/play-queue.tsx @@ -11,6 +11,7 @@ import '@ag-grid-community/styles/ag-theme-alpine.css'; import { useAppStoreActions, useCurrentSong, + useCurrentStatus, useDefaultQueue, usePlayerControls, usePreviousSong, @@ -49,6 +50,7 @@ export const PlayQueue = forwardRef(({ type }: QueueProps, ref: Ref) => { const { reorderQueue, setCurrentTrack } = useQueueControls(); const currentSong = useCurrentSong(); const previousSong = usePreviousSong(); + const status = useCurrentStatus(); const { setSettings } = useSettingsStoreActions(); const { setAppStore } = useAppStoreActions(); const tableConfig = useTableSettings(type); @@ -204,7 +206,7 @@ export const PlayQueue = forwardRef(({ type }: QueueProps, ref: Ref) => { } } } - }, [currentSong, previousSong, tableConfig.followCurrentSong]); + }, [currentSong, previousSong, tableConfig.followCurrentSong, status]); const onCellContextMenu = useHandleTableContextMenu(LibraryItem.SONG, QUEUE_CONTEXT_MENU_ITEMS); From 677d858f3bced906e02dcc0312744ced6af588ed Mon Sep 17 00:00:00 2001 From: jeffvli Date: Wed, 18 Oct 2023 17:32:46 -0700 Subject: [PATCH 13/16] Add current song images --- src/renderer/media/play-static.svg | 7 +++++++ src/renderer/media/play.svg | 15 +++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 src/renderer/media/play-static.svg create mode 100644 src/renderer/media/play.svg diff --git a/src/renderer/media/play-static.svg b/src/renderer/media/play-static.svg new file mode 100644 index 000000000..acee23633 --- /dev/null +++ b/src/renderer/media/play-static.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/renderer/media/play.svg b/src/renderer/media/play.svg new file mode 100644 index 000000000..f1808b5d0 --- /dev/null +++ b/src/renderer/media/play.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file From 59a21e1e6aaba3283fc112c381dde4fe823b07b9 Mon Sep 17 00:00:00 2001 From: jeffvli Date: Wed, 18 Oct 2023 17:33:51 -0700 Subject: [PATCH 14/16] 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); + } } From b304d42ff20b78c3772afea29c9f0e5a73d5f94a Mon Sep 17 00:00:00 2001 From: jeffvli Date: Wed, 18 Oct 2023 17:56:35 -0700 Subject: [PATCH 15/16] Revert row index cell width --- src/renderer/components/virtual-table/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/components/virtual-table/index.tsx b/src/renderer/components/virtual-table/index.tsx index e67a5fadb..272b3c7bf 100644 --- a/src/renderer/components/virtual-table/index.tsx +++ b/src/renderer/components/virtual-table/index.tsx @@ -282,7 +282,7 @@ const tableColumns: { [key: string]: ColDef } = { valueGetter: (params) => { return (params.node?.rowIndex || 0) + 1; }, - width: 80, + width: 65, }, songCount: { cellRenderer: (params: ICellRendererParams) => GenericCell(params, { position: 'center' }), From 4f5543561fcbc97a62a18ccea5e602bffeadf937 Mon Sep 17 00:00:00 2001 From: jeffvli Date: Wed, 18 Oct 2023 18:30:51 -0700 Subject: [PATCH 16/16] Remove animated svg on browser --- src/renderer/components/virtual-table/index.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/renderer/components/virtual-table/index.tsx b/src/renderer/components/virtual-table/index.tsx index 272b3c7bf..9ff519926 100644 --- a/src/renderer/components/virtual-table/index.tsx +++ b/src/renderer/components/virtual-table/index.tsx @@ -19,6 +19,7 @@ import dayjs from 'dayjs'; import relativeTime from 'dayjs/plugin/relativeTime'; import formatDuration from 'format-duration'; import { AnimatePresence } from 'framer-motion'; +import isElectron from 'is-electron'; import { generatePath } from 'react-router'; import styled from 'styled-components'; import { AlbumArtistCell } from '/@/renderer/components/virtual-table/cells/album-artist-cell'; @@ -268,7 +269,7 @@ const tableColumns: { [key: string]: ColDef } = { cellClass: 'row-index', cellClassRules: { focused: (params) => { - return params.context?.isFocused; + return isElectron() && params.context?.isFocused; }, playing: (params) => { return params.context?.status === PlayerStatus.PLAYING; @@ -341,7 +342,7 @@ const tableColumns: { [key: string]: ColDef } = { cellClass: 'row-index', cellClassRules: { focused: (params) => { - return params.context?.isFocused; + return isElectron() && params.context?.isFocused; }, playing: (params) => { return params.context?.status === PlayerStatus.PLAYING;