feat: browser context stuff

This commit is contained in:
Szedann 2025-07-15 19:59:14 +02:00
parent a02ca5c085
commit 6d354d0eca
6 changed files with 77 additions and 21 deletions

View file

@ -1,21 +1,49 @@
import type { ClusterModel } from '@/bindings.gen';
import { createContext } from 'react';
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;
search: () => void;
}
const browserContext = createContext<BrowserControllerType | null>(null);
const BrowserContext = createContext<BrowserControllerType | null>(null);
export function useBrowserContext() {
const context = useContext(BrowserContext);
if (!context)
throw new Error('useBrowserContext must be used within a BrowserProvider');
return context;
}
export function BrowserProvider(props: any) {
const { children } = props;
const [cluster, setCluster] = useState<ClusterModel | undefined>(undefined);
const [provider, setProvider] = useState<Provider>(PROVIDERS[0]);
const context = useMemo<BrowserControllerType>(() => ({
cluster,
setCluster,
provider,
setProvider,
search: () => {},
}), [cluster, provider]);
return (
<browserContext.Provider value={browserContext}>
<BrowserContext.Provider value={context}>
{children}
</browserContext.Provider>
</BrowserContext.Provider>
);
}
export function useFeatured() {
useCommand();
}

View file

@ -3,7 +3,7 @@ import { bindings } from '@/main';
import { useCommand } from '@onelauncher/common';
import { useEffect, useState } from 'react';
function useRecentCluster() {
export function useRecentCluster() {
const result = useCommand('getClusters', bindings.core.getClusters);
const [cluster, setCluster] = useState<ClusterModel | undefined>();
@ -40,4 +40,15 @@ function useRecentCluster() {
return cluster;
}
export default useRecentCluster;
export function useClusters() {
const result = useCommand('getClusters', bindings.core.getClusters);
const [clusters, setClusters] = useState<Array<ClusterModel> | undefined>();
useEffect(() => {
if (!result.data)
return;
setClusters(result.data);
}, [result.data]);
return clusters;
}

View file

@ -1,4 +1,5 @@
import OneConfigLogo from '@/assets/logos/oneconfig.svg';
import { useBrowserContext } from '@/hooks/useBrowser';
import { Button, Show } from '@onelauncher/common/components';
import { createFileRoute } from '@tanstack/react-router';
import { ChevronRightIcon } from '@untitled-theme/icons-react';

View file

@ -1,3 +1,5 @@
import { BrowserProvider, useBrowserContext } from '@/hooks/useBrowser';
import { useClusters } from '@/hooks/useCluster';
import { PROVIDERS } from '@/utils';
import { Button, Dropdown, Show, TextField } from '@onelauncher/common/components';
import { createFileRoute, Outlet } from '@tanstack/react-router';
@ -9,9 +11,11 @@ export const Route = createFileRoute('/app/browser')({
function RouteComponent() {
return (
<div>
<Outlet />
</div>
<BrowserProvider>
<div>
<Outlet />
</div>
</BrowserProvider>
);
}
@ -42,20 +46,30 @@ export function BrowserLayout(props: any) {
}
function BrowserSidebar() {
const context = useBrowserContext();
const clusters = useClusters();
return (
<div className="flex flex-col gap-y-4">
<div className="flex flex-col gap-y-4">
<div className="flex flex-col gap-y-1">
<h6 className="my-1">Active Cluster</h6>
<Button
children="None"
className="h-9.5"
color="secondary"
/>
<Dropdown
onSelectionChange={(id) => {
const cluster = clusters?.find(cluster => cluster.id.toString() === id);
context.setCluster(cluster);
}}
selectedKey={context.cluster?.id.toString()}
>
{clusters?.map(cluster => (
<Dropdown.Item id={cluster.id.toString()} key={cluster.id}>
{cluster.name}
</Dropdown.Item>
))}
</Dropdown>
</div>
<div className="flex flex-col gap-y-1">
<h6 className="my-1">Provider</h6>
<Dropdown>
<Dropdown onSelectionChange={provider => context.setProvider(provider as typeof context.provider)} selectedKey={context.provider}>
{/* <For each={PROVIDERS}>
{provider => (
<Dropdown.Row>
@ -65,7 +79,9 @@ function BrowserSidebar() {
)}
</For> */}
{PROVIDERS.map(provider => (
<Dropdown.Item key={provider}>{provider}</Dropdown.Item>
<Dropdown.Item id={provider} key={provider}>
{provider}
</Dropdown.Item>
))}
</Dropdown>
</div>

View file

@ -2,7 +2,7 @@ import type { ClusterModel } from '@/bindings.gen';
import DefaultBanner from '@/assets/images/default_banner.png';
import DefaultInstancePhoto from '@/assets/images/default_instance_cover.jpg';
import { NewClusterCreate } from '@/components/launcher/cluster/ClusterCreation';
import useRecentCluster from '@/hooks/useCluster';
import { useRecentCluster } from '@/hooks/useCluster';
import { bindings } from '@/main';
import { formatAsDuration, upperFirst } from '@/utils';
import { useCommand } from '@onelauncher/common';

View file

@ -1,4 +1,4 @@
export const LAUNCHER_IMPORT_TYPES: Array<string> = [
export const LAUNCHER_IMPORT_TYPES = [
'PrismLauncher',
'Curseforge',
// 'Modrinth',
@ -10,7 +10,7 @@ export const LAUNCHER_IMPORT_TYPES: Array<string> = [
// 'Technic'
] as const;
export const LOADERS: Array<string> = [
export const LOADERS = [
'vanilla',
'forge',
'neoforge',
@ -18,8 +18,8 @@ export const LOADERS: Array<string> = [
'fabric',
'legacyfabric',
] as const;
export const PROVIDERS: Array<string> = ['Modrinth', 'Curseforge', 'SkyClient'] as const;
export const PACKAGE_TYPES: Array<string> = ['mod', 'resourcepack', 'datapack', 'shaderpack'] as const;
export const PROVIDERS = ['Modrinth', 'Curseforge', 'SkyClient'] as const;
export const PACKAGE_TYPES = ['mod', 'resourcepack', 'datapack', 'shaderpack'] as const;
export function pluralize(n: number, word: string, locale: string = 'en'): string {
const pluralRules = new Intl.PluralRules(locale);