fix: browser category selector

This commit is contained in:
Szedann 2025-07-15 21:42:09 +02:00
parent 2593b293de
commit 089fbd3e26
3 changed files with 53 additions and 14 deletions

View file

@ -1,17 +1,16 @@
import type { ClusterModel } from '@/bindings.gen';
import type { ClusterModel, Provider, SearchQuery } from '@/bindings.gen';
import { bindings } from '@/main';
import { PROVIDERS } from '@/utils';
import { useCommand } from '@onelauncher/common';
import { createContext, useContext, useMemo, useState } from 'react';
type Provider = typeof PROVIDERS[number];
export interface BrowserControllerType {
cluster: ClusterModel | undefined;
setCluster: (cluster: ClusterModel | undefined) => void;
provider: Provider;
setProvider: (provider: Provider) => void;
query: SearchQuery;
setQuery: (query: SearchQuery) => void;
search: () => void;
}
@ -28,14 +27,23 @@ export function BrowserProvider(props: any) {
const { children } = props;
const [cluster, setCluster] = useState<ClusterModel | undefined>(undefined);
const [provider, setProvider] = useState<Provider>(PROVIDERS[0]);
const [query, setQuery] = useState<SearchQuery>({
filters: null,
query: null,
limit: 18 as unknown as bigint,
offset: null,
sort: null,
});
const context = useMemo<BrowserControllerType>(() => ({
cluster,
setCluster,
provider,
setProvider,
query,
setQuery,
search: () => {},
}), [cluster, provider]);
}), [cluster, provider, query]);
return (
<BrowserContext.Provider value={context}>
@ -43,3 +51,7 @@ export function BrowserProvider(props: any) {
</BrowserContext.Provider>
);
}
export function useBrowserSearch(provider: Provider, query: SearchQuery) {
return useCommand('searchPackages', () => bindings.core.searchPackages(provider, query));
}

View file

@ -1,7 +1,7 @@
import OneConfigLogo from '@/assets/logos/oneconfig.svg';
import { useBrowserContext } from '@/hooks/useBrowser';
import { useBrowserContext, useBrowserSearch } from '@/hooks/useBrowser';
import { Button, Show } from '@onelauncher/common/components';
import { createFileRoute } from '@tanstack/react-router';
import { createFileRoute, useSearch } from '@tanstack/react-router';
import { ChevronRightIcon } from '@untitled-theme/icons-react';
import { BrowserLayout } from './route';
@ -20,6 +20,8 @@ function RouteComponent() {
}
function Featured() {
const context = useBrowserContext();
const search = useBrowserSearch(context.provider, context.query);
return (
<Show when>
<div className="flex flex-col gap-y-1">
@ -48,6 +50,12 @@ function Featured() {
</div>
</div>
</div>
{search.status}
{search.isSuccess && (
<>
{search.data.items.map(item => <p key={item.id}>{item.name}</p>)}
</>
)}
</div>
</Show>
);

View file

@ -1,10 +1,12 @@
import type { Filters } from '@/bindings.gen';
import ProviderIcon from '@/components/content/ProviderIcon';
import { BrowserProvider, useBrowserContext } from '@/hooks/useBrowser';
import { useClusters } from '@/hooks/useCluster';
import { PROVIDERS } from '@/utils';
import { browserCategories } from '@/utils/browser';
import { Button, Dropdown, Show, TextField } from '@onelauncher/common/components';
import { Dropdown, Show, TextField } from '@onelauncher/common/components';
import { createFileRoute, Outlet } from '@tanstack/react-router';
import { SearchMdIcon } from '@untitled-theme/icons-react';
import { memo } from 'react';
export const Route = createFileRoute('/app/browser')({
component: RouteComponent,
@ -70,9 +72,9 @@ function BrowserSidebar() {
</div>
<div className="flex flex-col gap-y-1">
<h6 className="my-1">Provider</h6>
<Dropdown>
<Dropdown onSelectionChange={id => context.setProvider(id as typeof context.provider)} selectedKey={context.provider}>
{PROVIDERS.map(provider => (
<Dropdown.Item key={provider}>
<Dropdown.Item id={provider} key={provider}>
<div className="flex flex-row">
<ProviderIcon className="size-4 mr-2 self-center" provider={provider} />
{provider}
@ -86,8 +88,23 @@ function BrowserSidebar() {
);
}
const defaultFilters:Filters = {
categories: null,
game_versions: null,
loaders: null,
package_types: null
}
function BrowserCategories() {
const categories = browserCategories.byPackageType('mod', 'Modrinth');
const context = useBrowserContext();
const categories = browserCategories.byPackageType('mod', context.provider);
function switchCategory(category:string){
if(context.query.filters?.categories?.includes(category))
context.setQuery({...context.query, filters: {...defaultFilters, ...context.query.filters, categories: (context.query.filters?.categories ?? []).filter(cat=>cat!==category)}})
else
context.setQuery({...context.query, filters: {...defaultFilters, ...context.query.filters, categories: [...(context.query.filters?.categories ?? []), category]}})
}
return (
<div className="top-0 grid grid-cols-[1fr_auto] h-fit min-w-50 gap-y-6">
@ -95,11 +112,13 @@ function BrowserCategories() {
<div className="flex flex-col gap-y-6">
<Show when>
<div className="flex flex-col gap-y-2">
<h6 className="my-1">Categories</h6>
<h6 className="my-1 uppercase">Categories</h6>
{categories.map(category => (
<p
className="text-md capitalize opacity-100 hover:opacity-90 text-fg-primary hover:text-fg-primary-hover"
aria-selected={context.query.filters?.categories?.includes(category.id)}
className="text-md capitalize opacity-60 hover:opacity-90 text-fg-primary hover:text-fg-primary-hover aria-selected:opacity-100"
key={category.id}
onClick={()=>switchCategory(category.id)}
>
{category.display}
</p>