Skip to content

Commit

Permalink
feat: collections now use list search
Browse files Browse the repository at this point in the history
  • Loading branch information
Tormak9970 committed Dec 17, 2023
1 parent a246eb2 commit 35f0b73
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 17 deletions.
16 changes: 8 additions & 8 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 33 additions & 3 deletions src/components/filters/FilterOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { FaTag, FaTags, FaUser, FaCompactDisc, FaListCheck, FaSteam } from "reac
import { FaUserFriends, FaQuestionCircle } from "react-icons/fa";
import { MdApps } from "react-icons/md";
import { IoGameController } from "react-icons/io5";
import { BsWindow } from "react-icons/bs";
import { BsCollectionFill, BsWindow } from "react-icons/bs";
import { IconType } from "react-icons/lib";

import { FilterType, ReviewScoreType, TabFilterSettings, ThresholdCondition, TimeUnit, compatCategoryToLabel } from "./Filters";
Expand All @@ -29,6 +29,7 @@ import { IncludeCategories } from "../../lib/Utils";
import { Slider } from '../generic/Slider';
import { STEAM_FEATURES_ID_MAP, STEAM_FEATURES_TO_RENDER } from "./SteamFeatures";
import { MicroSDeckInterop } from '../../lib/controllers/MicroSDeckInterop';
import { ListSearchDropdown } from "../modals/ListSearchModal";

type FilterOptionsProps<T extends FilterType> = {
index: number,
Expand All @@ -55,11 +56,31 @@ function getAppIconType(entry: any): IconType {
}
}


/**
* Gets an entry icon for a collection based on if its user made.
* @param entry The collection entry.
* @returns The icon for the collection.
*/
function getCollectionIcon(entry: any): IconType {
const collection = collectionStore.userCollections.find((collection: SteamCollection) => collection.id === entry.data);
if (collection?.bIsEditable) {
return FaUser;
} else {
return FaSteam;
}
}

/**
* The options for a collection filter.
*/
const CollectionFilterOptions: VFC<FilterOptionsProps<'collection'>> = ({ index, setContainingGroupFilters, filter, containingGroupFilters }) => {
const collectionDropdownOptions: DropdownOption[] = collectionStore.userCollections.map((collection: { displayName: string; id: string; }) => { return { label: collection.displayName, data: collection.id }; });
const collectionDropdownOptions: SingleDropdownOption[] = collectionStore.userCollections.map((collection: SteamCollection) => {
return {
label: collection.displayName,
data: collection.id
};
});

function onChange(data: SingleDropdownOption) {
const updatedFilter = { ...filter };
Expand All @@ -73,7 +94,16 @@ const CollectionFilterOptions: VFC<FilterOptionsProps<'collection'>> = ({ index,
return (
<Field
label="Selected Collection"
description={<Dropdown rgOptions={collectionDropdownOptions} selectedOption={filter.params.id} onChange={onChange} />}
description={
<ListSearchDropdown
entryLabel="Collections"
rgOptions={collectionDropdownOptions}
selectedOption={filter.params.id}
onChange={onChange}
TriggerIcon={BsCollectionFill}
determineEntryIcon={getCollectionIcon}
/>
}
/>
);
};
Expand Down
2 changes: 1 addition & 1 deletion src/components/filters/Filters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ type FilterFunction = (params: FilterParams<FilterType>, appOverview: SteamAppOv
* Checking and settings defaults in component is unnecessary
*/
export const FilterDefaultParams: { [key in FilterType]: FilterParams<key> } = {
"collection": { id: "", name: "" },
"collection": { id: "favorite", name: "Favorites" },
"installed": { installed: true },
"regex": { regex: "" },
"friends": { friends: [], mode: 'and' },
Expand Down
4 changes: 2 additions & 2 deletions src/components/modals/EditTabModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
showModal
} from "decky-frontend-lib";
import { useState, VFC, useEffect, Fragment } from "react";
import { FilterType, TabFilterSettings, isValidParams } from "../filters/Filters";
import { FilterDefaultParams, FilterType, TabFilterSettings, isValidParams } from "../filters/Filters";
import { PythonInterop } from "../../lib/controllers/PythonInterop";
import { TabMasterContextProvider } from "../../state/TabMasterContext";
import { TabMasterManager } from "../../state/TabMasterManager";
Expand Down Expand Up @@ -99,7 +99,7 @@ export const EditTabModal: VFC<EditTabModalProps> = ({ closeModal, onConfirm, ta
updatedFilters.push({
type: "collection",
inverted: false,
params: { id: "", name: "" }
params: FilterDefaultParams.collection
});
setTopLevelFilters(updatedFilters);
}
Expand Down
35 changes: 33 additions & 2 deletions src/components/modals/ListSearchModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ export const ListSearchModal: VFC<ListSearchModalProps> = ({ rgOptions: list, en
);
};

export type ListSearchTrigger = {
export type ListSearchTriggerProps = {
entryLabel: string,
labelOverride: string,
options: SingleDropdownOption[],
Expand All @@ -127,7 +127,7 @@ export type ListSearchTrigger = {
disabled: boolean
}

export function ListSearchTrigger({ entryLabel, labelOverride, options, onChange, TriggerIcon, determineEntryIcon, disabled }: ListSearchTrigger) {
export function ListSearchTrigger({ entryLabel, labelOverride, options, onChange, TriggerIcon, determineEntryIcon, disabled }: ListSearchTriggerProps) {
const ModalWrapper: VFC<BaseModalProps> = ({ onSelectOption, rgOptions, closeModal }: BaseModalProps) => {
return <ListSearchModal entryLabel={entryLabel} rgOptions={rgOptions!} onSelectOption={onSelectOption} determineEntryIcon={determineEntryIcon} closeModal={closeModal} />
}
Expand All @@ -143,3 +143,34 @@ export function ListSearchTrigger({ entryLabel, labelOverride, options, onChange
/>
);
}

export type ListSearchDropdownProps = {
entryLabel: string,
rgOptions: SingleDropdownOption[],
selectedOption: any,
onChange: (option: SingleDropdownOption) => void,
TriggerIcon: IconType,
determineEntryIcon: (entry?: any) => IconType,
disabled?: boolean
}

export function ListSearchDropdown({ entryLabel, rgOptions, selectedOption, onChange, TriggerIcon, determineEntryIcon, disabled }: ListSearchDropdownProps) {
const [selected, setSelected] = useState<SingleDropdownOption>(rgOptions.find((option: SingleDropdownOption) => option.data === selectedOption)!);

function onChangeWrapper(data: SingleDropdownOption) {
setSelected(data);
onChange(data);
}

return (
<ListSearchTrigger
entryLabel={entryLabel}
options={rgOptions}
onChange={onChangeWrapper}
labelOverride={selected.label as string}
disabled={disabled ?? false}
TriggerIcon={TriggerIcon}
determineEntryIcon={determineEntryIcon}
/>
);
}
2 changes: 1 addition & 1 deletion src/components/multi-selects/ModeMultiSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export const ModeMultiSelect:VFC<ModeMultiSelectProps> = ({ options, selected, f
labelOverride={dropdownSelected.label!}
disabled={available.length == 0 || (!!maxOptions && selected.length == maxOptions)}
TriggerIcon={TriggerIcon}
determineEntryIcon={(entry) => { return determineEntryIcon ? determineEntryIcon(entry) : EntryIcon}}
determineEntryIcon={(entry) => { return (determineEntryIcon ? determineEntryIcon(entry) : EntryIcon) as IconType }}
/>
</Focusable>
<Focusable style={{
Expand Down

0 comments on commit 35f0b73

Please sign in to comment.