From 01cbf9ec8f6f0d33c4ca7d715e4f8ed56f7baef0 Mon Sep 17 00:00:00 2001 From: Colin Date: Tue, 30 Jul 2024 07:54:45 +0100 Subject: [PATCH] fix: Game list sortable columns --- package.json | 2 +- src/renderer/components/GameListHeader.tsx | 88 ++++++++++++++++------ src/renderer/store/search/slice.ts | 7 +- static/window/styles/core.css | 4 +- 4 files changed, 70 insertions(+), 31 deletions(-) diff --git a/package.json b/package.json index 43576a263..8caaf46d1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "flashpoint-launcher", - "version": "13.0.2", + "version": "13.1.0", "description": "A desktop application used to browse, manage and play games from Flashpoint Archive", "main": "build/main/index.js", "config": { diff --git a/src/renderer/components/GameListHeader.tsx b/src/renderer/components/GameListHeader.tsx index 7de0cdb0c..a608a30c1 100644 --- a/src/renderer/components/GameListHeader.tsx +++ b/src/renderer/components/GameListHeader.tsx @@ -1,8 +1,11 @@ import { WithPreferencesProps } from '@renderer/containers/withPreferences'; import { updatePreferencesData } from '@shared/preferences/util'; -import { GameOrderBy } from 'flashpoint-launcher'; +import { GameOrderBy, GameOrderDirection } from 'flashpoint-launcher'; import { useMemo } from 'react'; import { OpenIcon } from './OpenIcon'; +import { useView } from '@renderer/hooks/search'; +import { useDispatch } from 'react-redux'; +import { searchActions } from '@renderer/store/search/slice'; export type GameListHeaderProps = WithPreferencesProps & { showExtremeIcon: boolean; @@ -11,37 +14,83 @@ export type GameListHeaderProps = WithPreferencesProps & { // Header on top of the GameList. It contains the resizable columns that decide how wide each column is. export function GameListHeader(props: GameListHeaderProps) { const { gamesOrderBy, gamesOrder } = props.preferencesData; + const currentView = useView(); + const dispatch = useDispatch(); + + const onToggleSort = (key: GameOrderBy) => { + if (currentView.orderBy === key) { + const newDirection = currentView.orderReverse === 'ASC' ? 'DESC' : 'ASC'; + dispatch(searchActions.setOrderReverse({ + view: currentView.id, + value: newDirection, + })); + } else { + dispatch(searchActions.setOrderBy({ + view: currentView.id, + value: key, + })); + dispatch(searchActions.setOrderReverse({ + view: currentView.id, + value: 'ASC', + })); + } + if (currentView.selectedPlaylist !== undefined && currentView.advancedFilter.playlistOrder) { + dispatch(searchActions.setAdvancedFilter({ + view: currentView.id, + filter: { + ...currentView.advancedFilter, + playlistOrder: false, + }, + })); + } + }; + + const curOrderBy = (currentView.selectedPlaylist !== undefined && currentView.advancedFilter.playlistOrder) ? + undefined : + currentView.orderBy; return useMemo(() => (
{ props.showExtremeIcon ? ( ) : undefined} - +
+ onToggleSort={onToggleSort} + direction={currentView.orderReverse} + value={curOrderBy} /> + onToggleSort={onToggleSort} + direction={currentView.orderReverse} + value={curOrderBy} /> + onToggleSort={onToggleSort} + direction={currentView.orderReverse} + value={curOrderBy} /> {/* */}
- ), [gamesOrderBy, gamesOrder]); + ), [currentView.orderReverse, currentView.orderBy, currentView.selectedPlaylist, currentView.advancedFilter.playlistOrder]); } type ColumnProps = { @@ -67,19 +116,25 @@ function Column(props: ColumnProps) { ); } -type SortableColumnProps = ColumnProps & WithPreferencesProps & { +type SortableColumnProps = ColumnProps & { /** GameOrderBy key */ orderBy: GameOrderBy; + /** Currently selected value */ + value?: GameOrderBy; + /** Current selected direction */ + direction: GameOrderDirection; + /** When toggled */ + onToggleSort: (key: GameOrderBy) => void; }; function SortableColumn(props: SortableColumnProps) { + const { orderBy, value, direction, onToggleSort } = props; const className = 'game-list-header-column'; - const { gamesOrderBy, gamesOrder } = props.preferencesData; - const active = gamesOrderBy === props.orderBy; + const active = orderBy === value; const showDivider = !props.hideDivider; // Render return ( -
toggleSorting(props.orderBy)}> +
onToggleSort(orderBy)}> { showDivider ? (
) : undefined } @@ -88,22 +143,11 @@ function SortableColumn(props: SortableColumnProps) { { active ? (
): undefined }
); - -} - -function toggleSorting(orderBy: GameOrderBy) { - const { gamesOrderBy, gamesOrder } = window.Shared.preferences.data; - const direction = gamesOrderBy === orderBy && gamesOrder === 'ASC'? 'DESC' : 'ASC'; - - updatePreferencesData({ - gamesOrderBy: orderBy, - gamesOrder: direction - }); } diff --git a/src/renderer/store/search/slice.ts b/src/renderer/store/search/slice.ts index 79d5dc412..f0213f02a 100644 --- a/src/renderer/store/search/slice.ts +++ b/src/renderer/store/search/slice.ts @@ -300,7 +300,6 @@ const searchSlice = createSlice({ } }, createViews(state: SearchState, { payload }: PayloadAction) { - console.log(`Creating views for: ${payload}`); const generalState = state.views[GENERAL_VIEW_ID]; // Clear existing views except general state.views = { @@ -398,7 +397,6 @@ const searchSlice = createSlice({ requestRange(state: SearchState, { payload }: PayloadAction) { const view = state.views[payload.view]; const { start, count, searchId } = payload; - console.log(`Range requested - ${start} - len:${count}`); if (view && view.data.searchId === searchId) { // Ignore outdated requests // Iterate over requested page numbers const end = start + count; @@ -412,7 +410,7 @@ const searchSlice = createSlice({ offset: view.data.keyset[i-1], page: i, }; - console.log(`requested page ${i}`); + console.log(`Requested page ${i}`); // Fire and forget request, registered handler will properly handle response window.Shared.back.send(BackIn.BROWSE_VIEW_PAGE, searchFilter); } @@ -531,7 +529,6 @@ const searchSlice = createSlice({ if (data.page !== undefined && data.games) { if (data.page === 0 && data.games.length === 0) { // No games in first page, must be empty results - console.log('no results'); view.data.total = 0; } else { const startIdx = VIEW_PAGE_SIZE * data.page; @@ -543,8 +540,6 @@ const searchSlice = createSlice({ view.data.metaState = RequestState.RECEIVED; } } - - console.log(`PERF - addData - ${Date.now() - startTime}ms`); } }, }); diff --git a/static/window/styles/core.css b/static/window/styles/core.css index 26a84baaf..3cd3c46e3 100644 --- a/static/window/styles/core.css +++ b/static/window/styles/core.css @@ -3598,8 +3598,8 @@ body { .searchable-select-dropdown-results { overflow-y: auto; - height: 50vh; - width: 25vw; + height: 45vh; + width: 22vw; } .searchable-select-dropdown-item {