From 676c16f14a7aa676bd15d7a9ce59443278e8aebb Mon Sep 17 00:00:00 2001 From: LynithDev <61880709+LynithDev@users.noreply.github.com> Date: Sun, 4 Aug 2024 15:57:58 +0200 Subject: [PATCH] refactor: ClusterCreationModal (still awaits refactoring, Contexts shouldn't be used like this) --- .../overlay/cluster/ClusterCreationModal.tsx | 266 +++++++++--------- .../overlay/cluster/ClusterStepTwo.tsx | 16 +- 2 files changed, 136 insertions(+), 146 deletions(-) diff --git a/apps/frontend/src/ui/components/overlay/cluster/ClusterCreationModal.tsx b/apps/frontend/src/ui/components/overlay/cluster/ClusterCreationModal.tsx index a0bec933..b6daf8e1 100644 --- a/apps/frontend/src/ui/components/overlay/cluster/ClusterCreationModal.tsx +++ b/apps/frontend/src/ui/components/overlay/cluster/ClusterCreationModal.tsx @@ -1,7 +1,7 @@ -import { type Accessor, type Context, Match, type ParentProps, type Setter, Show, Switch, createContext, createEffect, createSignal, untrack, useContext } from 'solid-js'; +import { type Accessor, type Context, Match, type ParentProps, type Setter, Switch, createContext, createEffect, createSignal, onCleanup, untrack, useContext } from 'solid-js'; import { ArrowRightIcon, Server01Icon } from '@untitled-theme/icons-solid'; import HeaderImage from '../../../../assets/images/header.png'; -import FullscreenOverlay from '../FullscreenOverlay'; +import { createModal } from '../Modal'; import ClusterStepOne from './ClusterStepOne'; import { ClusterStepTwo } from './ClusterStepTwo'; import Button from '~ui/components/base/Button'; @@ -22,8 +22,6 @@ interface ClusterModalContextFunc { updatePartialCluster: PartialClusterUpdateFunc; start: () => Promise; // Returns true if its finished (created) successfully finish: () => void; - visible: Accessor; - setVisible: Setter; } const ClusterModalContext = createContext() as Context; @@ -37,7 +35,6 @@ type ClusterModalStagesLength = UnionToArray['l export function ClusterModalController(props: ParentProps) { const [step, setStep] = createSignal(ClusterModalStages.STAGE_1_PROVIDER); - const [visible, setVisible] = createSignal(false); const [partialCluster, setPartialCluster] = createSignal({}); const [inProgress, setInProgress] = createSignal(false); const [error, setError] = createSignal(undefined); @@ -51,91 +48,92 @@ export function ClusterModalController(props: ParentProps) { }); }; - const start = () => { - setPartialCluster({}); - setStep(ClusterModalStages.STAGE_1_PROVIDER); - setError(undefined); - setInProgress(true); - setVisible(true); + const modal = createModal(() => ( + // eslint-disable-next-line ts/no-use-before-define -- circular dependency should be refactored later + + )); - return new Promise((resolve, reject) => { - createEffect(() => { - const result = error(); - if (inProgress() === true) - return; - - if (result === undefined || result.length === 0) - resolve(); - else - reject(result); - }); - }); - }; - - const finish = async () => { - const untracked = untrack(partialCluster); - - if (untracked.name === undefined || untracked.mc_version === undefined || untracked.mod_loader === undefined) - throw new Error('Cluster is missing required fields'); - - setVisible(false); - - await bridge.commands.createCluster({ - name: untracked.name!, - mod_loader: untracked.mod_loader!, - mc_version: untracked.mc_version!, - // TODO: Implement the rest of the fields - icon: null, - icon_url: null, - loader_version: null, - package_data: null, - skip: null, - skip_watch: null, - }); - - setInProgress(false); - }; - - const stepper: ClusterModalContextFunc = { + const context: ClusterModalContextFunc = { step, setStep, partialCluster, setPartialCluster, updatePartialCluster, - start, - finish, - visible, - setVisible, + + start() { + setPartialCluster({}); + setStep(ClusterModalStages.STAGE_1_PROVIDER); + setError(undefined); + setInProgress(true); + modal.show(); + + return new Promise((resolve, reject) => { + createEffect(() => { + const result = error(); + if (inProgress() === true) + return; + + if (result === undefined || result.length === 0) + resolve(); + else + reject(result); + }); + }); + }, + + async finish() { + const untracked = untrack(partialCluster); + + if (untracked.name === undefined || untracked.mc_version === undefined || untracked.mod_loader === undefined) + throw new Error('Cluster is missing required fields'); + + modal.hide(); + + await bridge.commands.createCluster({ + name: untracked.name!, + mod_loader: untracked.mod_loader!, + mc_version: untracked.mc_version!, + // TODO: Implement the rest of the fields + icon: null, + icon_url: null, + loader_version: null, + package_data: null, + skip: null, + skip_watch: null, + }); + + setInProgress(false); + }, }; - createEffect(() => { - if (visible() === false) - setStep(ClusterModalStages.STAGE_1_PROVIDER); + onCleanup(() => { + setStep(ClusterModalStages.STAGE_1_PROVIDER); }); return ( - + {props.children} - {/* Makes sure theres a new instance of the modal */} - - - ); } export function useClusterModalController() { - return useContext(ClusterModalContext); + const ctx = useContext(ClusterModalContext); + + if (!ctx) + throw new Error('useClusterModalController must be used within a ClusterModalController'); + + return ctx; } export interface ClusterStepProps { isVisible: Accessor; setCanGoForward: Setter; + controller: Accessor; }; -function ClusterCreationModal() { - const controller = useClusterModalController(); - const buttonIsNext = () => controller.step() !== ((Object.keys(ClusterModalStages).length / 2) - 1); +function ClusterCreationModal(props: { controller: ClusterModalContextFunc }) { + const buttonIsNext = () => props.controller.step() !== ((Object.keys(ClusterModalStages).length / 2) - 1); const [canGoForward, setCanGoForward] = createSignal(false); // Indexed by the current step @@ -150,97 +148,91 @@ function ClusterCreationModal() { ].map((Component, index) => ( Component({ setCanGoForward, - isVisible: () => controller.visible() && controller.step() === index, + isVisible: () => props.controller.step() === index, + controller: () => props.controller, }) )); const Step = (props: { step: number }) => <>{stepComponents[props.step]}; function cancel() { - controller.setVisible(false); + // controller.setVisible(false); } function prev() { - controller.setStep(prev => prev - 1); + props.controller.setStep(prev => prev - 1); } function next() { - controller.setStep(prev => prev + 1); + props.controller.setStep(prev => prev + 1); } function finish() { - controller.finish(); + props.controller.finish(); } return ( - -
-
-
-
- Header Image -
-
- -
- {/** weird positioning?? */} -

New Cluster

- {messages[controller.step()]} -
-
-
-
-
- -
- -
- - -
+
+
+
+ Header Image +
+
+ +
+ {/** weird positioning?? */} +

New Cluster

+ {messages[props.controller.step()]}
- +
+
+ +
+ +
+ + +
+
+
); } diff --git a/apps/frontend/src/ui/components/overlay/cluster/ClusterStepTwo.tsx b/apps/frontend/src/ui/components/overlay/cluster/ClusterStepTwo.tsx index ed6b94ef..0db0c04b 100644 --- a/apps/frontend/src/ui/components/overlay/cluster/ClusterStepTwo.tsx +++ b/apps/frontend/src/ui/components/overlay/cluster/ClusterStepTwo.tsx @@ -1,6 +1,6 @@ import { TextInputIcon } from '@untitled-theme/icons-solid'; import { For, Index, type JSX, Show, createEffect, createSignal, on, onMount, splitProps, untrack } from 'solid-js'; -import { type ClusterStepProps, useClusterModalController } from './ClusterCreationModal'; +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'; @@ -37,12 +37,10 @@ const loaders: { ]; export function ClusterStepTwo(props: ClusterStepProps) { - const { partialCluster, updatePartialCluster } = useClusterModalController(); - const check = () => { - const hasName = (partialCluster().name?.length ?? 0) > 0; - const hasVersion = (partialCluster().mc_version?.length ?? 0) > 0; - const hasLoader = (partialCluster().mod_loader?.length ?? 0) > 0; + const hasName = (props.controller().partialCluster().name?.length ?? 0) > 0; + const hasVersion = (props.controller().partialCluster().mc_version?.length ?? 0) > 0; + const hasLoader = (props.controller().partialCluster().mod_loader?.length ?? 0) > 0; props.setCanGoForward(hasName && hasVersion && hasLoader); }; @@ -53,9 +51,9 @@ export function ClusterStepTwo(props: ClusterStepProps) { check(); })); - const setName = (name: string) => updatePartialCluster('name', name); - const setVersion = (version: string) => updatePartialCluster('mc_version', version); - const setLoader = (loader: Loader | string) => updatePartialCluster('mod_loader', loader.toLowerCase() as Loader); + const setName = (name: string) => props.controller().updatePartialCluster('name', name); + const setVersion = (version: string) => props.controller().updatePartialCluster('mc_version', version); + const setLoader = (loader: Loader | string) => props.controller().updatePartialCluster('mod_loader', loader.toLowerCase() as Loader); onMount(() => { setLoader('vanilla');