feat: browser
This commit is contained in:
parent
e6a865657c
commit
b2f8a14acb
3 changed files with 75 additions and 26 deletions
|
|
@ -230,25 +230,14 @@ export type VersionType =
|
|||
*/
|
||||
"old_beta"
|
||||
|
||||
<<<<<<< HEAD
|
||||
const ARGS_MAP = { 'folders':'{"openCluster":["folder_name"],"fromCluster":["folder_name"]}', 'events':'{"ingress":["event"],"process":["event"],"message":["event"]}', 'oneclient':'{"getClustersGroupedByMajor":[],"openDevTools":[]}', 'core':'{"getWorlds":["id"],"launchCluster":["id","uuid"],"getDefaultUser":["fallback"],"getPackageVersions":["provider","slug","mc_version","loader","offset","limit"],"getClusterById":["id"],"downloadPackage":["provider","package_id","version_id","cluster_id","skip_compatibility"],"getProfileOrDefault":["name"],"updateClusterProfile":["name","profile"],"writeSettings":["setting"],"updateClusterById":["id","request"],"getMultiplePackages":["provider","slugs"],"removeCluster":["id"],"getUser":["uuid"],"getGlobalProfile":[],"openMsaLogin":[],"getPackageBody":["provider","body"],"getLogByName":["id","name"],"getLoadersForVersion":["mc_version"],"searchPackages":["provider","query"],"readSettings":[],"removeUser":["uuid"],"getClusters":[],"getGameVersions":[],"getUsers":[],"getPackage":["provider","slug"],"getUsersFromAuthor":["provider","author"],"getScreenshots":["id"],"getLogs":["id"],"setDefaultUser":["uuid"],"createCluster":["options"]}' }
|
||||
export type Router = { 'events': { ingress: (event: IngressPayload) => Promise<void>,
|
||||
message: (event: MessagePayload) => Promise<void>,
|
||||
process: (event: ProcessPayload) => Promise<void> },
|
||||
'folders': { fromCluster: (folderName: string) => Promise<string>,
|
||||
const ARGS_MAP = { 'core':'{"getPackageBody":["provider","body"],"getLogByName":["id","name"],"getClusters":[],"updateClusterProfile":["name","profile"],"getPackage":["provider","slug"],"getClusterById":["id"],"getGameVersions":[],"getUsers":[],"setDefaultUser":["uuid"],"openMsaLogin":[],"removeCluster":["id"],"getScreenshots":["id"],"removeUser":["uuid"],"searchPackages":["provider","query"],"getUsersFromAuthor":["provider","author"],"launchCluster":["id","uuid"],"getLogs":["id"],"updateClusterById":["id","request"],"getLoadersForVersion":["mc_version"],"getUser":["uuid"],"getProfileOrDefault":["name"],"fetchMinecraftProfile":["uuid"],"getWorlds":["id"],"writeSettings":["setting"],"getDefaultUser":["fallback"],"readSettings":[],"getGlobalProfile":[],"getMultiplePackages":["provider","slugs"],"downloadPackage":["provider","package_id","version_id","cluster_id","skip_compatibility"],"getPackageVersions":["provider","slug","mc_version","loader","offset","limit"],"createCluster":["options"]}', 'folders':'{"fromCluster":["folder_name"],"openCluster":["folder_name"]}', 'events':'{"message":["event"],"ingress":["event"],"process":["event"]}', 'oneclient':'{"getClustersGroupedByMajor":[],"openDevTools":[]}' }
|
||||
export type Router = { 'folders': { fromCluster: (folderName: string) => Promise<string>,
|
||||
openCluster: (folderName: string) => Promise<null> },
|
||||
'oneclient': { openDevTools: () => Promise<void>,
|
||||
getClustersGroupedByMajor: () => Promise<Partial<{ [key in number]: ClusterModel[] }>> },
|
||||
=======
|
||||
const ARGS_MAP = { 'oneclient':'{"openDevTools":[],"getClustersGroupedByMajor":[]}', 'events':'{"message":["event"],"process":["event"],"ingress":["event"]}', 'core':'{"getLoadersForVersion":["mc_version"],"writeSettings":["setting"],"getLogs":["id"],"getWorlds":["id"],"getClusterById":["id"],"launchCluster":["id","uuid"],"getPackage":["provider","slug"],"getGlobalProfile":[],"downloadPackage":["provider","package_id","version_id","cluster_id","skip_compatibility"],"readSettings":[],"updateClusterById":["id","request"],"getUser":["uuid"],"getPackageBody":["provider","body"],"fetchMinecraftProfile":["uuid"],"createCluster":["options"],"updateClusterProfile":["name","profile"],"getScreenshots":["id"],"removeUser":["uuid"],"getDefaultUser":["fallback"],"openMsaLogin":[],"getGameVersions":[],"setDefaultUser":["uuid"],"getUsersFromAuthor":["provider","author"],"removeCluster":["id"],"getLogByName":["id","name"],"getProfileOrDefault":["name"],"getClusters":[],"getMultiplePackages":["provider","slugs"],"getUsers":[],"searchPackages":["provider","query"],"getPackageVersions":["provider","slug","mc_version","loader","offset","limit"]}', 'folders':'{"openCluster":["folder_name"],"fromCluster":["folder_name"]}' }
|
||||
export type Router = { 'events': { ingress: (event: IngressPayload) => Promise<void>,
|
||||
'events': { ingress: (event: IngressPayload) => Promise<void>,
|
||||
message: (event: MessagePayload) => Promise<void>,
|
||||
process: (event: ProcessPayload) => Promise<void> },
|
||||
'oneclient': { openDevTools: () => Promise<void>,
|
||||
getClustersGroupedByMajor: () => Promise<Partial<{ [key in number]: ClusterModel[] }>> },
|
||||
'folders': { fromCluster: (folderName: string) => Promise<string>,
|
||||
openCluster: (folderName: string) => Promise<null> },
|
||||
>>>>>>> 04cd2183d01fa465f38ac0b802c81eb344a7ecf9
|
||||
'core': { getClusters: () => Promise<ClusterModel[]>,
|
||||
getClusterById: (id: number) => Promise<ClusterModel | null>,
|
||||
removeCluster: (id: number) => Promise<null>,
|
||||
|
|
@ -278,12 +267,8 @@ getPackageBody: (provider: Provider, body: ManagedPackageBody) => Promise<string
|
|||
getMultiplePackages: (provider: Provider, slugs: string[]) => Promise<ManagedPackage[]>,
|
||||
getPackageVersions: (provider: Provider, slug: string, mcVersion: string | null, loader: GameLoader | null, offset: number, limit: number) => Promise<Paginated<ManagedVersion>>,
|
||||
downloadPackage: (provider: Provider, packageId: string, versionId: string, clusterId: number, skipCompatibility: boolean | null) => Promise<PackageModel>,
|
||||
<<<<<<< HEAD
|
||||
getUsersFromAuthor: (provider: Provider, author: PackageAuthor) => Promise<ManagedUser[]> } };
|
||||
=======
|
||||
getUsersFromAuthor: (provider: Provider, author: PackageAuthor) => Promise<ManagedUser[]>,
|
||||
fetchMinecraftProfile: (uuid: string) => Promise<MojangPlayerProfile> } };
|
||||
>>>>>>> 04cd2183d01fa465f38ac0b802c81eb344a7ecf9
|
||||
|
||||
|
||||
export type { InferCommandOutput }
|
||||
|
|
|
|||
|
|
@ -1,23 +1,29 @@
|
|||
import type { PackageType, Provider } from '@/bindings.gen';
|
||||
import type { Filters, PackageCategories, PackageType, Provider } from '@/bindings.gen';
|
||||
import { LoaderSuspense } from '@/components';
|
||||
import { PackageGrid } from '@/components/PackageItem';
|
||||
import { bindings } from '@/main';
|
||||
import { browserCategories, categoryNameFromId } from '@/utils/browser';
|
||||
import { useCommandSuspense, usePagination } from '@onelauncher/common';
|
||||
import { Dropdown, Show, TextField } from '@onelauncher/common/components';
|
||||
import { createFileRoute } from '@tanstack/react-router';
|
||||
import { SearchMdIcon } from '@untitled-theme/icons-react';
|
||||
import { useMemo } from 'react';
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
|
||||
interface BrowserSearchRouteSearchParams {
|
||||
query?: string;
|
||||
packageType: PackageType;
|
||||
categories: Array<string>;
|
||||
page: number;
|
||||
}
|
||||
|
||||
export const Route = createFileRoute('/app/cluster/browser/')({
|
||||
component: RouteComponent,
|
||||
validateSearch: (search): BrowserSearchRouteSearchParams => {
|
||||
return {
|
||||
query: search.query as string,
|
||||
query: (search.query ?? '') as string,
|
||||
packageType: search.packageType as PackageType,
|
||||
categories: search.categories as Array<string>,
|
||||
categories: (search.categories ?? []) as Array<string>,
|
||||
page: Number(search.page ?? 0),
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
@ -39,6 +45,9 @@ function RouteComponent() {
|
|||
|
||||
<div className="h-full flex flex-col gap-y-4">
|
||||
<div className="h-full flex-1">
|
||||
<LoaderSuspense spinner={{ size: 'large' }}>
|
||||
<SearchResult />
|
||||
</LoaderSuspense>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -54,17 +63,18 @@ function BrowserCategories() {
|
|||
const search = Route.useSearch();
|
||||
const { categories, packageType } = search;
|
||||
const navigate = Route.useNavigate();
|
||||
const navRef = useRef(navigate);
|
||||
const switchCategory = useMemo(() => (category: string) => {
|
||||
const newCategories = categories.includes(category)
|
||||
? categories.filter(element => element !== category)
|
||||
: [...categories, category];
|
||||
navigate({
|
||||
navRef.current({
|
||||
search: {
|
||||
...search,
|
||||
categories: newCategories,
|
||||
},
|
||||
});
|
||||
}, []);
|
||||
}, [search, categories]);
|
||||
|
||||
return (
|
||||
<div className="top-0 h-fit min-w-50">
|
||||
|
|
@ -97,6 +107,7 @@ function BrowserToolbar() {
|
|||
const setQuery = (query: string) => {
|
||||
navigate({ search: { ...search, query } });
|
||||
};
|
||||
const [searchBar, setSearchBar] = useState(query);
|
||||
return (
|
||||
<div className="w-full flex flex-row justify-between bg-page">
|
||||
<div className="flex flex-row gap-2">
|
||||
|
|
@ -120,7 +131,7 @@ function BrowserToolbar() {
|
|||
<TextField
|
||||
className="min-w-64"
|
||||
iconLeft={<SearchMdIcon className="scale-75" />}
|
||||
// onChange={e => setQuery(e.currentTarget.value)}
|
||||
onChange={e => setSearchBar(e.currentTarget.value)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key !== 'Enter')
|
||||
return;
|
||||
|
|
@ -128,9 +139,61 @@ function BrowserToolbar() {
|
|||
setQuery(e.currentTarget.value);
|
||||
}}
|
||||
placeholder="Search for content"
|
||||
value={query}
|
||||
value={searchBar}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
interface SearchQuery {
|
||||
query: string | null;
|
||||
offset: number | null;
|
||||
limit: number;
|
||||
sort: 'Relevance' | 'Downloads' | 'Newest' | 'Updated' | null;
|
||||
filters: Filters | null;
|
||||
}
|
||||
|
||||
const itemsPerPage = 25;
|
||||
|
||||
function SearchResult() {
|
||||
const search = Route.useSearch();
|
||||
const { cluster } = Route.useRouteContext();
|
||||
const navigate = Route.useNavigate();
|
||||
const navRef = useRef(navigate);
|
||||
const query = useMemo<SearchQuery>(() => ({
|
||||
query: search.query ?? null,
|
||||
offset: (search.page - 1) * itemsPerPage,
|
||||
limit: itemsPerPage,
|
||||
sort: 'Relevance',
|
||||
filters: {
|
||||
game_versions: [cluster.mc_version],
|
||||
categories: { [categoryNameFromId[search.packageType]]: search.categories } as PackageCategories,
|
||||
loaders: [cluster.mc_loader],
|
||||
package_type: search.packageType,
|
||||
},
|
||||
}), [cluster, search]);
|
||||
const results = useCommandSuspense(['searchPackages', search], () => bindings.core.searchPackages(
|
||||
search.provider,
|
||||
query,
|
||||
));
|
||||
const pagination = usePagination({
|
||||
itemsPerPage: query.limit,
|
||||
itemsCount: results.data.total,
|
||||
});
|
||||
const paginationRef = useRef(pagination);
|
||||
useEffect(() => {
|
||||
navRef.current({ search: prev => ({ ...prev, page: pagination.page }) });
|
||||
}, [pagination.page]);
|
||||
useEffect(() => {
|
||||
paginationRef.current.reset();
|
||||
}, [pagination.totalPages]);
|
||||
return (
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="flex justify-end">
|
||||
<pagination.Navigation />
|
||||
</div>
|
||||
<PackageGrid items={results.data.items} provider={search.provider} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ function RouteComponent() {
|
|||
<TabList className="sticky top-0 z-10 shadow-lg" floating={floating} ref={tabListRef}>
|
||||
<Tab from={Route.id} search={search} to="/app/cluster/overview">Overview</Tab>
|
||||
<Tab from={Route.id} search={search} to="/app/cluster/logs">Logs</Tab>
|
||||
<Tab from={Route.id} search={{ ...search, packageType: 'mod' }} to="/app/cluster/browser">Browser</Tab>
|
||||
</TabList>
|
||||
|
||||
<div className="relative pb-8">
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue