summaryrefslogtreecommitdiff
path: root/frontend/src/components/store/Store.tsx
diff options
context:
space:
mode:
authorParty Wumpus <48649272+PartyWumpus@users.noreply.github.com>2024-02-07 17:38:08 +0000
committerAAGaming <aagaming@riseup.net>2024-02-14 16:43:30 -0500
commitec41c6121956afc4eb33c9f21905cdce4c07a097 (patch)
tree6310daec76d70fbbd78fb765b36adf2b0fde1ce5 /frontend/src/components/store/Store.tsx
parent21c7742f9a5ad499a95c6b54644d5494d5536967 (diff)
downloaddecky-loader-ec41c6121956afc4eb33c9f21905cdce4c07a097.tar.gz
decky-loader-ec41c6121956afc4eb33c9f21905cdce4c07a097.zip
Refactor plugin store and add sorting by downloads and release date (#547)
* untested first commit * fix types & names * comment out built in sorting for now * rerun search when sort changes * fix ts complaints * use prettier * stop switch-case fall through * move spinner * use locale instead of hardcoded string * fix typo * add sorting by downloads & try using the data field in the dropdown for data * fix typing error * fix asc/desc in dropdown * fix asc/desc again. asc = smaller one go first aaaaa * I don't think i know what ascending means maybe * use props instead of children, like a normal component
Diffstat (limited to 'frontend/src/components/store/Store.tsx')
-rw-r--r--frontend/src/components/store/Store.tsx137
1 files changed, 72 insertions, 65 deletions
diff --git a/frontend/src/components/store/Store.tsx b/frontend/src/components/store/Store.tsx
index 1afbb22b..e3d1b0f1 100644
--- a/frontend/src/components/store/Store.tsx
+++ b/frontend/src/components/store/Store.tsx
@@ -8,20 +8,19 @@ import {
TextField,
findModule,
} from 'decky-frontend-lib';
-import { FC, useEffect, useMemo, useState } from 'react';
+import { Dispatch, FC, SetStateAction, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import logo from '../../../assets/plugin_store.png';
import Logger from '../../logger';
-import { Store, StorePlugin, getPluginList, getStore } from '../../store';
+import { SortDirections, SortOptions, Store, StorePlugin, getPluginList, getStore } from '../../store';
import PluginCard from './PluginCard';
const logger = new Logger('Store');
const StorePage: FC<{}> = () => {
const [currentTabRoute, setCurrentTabRoute] = useState<string>('browse');
- const [data, setData] = useState<StorePlugin[] | null>(null);
- const [isTesting, setIsTesting] = useState<boolean>(false);
+ const [pluginCount, setPluginCount] = useState<number | null>(null);
const { TabCount } = findModule((m) => {
if (m?.TabCount && m?.TabTitle) return true;
return false;
@@ -29,17 +28,6 @@ const StorePage: FC<{}> = () => {
const { t } = useTranslation();
- useEffect(() => {
- (async () => {
- const res = await getPluginList();
- logger.log('got data!', res);
- setData(res);
- const storeRes = await getStore();
- logger.log(`store is ${storeRes}, isTesting is ${storeRes === Store.Testing}`);
- setIsTesting(storeRes === Store.Testing);
- })();
- }, []);
-
return (
<>
<div
@@ -49,52 +37,71 @@ const StorePage: FC<{}> = () => {
background: '#0005',
}}
>
- {!data ? (
- <div style={{ height: '100%' }}>
- <SteamSpinner />
- </div>
- ) : (
- <Tabs
- activeTab={currentTabRoute}
- onShowTab={(tabId: string) => {
- setCurrentTabRoute(tabId);
- }}
- tabs={[
- {
- title: t('Store.store_tabs.title'),
- content: <BrowseTab children={{ data: data, isTesting: isTesting }} />,
- id: 'browse',
- renderTabAddon: () => <span className={TabCount}>{data.length}</span>,
- },
- {
- title: t('Store.store_tabs.about'),
- content: <AboutTab />,
- id: 'about',
- },
- ]}
- />
- )}
+ <Tabs
+ activeTab={currentTabRoute}
+ onShowTab={(tabId: string) => {
+ setCurrentTabRoute(tabId);
+ }}
+ tabs={[
+ {
+ title: t('Store.store_tabs.title'),
+ content: <BrowseTab setPluginCount={setPluginCount} />,
+ id: 'browse',
+ renderTabAddon: () => <span className={TabCount}>{pluginCount}</span>,
+ },
+ {
+ title: t('Store.store_tabs.about'),
+ content: <AboutTab />,
+ id: 'about',
+ },
+ ]}
+ />
</div>
</>
);
};
-const BrowseTab: FC<{ children: { data: StorePlugin[]; isTesting: boolean } }> = (data) => {
+const BrowseTab: FC<{ setPluginCount: Dispatch<SetStateAction<number | null>> }> = ({ setPluginCount }) => {
const { t } = useTranslation();
- const sortOptions = useMemo(
+ const dropdownSortOptions = useMemo(
(): DropdownOption[] => [
- { data: 1, label: t('Store.store_tabs.alph_desc') },
- { data: 2, label: t('Store.store_tabs.alph_asce') },
+ // ascending and descending order are the wrong way around for the alphabetical sort
+ // this is because it was initially done incorrectly for i18n and 'fixing' it would
+ // make all the translations incorrect
+ { data: [SortOptions.name, SortDirections.ascending], label: t('Store.store_tabs.alph_desc') },
+ { data: [SortOptions.name, SortDirections.descending], label: t('Store.store_tabs.alph_asce') },
+ { data: [SortOptions.date, SortDirections.ascending], label: t('Store.store_tabs.date_asce') },
+ { data: [SortOptions.date, SortDirections.descending], label: t('Store.store_tabs.date_desc') },
+ { data: [SortOptions.downloads, SortDirections.descending], label: t('Store.store_tabs.downloads_desc') },
+ { data: [SortOptions.downloads, SortDirections.ascending], label: t('Store.store_tabs.downloads_asce') },
],
[],
);
// const filterOptions = useMemo((): DropdownOption[] => [{ data: 1, label: 'All' }], []);
-
- const [selectedSort, setSort] = useState<number>(sortOptions[0].data);
+ const [selectedSort, setSort] = useState<[SortOptions, SortDirections]>(dropdownSortOptions[0].data);
// const [selectedFilter, setFilter] = useState<number>(filterOptions[0].data);
const [searchFieldValue, setSearchValue] = useState<string>('');
+ const [pluginList, setPluginList] = useState<StorePlugin[] | null>(null);
+ const [isTesting, setIsTesting] = useState<boolean>(false);
+
+ useEffect(() => {
+ (async () => {
+ const res = await getPluginList(selectedSort[0], selectedSort[1]);
+ logger.log('got data!', res);
+ setPluginList(res);
+ setPluginCount(res.length);
+ })();
+ }, [selectedSort]);
+
+ useEffect(() => {
+ (async () => {
+ const storeRes = await getStore();
+ logger.log(`store is ${storeRes}, isTesting is ${storeRes === Store.Testing}`);
+ setIsTesting(storeRes === Store.Testing);
+ })();
+ }, []);
return (
<>
@@ -117,7 +124,7 @@ const BrowseTab: FC<{ children: { data: StorePlugin[]; isTesting: boolean } }> =
<span className="DialogLabel">{t("Store.store_sort.label")}</span>
<Dropdown
menuLabel={t("Store.store_sort.label") as string}
- rgOptions={sortOptions}
+ rgOptions={dropdownSortOptions}
strDefaultLabel={t("Store.store_sort.label_def") as string}
selectedOption={selectedSort}
onChange={(e) => setSort(e.data)}
@@ -163,7 +170,7 @@ const BrowseTab: FC<{ children: { data: StorePlugin[]; isTesting: boolean } }> =
<span className="DialogLabel">{t('Store.store_sort.label')}</span>
<Dropdown
menuLabel={t('Store.store_sort.label') as string}
- rgOptions={sortOptions}
+ rgOptions={dropdownSortOptions}
strDefaultLabel={t('Store.store_sort.label_def') as string}
selectedOption={selectedSort}
onChange={(e) => setSort(e.data)}
@@ -182,7 +189,7 @@ const BrowseTab: FC<{ children: { data: StorePlugin[]; isTesting: boolean } }> =
</div>
</Focusable>
</div>
- {data.children.isTesting && (
+ {isTesting && (
<div
style={{
alignItems: 'center',
@@ -213,22 +220,22 @@ const BrowseTab: FC<{ children: { data: StorePlugin[]; isTesting: boolean } }> =
</div>
)}
<div>
- {data.children.data
- .filter((plugin: StorePlugin) => {
- return (
- plugin.name.toLowerCase().includes(searchFieldValue.toLowerCase()) ||
- plugin.description.toLowerCase().includes(searchFieldValue.toLowerCase()) ||
- plugin.author.toLowerCase().includes(searchFieldValue.toLowerCase()) ||
- plugin.tags.some((tag: string) => tag.toLowerCase().includes(searchFieldValue.toLowerCase()))
- );
- })
- .sort((a, b) => {
- if (selectedSort % 2 === 1) return a.name.localeCompare(b.name);
- else return b.name.localeCompare(a.name);
- })
- .map((plugin: StorePlugin) => (
- <PluginCard plugin={plugin} />
- ))}
+ {!pluginList ? (
+ <div style={{ height: '100%' }}>
+ <SteamSpinner />
+ </div>
+ ) : (
+ pluginList
+ .filter((plugin: StorePlugin) => {
+ return (
+ plugin.name.toLowerCase().includes(searchFieldValue.toLowerCase()) ||
+ plugin.description.toLowerCase().includes(searchFieldValue.toLowerCase()) ||
+ plugin.author.toLowerCase().includes(searchFieldValue.toLowerCase()) ||
+ plugin.tags.some((tag: string) => tag.toLowerCase().includes(searchFieldValue.toLowerCase()))
+ );
+ })
+ .map((plugin: StorePlugin) => <PluginCard plugin={plugin} />)
+ )}
</div>
</>
);