diff options
| author | 2026-02-26 18:32:06 +0800 | |
|---|---|---|
| committer | 2026-02-26 18:32:06 +0800 | |
| commit | 120c0a460162226446cce4cfbc4c7e5859cd9d09 (patch) | |
| tree | 91739f044507c2bf0ef8d9956f46cbb99fdb890f /packages/ui | |
| parent | d95ca2801c19a89a2a845f43b6e0133bf4e9be50 (diff) | |
| download | DropOut-120c0a460162226446cce4cfbc4c7e5859cd9d09.tar.gz DropOut-120c0a460162226446cce4cfbc4c7e5859cd9d09.zip | |
feat(ui): improve launching game
Diffstat (limited to 'packages/ui')
| -rw-r--r-- | packages/ui/src/components/bottom-bar.tsx | 104 |
1 files changed, 70 insertions, 34 deletions
diff --git a/packages/ui/src/components/bottom-bar.tsx b/packages/ui/src/components/bottom-bar.tsx index 32eb852..5489675 100644 --- a/packages/ui/src/components/bottom-bar.tsx +++ b/packages/ui/src/components/bottom-bar.tsx @@ -1,11 +1,11 @@ import { listen, type UnlistenFn } from "@tauri-apps/api/event"; -import { Play, User } from "lucide-react"; -import { useCallback, useEffect, useMemo, useState } from "react"; +import { Play, User, XIcon } from "lucide-react"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { toast } from "sonner"; import { listInstalledVersions, startGame } from "@/client"; import { cn } from "@/lib/utils"; import { useAuthStore } from "@/models/auth"; -import { useInstancesStore } from "@/models/instances"; +import { useInstanceStore } from "@/models/instance"; import { useGameStore } from "@/stores/game-store"; import { LoginModal } from "./login-modal"; import { Button } from "./ui/button"; @@ -17,6 +17,7 @@ import { SelectTrigger, SelectValue, } from "./ui/select"; +import { Spinner } from "./ui/spinner"; interface InstalledVersion { id: string; @@ -26,8 +27,11 @@ interface InstalledVersion { export function BottomBar() { const authStore = useAuthStore(); const gameStore = useGameStore(); - const instancesStore = useInstancesStore(); + const instancesStore = useInstanceStore(); + const [isLaunched, setIsLaunched] = useState<boolean>(false); + const gameUnlisten = useRef<UnlistenFn | null>(null); + const [isLaunching, setIsLaunching] = useState<boolean>(false); const [selectedVersion, setSelectedVersion] = useState<string | null>(null); const [installedVersions, setInstalledVersions] = useState< InstalledVersion[] @@ -118,13 +122,25 @@ export function BottomBar() { toast.info("Please select an instance first!"); return; } - // await gameStore.startGame( - // authStore.currentAccount, - // authStore.openLoginModal, - // instancesStore.activeInstanceId, - // uiStore.setView, - // ); - await startGame(instancesStore.activeInstance?.id, selectedVersion); + + try { + gameUnlisten.current = await listen("game-exited", () => { + setIsLaunched(false); + }); + } catch (error) { + toast.warning(`Failed to listen to game-exited event: ${error}`); + } + + setIsLaunching(true); + try { + await startGame(instancesStore.activeInstance?.id, selectedVersion); + setIsLaunched(true); + } catch (error) { + console.error(`Failed to start game: ${error}`); + toast.error(`Failed to start game: ${error}`); + } finally { + setIsLaunching(false); + } }; const getVersionTypeColor = (type: string) => { @@ -152,6 +168,48 @@ export function BottomBar() { [installedVersions], ); + const renderButton = () => { + if (!authStore.account) { + return ( + <Button + className="px-4 py-2" + size="lg" + onClick={() => setShowLoginModal(true)} + > + <User /> Login + </Button> + ); + } + + return isLaunched ? ( + <Button + variant="destructive" + onClick={() => { + toast.warning( + "Minecraft Process will not be terminated, please close it manually.", + ); + setIsLaunched(false); + }} + > + <XIcon /> + Game started + </Button> + ) : ( + <Button + className={cn( + "px-4 py-2 shadow-xl", + "bg-emerald-600! hover:bg-emerald-500!", + )} + size="lg" + onClick={handleStartGame} + disabled={isLaunching} + > + {isLaunching ? <Spinner /> : <Play />} + Start + </Button> + ); + }; + return ( <div className="absolute bottom-0 left-0 right-0 bg-linear-to-t from-black/30 via-transparent to-transparent p-4 z-10"> <div className="max-w-7xl mx-auto"> @@ -196,29 +254,7 @@ export function BottomBar() { </Select> </div> - <div className="flex items-center gap-3"> - {authStore.account ? ( - <Button - className={cn( - "px-4 py-2 shadow-xl", - "bg-emerald-600! hover:bg-emerald-500!", - )} - size="lg" - onClick={handleStartGame} - > - <Play /> - Start - </Button> - ) : ( - <Button - className="px-4 py-2" - size="lg" - onClick={() => setShowLoginModal(true)} - > - <User /> Login - </Button> - )} - </div> + <div className="flex items-center gap-3">{renderButton()}</div> </div> </div> |