diff options
| author | 2026-03-29 21:35:34 +0800 | |
|---|---|---|
| committer | 2026-03-29 21:35:34 +0800 | |
| commit | 70348cefb7de8c1e044800296a99177309c5a81e (patch) | |
| tree | eb0fdfbcc880574e9b386a3f2fc9b3a89489e5b5 /packages/ui/src/stores/game-store.ts | |
| parent | f2f5383a1b615a7493316d558dc55271198e772a (diff) | |
| parent | 1c115141cc7b676e6a07786594155c3ac293fe34 (diff) | |
| download | DropOut-70348cefb7de8c1e044800296a99177309c5a81e.tar.gz DropOut-70348cefb7de8c1e044800296a99177309c5a81e.zip | |
refactor(ui): full rewrite instance and code struct (#129)
## Summary by Sourcery
Refactor the UI to modernize effect handling, routing, and legacy APIs
while adding a reusable alert dialog component and cleaning up obsolete
stores.
New Features:
- Introduce a shared SaturnEffect context via ParticleBackground so
pages can access the effect without relying on global window APIs.
- Add a Base UI–powered alert dialog component for consistent
confirmation and warning flows across the app.
- Define a central router configuration module with instance routes to
standardize page wiring.
Bug Fixes:
- Ensure SaturnEffect nullish checks are handled safely when forwarding
pointer and touch events from the home view.
Enhancements:
- Rewrite ParticleBackground to manage its own SaturnEffect lifecycle
via React state and context instead of global accessors.
- Update the home view to use the SaturnEffect hook, simplify
pointer/touch handlers, and remove legacy game and release store usage.
- Refine layout and accessibility attributes for various form field and
label components, including field grouping and error rendering keys.
- Simplify sidebar navigation and adjust the user dropdown trigger to
work with the updated dropdown menu API.
- Wrap the root outlet for the home route with ParticleBackground only
on the index path to limit the effect to the intended view.
- Clean up imports and code style in radio group and other UI primitives
for consistency.
Chores:
- Remove deprecated UI stores and utility modules that are no longer
used with the new architecture.
- Add changeset entries documenting the Saturn effect refactor,
ParticleBackground rewrite, and removal of legacy store code.
Diffstat (limited to 'packages/ui/src/stores/game-store.ts')
| -rw-r--r-- | packages/ui/src/stores/game-store.ts | 182 |
1 files changed, 0 insertions, 182 deletions
diff --git a/packages/ui/src/stores/game-store.ts b/packages/ui/src/stores/game-store.ts deleted file mode 100644 index 1eaf7e7..0000000 --- a/packages/ui/src/stores/game-store.ts +++ /dev/null @@ -1,182 +0,0 @@ -import { listen, type UnlistenFn } from "@tauri-apps/api/event"; -import { toast } from "sonner"; -import { create } from "zustand"; -import { - getVersions, - getVersionsOfInstance, - startGame as startGameCommand, - stopGame as stopGameCommand, -} from "@/client"; -import type { Account } from "@/types/bindings/auth"; -import type { GameExitedEvent } from "@/types/bindings/core"; -import type { Version } from "@/types/bindings/manifest"; - -interface GameState { - versions: Version[]; - selectedVersion: string; - runningInstanceId: string | null; - runningVersionId: string | null; - launchingInstanceId: string | null; - stoppingInstanceId: string | null; - lifecycleUnlisten: UnlistenFn | null; - - latestRelease: Version | undefined; - isGameRunning: boolean; - - initLifecycle: () => Promise<void>; - loadVersions: (instanceId?: string) => Promise<void>; - startGame: ( - currentAccount: Account | null, - openLoginModal: () => void, - activeInstanceId: string | null, - versionId: string | null, - setView: (view: string) => void, - ) => Promise<string | null>; - stopGame: (instanceId?: string | null) => Promise<string | null>; - setSelectedVersion: (version: string) => void; - setVersions: (versions: Version[]) => void; -} - -export const useGameStore = create<GameState>((set, get) => ({ - versions: [], - selectedVersion: "", - runningInstanceId: null, - runningVersionId: null, - launchingInstanceId: null, - stoppingInstanceId: null, - lifecycleUnlisten: null, - - get latestRelease() { - return get().versions.find((v) => v.type === "release"); - }, - - get isGameRunning() { - return get().runningInstanceId !== null; - }, - - initLifecycle: async () => { - if (get().lifecycleUnlisten) { - return; - } - - const unlisten = await listen<GameExitedEvent>("game-exited", (event) => { - const { instanceId, versionId, wasStopped } = event.payload; - - set({ - runningInstanceId: null, - runningVersionId: null, - launchingInstanceId: null, - stoppingInstanceId: null, - }); - - if (wasStopped) { - toast.success(`Stopped Minecraft ${versionId} for instance ${instanceId}`); - } else { - toast.info(`Minecraft ${versionId} exited for instance ${instanceId}`); - } - }); - - set({ lifecycleUnlisten: unlisten }); - }, - - loadVersions: async (instanceId?: string) => { - try { - const versions = instanceId - ? await getVersionsOfInstance(instanceId) - : await getVersions(); - set({ versions: versions ?? [] }); - } catch (e) { - console.error("Failed to load versions:", e); - set({ versions: [] }); - } - }, - - startGame: async ( - currentAccount, - openLoginModal, - activeInstanceId, - versionId, - setView, - ) => { - const { isGameRunning } = get(); - const targetVersion = versionId ?? get().selectedVersion; - - if (!currentAccount) { - toast.info("Please login first"); - openLoginModal(); - return null; - } - - if (!targetVersion) { - toast.info("Please select a version first"); - return null; - } - - if (!activeInstanceId) { - toast.info("Please select an instance first"); - setView("instances"); - return null; - } - - if (isGameRunning) { - toast.info("A game is already running"); - return null; - } - - set({ - launchingInstanceId: activeInstanceId, - selectedVersion: targetVersion, - }); - toast.info(`Preparing to launch ${targetVersion}...`); - - try { - const message = await startGameCommand(activeInstanceId, targetVersion); - set({ - launchingInstanceId: null, - runningInstanceId: activeInstanceId, - runningVersionId: targetVersion, - }); - toast.success(message); - return message; - } catch (e) { - console.error(e); - set({ launchingInstanceId: null }); - toast.error(`Error: ${e}`); - return null; - } - }, - - stopGame: async (instanceId) => { - const { runningInstanceId } = get(); - - if (!runningInstanceId) { - toast.info("No running game found"); - return null; - } - - if (instanceId && instanceId !== runningInstanceId) { - toast.info("That instance is not the one currently running"); - return null; - } - - set({ stoppingInstanceId: runningInstanceId }); - - try { - return await stopGameCommand(); - } catch (e) { - console.error("Failed to stop game:", e); - toast.error(`Failed to stop game: ${e}`); - return null; - } finally { - set({ stoppingInstanceId: null }); - } - }, - - setSelectedVersion: (version: string) => { - set({ selectedVersion: version }); - }, - - setVersions: (versions: Version[]) => { - set({ versions }); - }, -})); |