From 2fe2749d62da4532876b7fb45cd63a8323e6e346 Mon Sep 17 00:00:00 2001 From: neoapps-dev Date: Tue, 21 Apr 2026 21:16:54 +0300 Subject: [PATCH] feat: redesign setup --- src/components/views/SetupView.tsx | 650 +++++++++++++++-------------- 1 file changed, 331 insertions(+), 319 deletions(-) diff --git a/src/components/views/SetupView.tsx b/src/components/views/SetupView.tsx index f4cc9e4..144a90e 100644 --- a/src/components/views/SetupView.tsx +++ b/src/components/views/SetupView.tsx @@ -3,7 +3,6 @@ import { motion, AnimatePresence } from "framer-motion"; import { TauriService, Runner } from "../../services/TauriService"; import { usePlatform } from "../../hooks/usePlatform"; import { useConfig, useAudio, useGame } from "../../context/LauncherContext"; - interface SetupViewProps { onComplete: () => void; } @@ -20,12 +19,11 @@ const SetupView: React.FC = ({ onComplete }) => { linuxRunner: configLinuxRunner, vfxEnabled: configVfx, rpcEnabled: configRpc, + animationsEnabled, } = useConfig(); const { playPressSound, playSfx } = useAudio(); - const { editions } = useGame(); const titleImage = editions.find(e => e.id === profile)?.titleImage || "/images/MenuTitle.png"; - const [currentStep, setCurrentStep] = useState(0); const [focusIndex, setFocusIndex] = useState(0); const [tempUsername, setTempUsername] = useState(username); @@ -34,12 +32,9 @@ const SetupView: React.FC = ({ onComplete }) => { const [isSettingUpRuntime, setIsSettingUpRuntime] = useState(false); const [setupProgress, setSetupProgress] = useState<{ stage: string; message: string; percent?: number } | null>(null); const [runtimeAlreadyInstalled, setRuntimeAlreadyInstalled] = useState(false); - const [enableVfx, setEnableVfx] = useState(configVfx); const [enableDiscordRPC, setEnableDiscordRPC] = useState(configRpc); - - const totalSteps = isLinux ? 4 : 4; - + const totalSteps = 4; useEffect(() => { if (isLinux || isMac) { TauriService.getAvailableRunners().then(availableRunners => { @@ -52,9 +47,7 @@ const SetupView: React.FC = ({ onComplete }) => { if (isMac) { checkMacOSRuntime(); - const unlisten = TauriService.onMacosProgress((progress) => { - console.log("[macOS Setup Progress]", progress); setSetupProgress(progress); }); @@ -67,31 +60,22 @@ const SetupView: React.FC = ({ onComplete }) => { const checkMacOSRuntime = async () => { try { const localStorageInstalled = localStorage.getItem('lce-macos-runtime-installed') === 'true'; - if (localStorageInstalled) { - console.log("[macOS Runtime] Using cached installation status"); try { const runtimeCheck = await TauriService.checkMacOSRuntimeInstalledFast(); if (runtimeCheck) { setRuntimeAlreadyInstalled(true); - return; } else { - console.log("[macOS Runtime] Cache was wrong, clearing"); localStorage.removeItem('lce-macos-runtime-installed'); setRuntimeAlreadyInstalled(false); - return; } - } catch (error) { - console.log("[macOS Runtime] Fast check failed, using cache"); + } catch { setRuntimeAlreadyInstalled(true); - return; } } else { - console.log("[macOS Runtime] No installation detected"); setRuntimeAlreadyInstalled(false); } - } catch (error) { - console.error("[macOS Runtime] Error checking:", error); + } catch { setRuntimeAlreadyInstalled(false); } }; @@ -103,21 +87,17 @@ const SetupView: React.FC = ({ onComplete }) => { const handleNext = async () => { playPressSound(); - if (currentStep === 0) { setUsername(tempUsername); setCurrentStep(1); setFocusIndex(0); } else if (currentStep === 1) { - if (isLinux && selectedRunner) { - setLinuxRunner(selectedRunner); - } + if (isLinux && selectedRunner) setLinuxRunner(selectedRunner); setCurrentStep(2); setFocusIndex(0); } else if (currentStep === 2) { setConfigVfx(enableVfx); setConfigRpc(enableDiscordRPC); - setCurrentStep(3); setFocusIndex(0); } else if (currentStep === 3) { @@ -137,16 +117,14 @@ const SetupView: React.FC = ({ onComplete }) => { useEffect(() => { const handleKey = (e: KeyboardEvent) => { - // Elements count per step let count = 0; - if (currentStep === 0) count = 2; // Input, Next + if (currentStep === 0) count = 2; else if (currentStep === 1) { - if (isLinux) count = runners.length + 2; // Runners, Back, Next - else if (isMac) count = 3; // Install, Back, Next - else count = 2; // Back, Next - } else if (currentStep === 2) count = 4; // 2 Toggles, Back, Next - else if (currentStep === 3) count = 2; // Back, Finish - + if (isLinux) count = runners.length + 2; + else if (isMac) count = 3; + else count = 2; + } else if (currentStep === 2) count = 4; + else if (currentStep === 3) count = 2; if (e.key === "ArrowDown" || e.key === "Tab") { e.preventDefault(); setFocusIndex((prev) => (prev + 1) % count); @@ -154,10 +132,9 @@ const SetupView: React.FC = ({ onComplete }) => { e.preventDefault(); setFocusIndex((prev) => (prev - 1 + count) % count); } else if (e.key === "Enter") { - // Handle enter based on focusIndex and step if (currentStep === 0) { - if (focusIndex === 0) handleNext(); // For input field - else if (focusIndex === 1) handleNext(); // Next button + if (focusIndex === 0) handleNext(); + else if (focusIndex === 1) handleNext(); } else if (currentStep === 1) { if (isLinux) { if (focusIndex < runners.length) handleRunnerSelect(runners[focusIndex].id); @@ -190,38 +167,37 @@ const SetupView: React.FC = ({ onComplete }) => { playPressSound(); setIsSettingUpRuntime(true); setSetupProgress({ stage: "preparing", message: "Preparing macOS runtime setup...", percent: 0 }); - try { - console.log("[macOS Setup] Starting runtime installation..."); await TauriService.setupMacosRuntime(); - console.log("[macOS Setup] Runtime installation completed successfully!"); setSetupProgress({ stage: "completed", message: "Setup completed successfully!", percent: 100 }); - localStorage.setItem('lce-macos-runtime-installed', 'true'); setRuntimeAlreadyInstalled(true); - setTimeout(() => { setCurrentStep(2); setIsSettingUpRuntime(false); setSetupProgress(null); }, 2000); } catch (e) { - console.error("[macOS Setup] Error:", e); setSetupProgress({ stage: "error", message: `Setup failed: ${e}`, percent: 0 }); setIsSettingUpRuntime(false); } }; const canProceed = () => { - if (currentStep === 0) { - return tempUsername.trim().length > 0; - } - if (currentStep === 1 && isMac) { - return runtimeAlreadyInstalled; - } + if (currentStep === 0) return tempUsername.trim().length > 0; + if (currentStep === 1 && isMac) return runtimeAlreadyInstalled; return true; }; + const stepTitles = ["Welcome", "Compatibility", "Preferences", "Ready"]; + const navBtnStyle = (isFocused: boolean) => ({ + backgroundImage: isFocused + ? "url('/images/button_highlighted.png')" + : "url('/images/Button_Background.png')", + backgroundSize: "100% 100%", + imageRendering: "pixelated" as const, + }); + return (
@@ -240,300 +216,327 @@ const SetupView: React.FC = ({ onComplete }) => { initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} - transition={{ duration: useConfig().animationsEnabled ? 0.2 : 0 }} - className="max-w-2xl w-full mx-auto flex flex-col" + transition={{ duration: animationsEnabled ? 0.2 : 0 }} + className="max-w-xl w-full mx-auto flex flex-col items-center" > -
-
-
- {Array.from({ length: totalSteps }, (_, i) => ( - - ))} -
+ }} + > +
+ {Array.from({ length: totalSteps }, (_, i) => ( +
+ ))} +
+

+ {stepTitles[currentStep]} +

+ + - - - {currentStep === 0 && ( -
-

- Welcome to Emerald Launcher -

-

Let's configure your launcher

+ {currentStep === 0 && ( +
+

+ Let's configure your launcher +

+ + {tempUsername.trim().length === 0 && ( +

A username is required to continue

+ )} +
+ )} -
- + {currentStep === 1 && isMac && ( +
+

+ {runtimeAlreadyInstalled + ? "Compatibility runtime is already installed" + : "Emerald needs a compatibility runtime to run on macOS" + } +

+ +
+ + {runtimeAlreadyInstalled ? "✓" : "⚠"} + +
+

+ {runtimeAlreadyInstalled ? "Runtime Detected" : "Runtime Not Detected"} +

+

+ {runtimeAlreadyInstalled + ? "Ready to use — you can proceed." + : "You must install the runtime before proceeding."} +

- )} - {currentStep === 1 && isMac && ( -
-

- macOS Compatibility -

-

- {runtimeAlreadyInstalled - ? "Emerald compatibility runtime is already installed" - : "Emerald needs compatibility runtime for macOS" - } -

- - {setupProgress && ( -
-

{setupProgress.stage.toUpperCase()}

-

{setupProgress.message}

- {setupProgress.percent !== undefined && ( -
-
-
- )} -
- )} - -
-
-

- {runtimeAlreadyInstalled ? "✓ Runtime Detected" : "⚠ Runtime Not Detected"} -

-

- {runtimeAlreadyInstalled - ? "The compatibility runtime is properly installed and ready to use." - : "You must install the compatibility runtime before proceeding to the next step." - } -

-
- - - - {!runtimeAlreadyInstalled && ( -

- ⚠ Installation required before proceeding to next step -

+ {setupProgress && ( +
+

{setupProgress.stage}

+

{setupProgress.message}

+ {setupProgress.percent !== undefined && ( +
+
+
)}
+ )} + +
+
- )} +
+ )} - {currentStep === 1 && isLinux && ( -
-

- Linux Compatibility -

-

Choose your preferred compatibility layer

+ {currentStep === 1 && isLinux && ( +
+

+ Choose your preferred compatibility layer +

+ {runners.length === 0 ? ( +
+

No compatible runners found. Please install Wine or Proton.

+
+ ) : ( +
+ {runners.map((runner, idx) => ( + + ))} +
+ )} +

You can change this later in settings

+
+ )} - {runners.length === 0 ? ( -
-

No compatible runners found. Please install Wine or Proton.

-
- ) : ( -
- {runners.map((runner, idx) => ( - - ))} + {currentStep === 1 && !isMac && !isLinux && ( +
+

+ Everything is ready to go! +

+
+ +
+

Windows Native Support

+

Emerald Legacy runs natively on Windows without additional requirements.

+
+
+
+ )} + + {currentStep === 2 && ( +
+

+ Choose your preferred launcher settings +

+ + + + +

You can change these later in settings

+
+ )} + + {currentStep === 3 && ( +
+

+ Emerald Launcher is now configured and ready to use! +

+ +
+
+ Username + {tempUsername} +
+ {isMac && ( +
+ Runtime + Ready
)} - -

You can change this later in settings

-
- )} - - {currentStep === 1 && !isMac && !isLinux && ( -
-

- Windows Setup -

-

Everything is ready to go!

-
✓ Native compatibility
- -
-

✓ Windows Native Support

-

Emerald Legacy runs natively on Windows without additional requirements.

+ {isLinux && selectedRunner && ( +
+ Runner + {runners.find(r => r.id === selectedRunner)?.name} +
+ )} +
+ Click Effects + {enableVfx +
+
+ Discord RPC + {enableDiscordRPC
- )} +
+ )} + + - {currentStep === 2 && ( -
-

- Customize Your Experience -

-

Choose your preferred launcher settings

- -
-
-
-
-

Click effects

-

Click particles and animations

-
- -
-
- -
-
-
-

Discord Rich Presence

-

Show your Emerald Launcher status on Discord

-
- -
-
-
- -

You can change these later in settings

-
- )} - - {currentStep === 3 && ( -
-

- Setup Complete! -

- -
-
-

Username: {tempUsername}

- {isMac && ( -

- Runtime: Ready -

- )} - {isLinux && selectedRunner && ( -

- Runner: {runners.find(r => r.id === selectedRunner)?.name} -

- )} -
-

Customization:

-
- {enableVfx && Visual Effects} - {enableDiscordRPC && Discord RPC} -
-
-
-
- -

Emerald Launcher is now configured and ready to use!

-
- )} - - -
- -
- {currentStep > 0 && ( +
+ {currentStep > 0 ? ( + ) : ( +
)}