OneLauncher-Cracked/apps/desktop/src/ui/components/overlay/cluster/ClusterStepTwo.tsx
2024-07-22 16:13:36 +02:00

175 lines
4.5 KiB
TypeScript

import { Camera01Icon, FilterFunnel01Icon, TextInputIcon } from '@untitled-theme/icons-solid';
import { For, Index, type JSX, Show, createEffect, createMemo, createSignal, on, onMount, splitProps } from 'solid-js';
import { Select } from '@thisbeyond/solid-select';
import { OverlayScrollbarsComponent } from 'overlayscrollbars-solid';
import type { ClusterStepProps } from './ClusterCreationModal';
import Dropdown from '~ui/components/base/Dropdown';
import TextField from '~ui/components/base/TextField';
import VanillaImage from '~assets/logos/vanilla.png';
import FabricImage from '~assets/logos/fabric.png';
import ForgeImage from '~assets/logos/forge.png';
import QuiltImage from '~assets/logos/quilt.png';
import useCommand from '~ui/hooks/useCommand';
import { bridge } from '~imports';
import Button from '~ui/components/base/Button';
import Tooltip from '~ui/components/base/Tooltip';
import SelectList from '~ui/components/base/SelectList';
import Checkbox from '~ui/components/base/Checkbox';
import { getEnumMembers } from '~utils/primitives';
import type { VersionType } from '~bindings';
import { formatVersionRelease } from '~utils/helpers';
const loaders: {
name: string;
icon: () => JSX.Element;
}[] = [
{
name: 'Vanilla',
icon: () => <img src={VanillaImage} />,
},
{
name: 'Fabric',
icon: () => <img src={FabricImage} />,
},
{
name: 'Forge',
icon: () => <img src={ForgeImage} />,
},
{
name: 'Quilt',
icon: () => <img src={QuiltImage} />,
},
];
export function ClusterStepTwo(props: ClusterStepProps) {
const [name, setName] = createSignal('');
const check = () => {
const hasName = name().length > 0;
props.setCanGoForward(hasName);
};
createEffect(check);
createEffect(on(() => props.isVisible(), (curr: boolean) => {
if (curr)
check();
}));
return (
<div class="flex flex-col gap-y-4">
<Option header="Name">
<TextField
onInput={e => setName(e.target.value)}
placeholder="Name"
iconLeft={<TextInputIcon />}
/>
</Option>
<Option header="Versions">
<VersionSelector />
</Option>
<Option header="Loader">
<Dropdown>
<For each={loaders}>
{loader => (
<Dropdown.Row>
<div class="flex flex-row gap-x-2">
<div class="w-4 h-4">
<loader.icon />
</div>
{loader.name}
</div>
</Dropdown.Row>
)}
</For>
</Dropdown>
</Option>
</div>
);
}
type VersionReleaseFilters = {
[key in VersionType]: boolean;
};
function VersionSelector() {
const [versions] = useCommand(bridge.commands.getMinecraftVersions);
const [filteredVersions, setFilteredVersions] = createSignal<bridge.Version[]>([]);
const [filters, setFilters] = createSignal<VersionReleaseFilters>({
old_alpha: false,
old_beta: false,
release: false,
snapshot: false,
});
function refresh(filters: VersionReleaseFilters, versions: bridge.Version[]) {
setFilteredVersions(() => {
if (Object.values(filters).every(value => value === false))
return versions;
return versions.filter((version) => {
return filters[version.type];
});
});
}
function toggleFilter(name: string) {
setFilters((prev) => {
return {
...prev,
[name]: !prev[name as keyof VersionReleaseFilters],
};
});
}
createEffect(() => {
const list = versions();
if (list !== undefined)
refresh(filters(), list);
});
createEffect(() => {
setFilteredVersions(versions()!);
});
return (
<div class="flex flex-row flex-1 gap-2">
<SelectList class="max-h-40 min-w-3/5">
<Show when={filteredVersions() !== undefined}>
<Index each={filteredVersions()}>
{(version, index) => (
<SelectList.Row index={index}>{version().id}</SelectList.Row>
)}
</Index>
</Show>
</SelectList>
<div class="bg-component-bg rounded-lg overflow-hidden border border-gray-05 flex-1 p-2 flex flex-col gap-y-2">
<For each={Object.keys(filters())}>
{name => (
<Checkbox onChecked={() => toggleFilter(name)}>{formatVersionRelease(name as VersionType)}</Checkbox>
)}
</For>
</div>
</div>
);
}
type OptionProps = {
header: string;
} & JSX.HTMLAttributes<HTMLDivElement>;
function Option(props: OptionProps) {
const [split, rest] = splitProps(props, ['header', 'class']);
return (
<div {...rest} class={`flex flex-col gap-y-2 items-stretch ${split.class || ''}`}>
<h3 class="text-md font-semibold uppercase text-fg-secondary text-left">{props.header}</h3>
{/* <div class="max-h-8"> */}
{props.children}
{/* </div> */}
</div>
);
}