From b275a3668b140d9ce4663de646519d2dbd4297e7 Mon Sep 17 00:00:00 2001 From: 苏向夜 Date: Tue, 24 Feb 2026 22:41:36 +0800 Subject: refactor: rewrite login and settings pages --- package.json | 2 +- packages/ui-new/package.json | 2 + packages/ui-new/src/components/bottom-bar.tsx | 157 +++-------- packages/ui-new/src/components/config-editor.tsx | 111 ++++++++ packages/ui-new/src/components/login-modal.tsx | 292 ++++++++++--------- packages/ui-new/src/components/sidebar.tsx | 117 ++++---- packages/ui-new/src/components/ui/avatar.tsx | 107 +++++++ .../ui-new/src/components/ui/dropdown-menu.tsx | 269 ++++++++++++++++++ packages/ui-new/src/components/ui/field.tsx | 238 ++++++++++++++++ packages/ui-new/src/components/ui/spinner.tsx | 10 + packages/ui-new/src/components/ui/tabs.tsx | 4 +- packages/ui-new/src/components/user-avatar.tsx | 23 ++ packages/ui-new/src/main.tsx | 11 +- packages/ui-new/src/models/auth.ts | 142 ++++++++++ packages/ui-new/src/models/settings.ts | 75 +++++ packages/ui-new/src/pages/home-view.tsx | 212 +------------- packages/ui-new/src/pages/index-old.tsx | 187 +++++++++++++ packages/ui-new/src/pages/index.tsx | 173 ++---------- packages/ui-new/src/pages/settings.tsx | 310 +++++++++++++++++++++ packages/ui-new/src/types/bindings/auth.ts | 6 +- packages/ui-new/src/types/bindings/java/core.ts | 22 +- pnpm-lock.yaml | 49 ++++ src-tauri/src/core/auth.rs | 6 +- src-tauri/src/core/java/mod.rs | 2 + 24 files changed, 1845 insertions(+), 682 deletions(-) create mode 100644 packages/ui-new/src/components/config-editor.tsx create mode 100644 packages/ui-new/src/components/ui/avatar.tsx create mode 100644 packages/ui-new/src/components/ui/dropdown-menu.tsx create mode 100644 packages/ui-new/src/components/ui/field.tsx create mode 100644 packages/ui-new/src/components/ui/spinner.tsx create mode 100644 packages/ui-new/src/components/user-avatar.tsx create mode 100644 packages/ui-new/src/models/auth.ts create mode 100644 packages/ui-new/src/models/settings.ts create mode 100644 packages/ui-new/src/pages/index-old.tsx create mode 100644 packages/ui-new/src/pages/settings.tsx diff --git a/package.json b/package.json index c4d5afc..b52ef7d 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "modpack" ], "license": "MIT", - "packageManager": "pnpm@10.27.0", + "packageManager": "pnpm@10.30.1", "dependencies": { "consola": "^3.4.2", "toml": "^3.0.0" diff --git a/packages/ui-new/package.json b/packages/ui-new/package.json index fcd6aed..b26d733 100644 --- a/packages/ui-new/package.json +++ b/packages/ui-new/package.json @@ -26,6 +26,7 @@ "@tauri-apps/plugin-shell": "^2.3.4", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "es-toolkit": "^1.44.0", "lucide-react": "^0.562.0", "marked": "^17.0.1", "next-themes": "^0.4.6", @@ -35,6 +36,7 @@ "react-router": "^7.12.0", "sonner": "^2.0.7", "tailwind-merge": "^3.4.1", + "zod": "^4.3.6", "zustand": "^5.0.10" }, "devDependencies": { diff --git a/packages/ui-new/src/components/bottom-bar.tsx b/packages/ui-new/src/components/bottom-bar.tsx index a0c2c00..2653880 100644 --- a/packages/ui-new/src/components/bottom-bar.tsx +++ b/packages/ui-new/src/components/bottom-bar.tsx @@ -1,11 +1,13 @@ import { invoke } from "@tauri-apps/api/core"; import { listen, type UnlistenFn } from "@tauri-apps/api/event"; -import { Check, ChevronDown, Play, Terminal, User } from "lucide-react"; +import { Check, ChevronDown, Play, User } from "lucide-react"; import { useCallback, useEffect, useRef, useState } from "react"; -import { useAuthStore } from "@/stores/auth-store"; +import { cn } from "@/lib/utils"; +import { useAuthStore } from "@/models/auth"; import { useGameStore } from "@/stores/game-store"; import { useInstancesStore } from "@/stores/instances-store"; -import { useUIStore } from "@/stores/ui-store"; +import { LoginModal } from "./login-modal"; +import { Button } from "./ui/button"; interface InstalledVersion { id: string; @@ -16,15 +18,13 @@ export function BottomBar() { const authStore = useAuthStore(); const gameStore = useGameStore(); const instancesStore = useInstancesStore(); - const uiStore = useUIStore(); const [isVersionDropdownOpen, setIsVersionDropdownOpen] = useState(false); const [installedVersions, setInstalledVersions] = useState< InstalledVersion[] >([]); const [isLoadingVersions, setIsLoadingVersions] = useState(true); - - const dropdownRef = useRef(null); + const [showLoginModal, setShowLoginModal] = useState(false); const loadInstalledVersions = useCallback(async () => { if (!instancesStore.activeInstanceId) { @@ -61,17 +61,6 @@ export function BottomBar() { useEffect(() => { loadInstalledVersions(); - const handleClickOutside = (event: MouseEvent) => { - if ( - dropdownRef.current && - !dropdownRef.current.contains(event.target as Node) - ) { - setIsVersionDropdownOpen(false); - } - }; - - document.addEventListener("mousedown", handleClickOutside); - // Listen for backend events that should refresh installed versions. let unlistenDownload: UnlistenFn | null = null; let unlistenVersionDeleted: UnlistenFn | null = null; @@ -98,7 +87,6 @@ export function BottomBar() { })(); return () => { - document.removeEventListener("mousedown", handleClickOutside); try { if (unlistenDownload) unlistenDownload(); } catch { @@ -120,12 +108,12 @@ export function BottomBar() { }; const handleStartGame = async () => { - await gameStore.startGame( - authStore.currentAccount, - authStore.openLoginModal, - instancesStore.activeInstanceId, - uiStore.setView, - ); + // await gameStore.startGame( + // authStore.currentAccount, + // authStore.openLoginModal, + // instancesStore.activeInstanceId, + // uiStore.setView, + // ); }; const getVersionTypeColor = (type: string) => { @@ -155,8 +143,7 @@ export function BottomBar() { return (
-
- {/* Left: Instance Info */} +
@@ -166,104 +153,38 @@ export function BottomBar() { {instancesStore.activeInstance?.name || "No instance selected"}
- - {/* Version Selector */} -
- - - {/* Dropdown */} - {isVersionDropdownOpen && ( -
-
- {versionOptions.map((option) => ( - - ))} -
-
- )} -
- {/* Right: Action Buttons */}
- {/* Console Toggle */} - - - {/* User Login/Info */} - - - {/* Start Game */} - + {authStore.account ? ( + + ) : ( + + )}
+ + setShowLoginModal(false)} + />
); } diff --git a/packages/ui-new/src/components/config-editor.tsx b/packages/ui-new/src/components/config-editor.tsx new file mode 100644 index 0000000..129b8f7 --- /dev/null +++ b/packages/ui-new/src/components/config-editor.tsx @@ -0,0 +1,111 @@ +import type React from "react"; +import { useEffect, useState } from "react"; +import { type ZodType, z } from "zod"; +import { useSettingsStore } from "@/models/settings"; +import type { LauncherConfig } from "@/types"; +import { Button } from "./ui/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "./ui/dialog"; +import { FieldError } from "./ui/field"; +import { Spinner } from "./ui/spinner"; +import { Textarea } from "./ui/textarea"; + +const launcherConfigSchema: ZodType = z.object({ + minMemory: z.number(), + maxMemory: z.number(), + javaPath: z.string(), + width: z.number(), + height: z.number(), + downloadThreads: z.number(), + customBackgroundPath: z.string().nullable(), + enableGpuAcceleration: z.boolean(), + enableVisualEffects: z.boolean(), + activeEffect: z.string(), + theme: z.string(), + logUploadService: z.string(), + pastebinApiKey: z.string().nullable(), + assistant: z.any(), // TODO: AssistantConfig schema + useSharedCaches: z.boolean(), + keepLegacyPerInstanceStorage: z.boolean(), + featureFlags: z.any(), // TODO: FeatureFlags schema +}); + +export interface ConfigEditorProps + extends Omit, "onOpenChange"> { + open: boolean; + onOpenChange: (open: boolean) => void; +} + +export function ConfigEditor({ onOpenChange, ...props }: ConfigEditorProps) { + const settings = useSettingsStore(); + + const [errorMessage, setErrorMessage] = useState(null); + const [rawConfigContent, setRawConfigContent] = useState( + JSON.stringify(settings.config, null, 2), + ); + const [isSaving, setIsSaving] = useState(false); + + useEffect(() => { + setRawConfigContent(JSON.stringify(settings.config, null, 2)); + }, [settings.config]); + + const handleSave = async () => { + setIsSaving(true); + setErrorMessage(null); + try { + const validatedConfig = launcherConfigSchema.parse( + JSON.parse(rawConfigContent), + ); + settings.config = validatedConfig; + await settings.save(); + onOpenChange?.(false); + } catch (error) { + setErrorMessage(error instanceof Error ? error.message : String(error)); + } finally { + setIsSaving(false); + } + }; + + return ( + + + + Edit Configuration + + Edit the raw JSON configuration file. + + + +