feat: Cluster Settings page

This commit is contained in:
LynithDev 2024-07-08 13:47:24 +02:00
parent 09b73dc55e
commit be867a9c8d
6 changed files with 103 additions and 38 deletions

View file

@ -67,6 +67,12 @@ pub async fn create_cluster(props: CreateCluster) -> Result<Uuid, String> {
}
}
// #[specta::specta]
// #[tauri::command]
// pub fn update_cluster(cluster: Cluster) -> Result<(), String> {
// }
fn placeholder_cluster() -> Cluster {
let path = ClusterPath("test".into());
Cluster {

View file

@ -22,7 +22,7 @@ function SettingsRow(props: SettingsRowProps) {
<p class="text-wrap text-sm">{props.description}</p>
</div>
<div>
<div class="flex flex-row justify-center items-center gap-2">
{props.children}
</div>
</div>

View file

@ -1,6 +1,6 @@
import { Route, useSearchParams } from '@solidjs/router';
import type { ParentProps } from 'solid-js';
import { EyeIcon, File06Icon, Globe04Icon, Image03Icon, Settings04Icon, Tool02Icon } from '@untitled-theme/icons-solid';
import { EyeIcon, File06Icon, Globe04Icon, Image03Icon, Settings04Icon } from '@untitled-theme/icons-solid';
import Sidebar from '../../components/Sidebar';
import AnimatedRoutes from '../../components/AnimatedRoutes';
import ErrorBoundary from '../../components/ErrorBoundary';
@ -8,6 +8,7 @@ import ClusterOverview from './cluster/ClusterOverview';
import ClusterLogs from './cluster/ClusterLogs';
import ClusterMods from './cluster/ClusterMods';
import ClusterScreenshots from './cluster/ClusterScreenshots';
import ClusterSettings from './cluster/ClusterSettings';
import useClusterContext, { ClusterProvider } from '~ui/hooks/useCluster';
function ClusterRoutes() {
@ -17,6 +18,7 @@ function ClusterRoutes() {
<Route path="/logs" component={ClusterLogs} />
<Route path="/mods" component={ClusterMods} />
<Route path="/screenshots" component={ClusterScreenshots} />
<Route path="/settings" component={ClusterSettings} />
</>
);
}
@ -58,10 +60,7 @@ function ClusterSidebar() {
[<Image03Icon />, 'Screenshots', '/screenshots'],
[<Globe04Icon />, 'Worlds', '/worlds'],
[<File06Icon />, 'Logs', '/logs'],
],
Settings: [
[<Tool02Icon />, 'Java', '/java'],
[<Settings04Icon />, 'Miscellaneous', '/misc'],
[<Settings04Icon />, 'Game Settings', '/settings'],
],
}}
/>

View file

@ -0,0 +1,34 @@
import ScrollableContainer from '~ui/components/ScrollableContainer';
import Sidebar from '~ui/components/Sidebar';
import useClusterContext from '~ui/hooks/useCluster';
import useSettingsContext from '~ui/hooks/useSettings';
import SettingsMinecraft from '~ui/pages/settings/game/SettingsMinecraft';
function ClusterSettings() {
const cluster = useClusterContext();
const settings = useSettingsContext();
// TODO: Save cluster settings
return (
<Sidebar.Page>
<h1>Overview</h1>
<ScrollableContainer>
<SettingsMinecraft.Settings
fullscreen={{
get: cluster.force_fullscreen ?? settings.force_fullscreen ?? false,
set: value => cluster.force_fullscreen = value,
isGlobal: cluster.force_fullscreen === null,
}}
resolution={{
get: cluster.resolution ?? settings.resolution,
set: value => cluster.resolution = value,
isGlobal: cluster.resolution === undefined || cluster.resolution === null,
}}
/>
</ScrollableContainer>
</Sidebar.Page>
);
}
export default ClusterSettings;

View file

@ -1,7 +1,10 @@
import { EyeIcon, LayoutTopIcon, Maximize01Icon, XIcon } from '@untitled-theme/icons-solid';
import { EyeIcon, FlipBackwardIcon, Globe02Icon, InfoCircleIcon, LayoutTopIcon, Maximize01Icon, XIcon } from '@untitled-theme/icons-solid';
import { Show } from 'solid-js';
import Button from '~ui/components/base/Button';
import Dropdown from '~ui/components/base/Dropdown';
import TextField from '~ui/components/base/TextField';
import Toggle from '~ui/components/base/Toggle';
import Tooltip from '~ui/components/base/Tooltip';
import ScrollableContainer from '~ui/components/ScrollableContainer';
import SettingsRow from '~ui/components/SettingsRow';
import Sidebar from '~ui/components/Sidebar';
@ -14,18 +17,54 @@ function SettingsMinecraft() {
<Sidebar.Page>
<h1>Global Minecraft Settings</h1>
<ScrollableContainer>
<SettingsMinecraft.Settings
fullscreen={{
get: settings.force_fullscreen ?? false,
set: value => settings.force_fullscreen = value,
}}
resolution={{
get: settings.resolution,
set: value => settings.resolution = value,
}}
hide_on_launch={{
get: settings.hide_on_launch ?? false,
set: value => settings.hide_on_launch = value,
}}
/>
</ScrollableContainer>
</Sidebar.Page>
);
}
interface SettingsEntryType<T> {
get: T;
set: (value: T) => any;
isGlobal?: boolean; // TODO: Ask how "global settings sync" should work on pages like ClusterSettings
};
interface SettingsProps {
fullscreen: SettingsEntryType<boolean>;
resolution: SettingsEntryType<[number, number]>;
hide_on_launch: SettingsEntryType<boolean>;
};
SettingsMinecraft.Settings = function (props: Partial<SettingsProps>) {
return (
<>
<Show when={props.fullscreen !== undefined}>
<SettingsRow
title="Force Fullscreen"
description="Force Minecraft to start in fullscreen mode."
icon={<Maximize01Icon />}
>
<Toggle
defaultChecked={settings.force_fullscreen ?? false}
onChecked={value => settings.force_fullscreen = value}
defaultChecked={props.fullscreen!.get}
onChecked={props.fullscreen!.set}
/>
</SettingsRow>
</Show>
<Show when={props.resolution !== undefined}>
<SettingsRow
title="Resolution"
description="The game window resolution in pixels."
@ -34,51 +73,37 @@ function SettingsMinecraft() {
<div class="grid grid-justify-center grid-items-center gap-2 grid-cols-[70px_16px_70px]">
<TextField.Number
class="text-center"
value={settings.resolution[0]}
value={props.resolution!.get[0]}
onValidSubmit={(value) => {
settings.resolution = [Number.parseInt(value), settings.resolution[1]];
props.resolution!.set([Number.parseInt(value), props.resolution!.get[1]]);
}}
/>
<XIcon class="w-4 h-4" />
<TextField.Number
class="text-center"
value={settings.resolution[1]}
value={props.resolution!.get[1]}
onValidSubmit={(value) => {
settings.resolution = [settings.resolution[0], Number.parseInt(value)];
props.resolution!.set([props.resolution!.get[0], Number.parseInt(value)]);
}}
/>
</div>
</SettingsRow>
</Show>
<Show when={props.hide_on_launch !== undefined}>
<SettingsRow
title="Launcher Visibility"
description="Set the launcher visibility whenever you start a game."
title="Hide On Launch"
description="Hide the launcher whenever you start a game."
icon={<EyeIcon />}
>
<Dropdown
class="w-32!"
onChange={(selected) => {
switch (selected) {
case 0:
settings.hide_on_launch = false;
break;
case 1:
settings.hide_on_launch = true;
break;
case 2:
break;
}
}}
>
<Dropdown.Row>Visible</Dropdown.Row>
<Dropdown.Row>Hide</Dropdown.Row>
<Dropdown.Row>Close (// TODO)</Dropdown.Row>
</Dropdown>
<Toggle
defaultChecked={props.hide_on_launch!.get}
onChecked={props.hide_on_launch!.set}
/>
</SettingsRow>
</ScrollableContainer>
</Sidebar.Page>
</Show>
</>
);
}
};
export default SettingsMinecraft;

View file

@ -21,6 +21,7 @@ export default petal({
'**/*.svg',
'*.rs',
'pnpm-lock.yaml',
'**/node_modules',
'desktop/src/bindings.ts',
],
}).append([