diff options
| author | 2026-02-25 00:16:53 +0800 | |
|---|---|---|
| committer | 2026-02-25 00:16:53 +0800 | |
| commit | a6773bd092db654360c599ca6b0108ea0e456e8c (patch) | |
| tree | c78c802a2563fff7aef908532a0706c0299830ac /packages/ui-new/src/pages | |
| parent | b275a3668b140d9ce4663de646519d2dbd4297e7 (diff) | |
| download | DropOut-a6773bd092db654360c599ca6b0108ea0e456e8c.tar.gz DropOut-a6773bd092db654360c599ca6b0108ea0e456e8c.zip | |
feat: prepare for nightly alpha
Diffstat (limited to 'packages/ui-new/src/pages')
| -rw-r--r-- | packages/ui-new/src/pages/assistant-view.tsx.bk (renamed from packages/ui-new/src/pages/assistant-view.tsx) | 0 | ||||
| -rw-r--r-- | packages/ui-new/src/pages/index-old.tsx | 187 | ||||
| -rw-r--r-- | packages/ui-new/src/pages/instances-view.tsx | 87 | ||||
| -rw-r--r-- | packages/ui-new/src/pages/settings-view.tsx.bk (renamed from packages/ui-new/src/pages/settings-view.tsx) | 0 | ||||
| -rw-r--r-- | packages/ui-new/src/pages/versions-view.tsx.bk (renamed from packages/ui-new/src/pages/versions-view.tsx) | 6 |
5 files changed, 19 insertions, 261 deletions
diff --git a/packages/ui-new/src/pages/assistant-view.tsx b/packages/ui-new/src/pages/assistant-view.tsx.bk index 56f827b..56f827b 100644 --- a/packages/ui-new/src/pages/assistant-view.tsx +++ b/packages/ui-new/src/pages/assistant-view.tsx.bk diff --git a/packages/ui-new/src/pages/index-old.tsx b/packages/ui-new/src/pages/index-old.tsx deleted file mode 100644 index a6626c9..0000000 --- a/packages/ui-new/src/pages/index-old.tsx +++ /dev/null @@ -1,187 +0,0 @@ -import { useEffect } from "react"; -import { Outlet } from "react-router"; -import { BottomBar } from "@/components/bottom-bar"; -import { DownloadMonitor } from "@/components/download-monitor"; -import { GameConsole } from "@/components/game-console"; -import { LoginModal } from "@/components/login-modal"; -import { ParticleBackground } from "@/components/particle-background"; -import { Sidebar } from "@/components/sidebar"; - -import { useAuthStore } from "@/stores/auth-store"; -import { useGameStore } from "@/stores/game-store"; -import { useInstancesStore } from "@/stores/instances-store"; -import { useLogsStore } from "@/stores/logs-store"; -import { useSettingsStore } from "@/stores/settings-store"; -import { useUIStore } from "@/stores/ui-store"; - -export function IndexPage() { - const authStore = useAuthStore(); - const settingsStore = useSettingsStore(); - const uiStore = useUIStore(); - const instancesStore = useInstancesStore(); - const gameStore = useGameStore(); - const logsStore = useLogsStore(); - useEffect(() => { - // ENFORCE DARK MODE: Always add 'dark' class and attribute - document.documentElement.classList.add("dark"); - document.documentElement.setAttribute("data-theme", "dark"); - document.documentElement.classList.remove("light"); - - // Initialize stores - // Include store functions in the dependency array to satisfy hooks lint. - // These functions are stable in our store implementation, so listing them - // here is safe and prevents lint warnings. - authStore.checkAccount(); - settingsStore.loadSettings(); - logsStore.init(); - settingsStore.detectJava(); - instancesStore.loadInstances(); - gameStore.loadVersions(); - - // Note: getVersion() would need Tauri API setup - // getVersion().then((v) => uiStore.setAppVersion(v)); - }, [ - authStore.checkAccount, - settingsStore.loadSettings, - logsStore.init, - settingsStore.detectJava, - instancesStore.loadInstances, - gameStore.loadVersions, - ]); - - // Refresh versions when active instance changes - useEffect(() => { - if (instancesStore.activeInstanceId) { - gameStore.loadVersions(); - } else { - gameStore.setVersions([]); - } - }, [ - instancesStore.activeInstanceId, - gameStore.loadVersions, - gameStore.setVersions, - ]); - - return ( - <div className="relative h-screen w-screen overflow-hidden dark:text-white text-gray-900 font-sans selection:bg-indigo-500/30"> - {/* Modern Animated Background */} - <div className="absolute inset-0 z-0 bg-gray-100 dark:bg-[#09090b] overflow-hidden"> - {settingsStore.settings.customBackgroundPath && ( - <img - src={settingsStore.settings.customBackgroundPath} - alt="Background" - className="absolute inset-0 w-full h-full object-cover transition-transform duration-[20s] ease-linear" - onError={(e) => console.error("Failed to load main background:", e)} - /> - )} - - {/* Dimming Overlay for readability */} - {settingsStore.settings.customBackgroundPath && ( - <div className="absolute inset-0 bg-black/50"></div> - )} - - {!settingsStore.settings.customBackgroundPath && ( - <> - {settingsStore.settings.theme === "dark" ? ( - <div className="absolute inset-0 opacity-60 bg-linear-to-br from-emerald-900 via-zinc-900 to-indigo-950"></div> - ) : ( - <div className="absolute inset-0 opacity-100 bg-linear-to-br from-emerald-100 via-gray-100 to-indigo-100"></div> - )} - - {uiStore.currentView === "home" && <ParticleBackground />} - - <div className="absolute inset-0 bg-linear-to-t from-zinc-900 via-transparent to-black/50 dark:from-zinc-900 dark:to-black/50"></div> - </> - )} - - {/* Subtle Grid Overlay */} - <div - className="absolute inset-0 z-0 dark:opacity-10 opacity-30 pointer-events-none" - style={{ - backgroundImage: `linear-gradient(${ - settingsStore.settings.theme === "dark" ? "#ffffff" : "#000000" - } 1px, transparent 1px), linear-gradient(90deg, ${ - settingsStore.settings.theme === "dark" ? "#ffffff" : "#000000" - } 1px, transparent 1px)`, - backgroundSize: "40px 40px", - maskImage: - "radial-gradient(circle at 50% 50%, black 30%, transparent 70%)", - }} - ></div> - </div> - - {/* Content Wrapper */} - <div className="relative z-10 flex h-full p-4 gap-4 text-gray-900 dark:text-white"> - {/* Floating Sidebar */} - <Sidebar /> - - {/* Main Content Area - Transparent & Flat */} - <main className="flex-1 flex flex-col relative min-w-0 overflow-hidden transition-all duration-300"> - {/* Window Drag Region */} - <div - className="h-8 w-full absolute top-0 left-0 z-50 drag-region" - data-tauri-drag-region - ></div> - - {/* App Content */} - <div className="flex-1 relative overflow-hidden flex flex-col"> - {/* Views Container */} - <div className="flex-1 relative overflow-hidden"> - <Outlet /> - </div> - - {/* Download Monitor Overlay */} - <div className="absolute bottom-20 left-4 right-4 pointer-events-none z-20"> - <div className="pointer-events-auto"> - <DownloadMonitor /> - </div> - </div> - - {/* Bottom Bar */} - {uiStore.currentView === "home" && <BottomBar />} - </div> - </main> - </div> - - {/* Logout Confirmation Dialog */} - {authStore.isLogoutConfirmOpen && ( - <div className="fixed inset-0 z-200 bg-black/70 backdrop-blur-sm flex items-center justify-center p-4"> - <div className="bg-zinc-900 border border-zinc-700 rounded-xl shadow-2xl p-6 max-w-sm w-full animate-in fade-in zoom-in-95 duration-200"> - <h3 className="text-lg font-bold text-white mb-2">Logout</h3> - <p className="text-zinc-400 text-sm mb-6"> - Are you sure you want to logout{" "} - <span className="text-white font-medium"> - {authStore.currentAccount?.username} - </span> - ? - </p> - <div className="flex gap-3 justify-end"> - <button - type="button" - onClick={() => authStore.cancelLogout()} - className="px-4 py-2 text-sm font-medium text-zinc-300 hover:text-white bg-zinc-800 hover:bg-zinc-700 rounded-lg transition-colors" - > - Cancel - </button> - <button - type="button" - onClick={() => authStore.confirmLogout()} - className="px-4 py-2 text-sm font-medium text-white bg-red-600 hover:bg-red-500 rounded-lg transition-colors" - > - Logout - </button> - </div> - </div> - </div> - )} - - {uiStore.showConsole && ( - <div className="fixed inset-0 z-100 bg-black/80 backdrop-blur-sm flex items-center justify-center p-8"> - <div className="w-full h-full max-w-6xl max-h-[85vh] bg-[#1e1e1e] rounded-lg overflow-hidden border border-zinc-700 shadow-2xl relative flex flex-col"> - <GameConsole /> - </div> - </div> - )} - </div> - ); -} diff --git a/packages/ui-new/src/pages/instances-view.tsx b/packages/ui-new/src/pages/instances-view.tsx index 0c511a1..ad6bd38 100644 --- a/packages/ui-new/src/pages/instances-view.tsx +++ b/packages/ui-new/src/pages/instances-view.tsx @@ -1,5 +1,6 @@ import { Copy, Edit2, Plus, Trash2 } from "lucide-react"; import { useEffect, useState } from "react"; +import InstanceCreationModal from "@/components/instance-creation-modal"; import InstanceEditorModal from "@/components/instance-editor-modal"; import { Button } from "@/components/ui/button"; import { @@ -12,7 +13,7 @@ import { } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { toNumber } from "@/lib/tsrs-utils"; -import { useInstancesStore } from "@/stores/instances-store"; +import { useInstancesStore } from "@/models/instances"; import type { Instance } from "../types/bindings/instance"; export function InstancesView() { @@ -31,19 +32,14 @@ export function InstancesView() { const [editingInstance, setEditingInstance] = useState<Instance | null>(null); // Form fields - const [newInstanceName, setNewInstanceName] = useState(""); const [duplicateName, setDuplicateName] = useState(""); - // Load instances on mount (matches Svelte onMount behavior) useEffect(() => { - instancesStore.loadInstances(); - // instancesStore methods are stable (Zustand); do not add to deps to avoid spurious runs - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [instancesStore.loadInstances]); + instancesStore.refresh(); + }, [instancesStore.refresh]); // Handlers to open modals const openCreate = () => { - setNewInstanceName(""); setShowCreateModal(true); }; @@ -63,25 +59,9 @@ export function InstancesView() { setShowDuplicateModal(true); }; - // Confirm actions - const confirmCreate = async () => { - const name = newInstanceName.trim(); - if (!name) return; - await instancesStore.createInstance(name); - setShowCreateModal(false); - setNewInstanceName(""); - }; - - const confirmEdit = async () => { - if (!editingInstance) return; - await instancesStore.updateInstance(editingInstance); - setEditingInstance(null); - setShowEditModal(false); - }; - const confirmDelete = async () => { if (!selectedInstance) return; - await instancesStore.deleteInstance(selectedInstance.id); + await instancesStore.delete(selectedInstance.id); setSelectedInstance(null); setShowDeleteConfirm(false); }; @@ -90,16 +70,12 @@ export function InstancesView() { if (!selectedInstance) return; const name = duplicateName.trim(); if (!name) return; - await instancesStore.duplicateInstance(selectedInstance.id, name); + await instancesStore.duplicate(selectedInstance.id, name); setSelectedInstance(null); setDuplicateName(""); setShowDuplicateModal(false); }; - const setActiveInstance = async (id: string) => { - await instancesStore.setActiveInstance(id); - }; - const formatDate = (timestamp: number): string => new Date(timestamp * 1000).toLocaleDateString(); @@ -124,7 +100,7 @@ export function InstancesView() { <Button type="button" onClick={openCreate} - className="flex items-center gap-2 px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg transition-colors" + className="px-4 py-2 transition-colors" > <Plus size={18} /> Create Instance @@ -141,16 +117,17 @@ export function InstancesView() { ) : ( <ul className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"> {instancesStore.instances.map((instance) => { - const isActive = instancesStore.activeInstanceId === instance.id; + const isActive = instancesStore.activeInstance?.id === instance.id; return ( <li key={instance.id} - onClick={() => setActiveInstance(instance.id)} + onClick={() => instancesStore.setActiveInstance(instance)} onKeyDown={(e) => - e.key === "Enter" && setActiveInstance(instance.id) + e.key === "Enter" && + instancesStore.setActiveInstance(instance) } - className={`relative p-4 text-left rounded-lg border-2 transition-all cursor-pointer hover:border-blue-500 ${ + className={`relative p-4 text-left border-2 transition-all cursor-pointer hover:border-blue-500 ${ isActive ? "border-blue-500" : "border-transparent" } bg-gray-100 dark:bg-gray-800`} > @@ -245,42 +222,10 @@ export function InstancesView() { </ul> )} - {/* Create Modal */} - <Dialog open={showCreateModal} onOpenChange={setShowCreateModal}> - <DialogContent> - <DialogHeader> - <DialogTitle>Create Instance</DialogTitle> - <DialogDescription> - Enter a name for the new instance. - </DialogDescription> - </DialogHeader> - - <div className="mt-4"> - <Input - value={newInstanceName} - onChange={(e) => setNewInstanceName(e.target.value)} - placeholder="Instance name" - /> - </div> - - <DialogFooter> - <Button - type="button" - variant="outline" - onClick={() => setShowCreateModal(false)} - > - Cancel - </Button> - <Button - type="button" - onClick={confirmCreate} - disabled={!newInstanceName.trim()} - > - Create - </Button> - </DialogFooter> - </DialogContent> - </Dialog> + <InstanceCreationModal + open={showCreateModal} + onOpenChange={setShowCreateModal} + /> <InstanceEditorModal open={showEditModal} diff --git a/packages/ui-new/src/pages/settings-view.tsx b/packages/ui-new/src/pages/settings-view.tsx.bk index ac43d9b..ac43d9b 100644 --- a/packages/ui-new/src/pages/settings-view.tsx +++ b/packages/ui-new/src/pages/settings-view.tsx.bk diff --git a/packages/ui-new/src/pages/versions-view.tsx b/packages/ui-new/src/pages/versions-view.tsx.bk index 7f44611..d54596d 100644 --- a/packages/ui-new/src/pages/versions-view.tsx +++ b/packages/ui-new/src/pages/versions-view.tsx.bk @@ -17,8 +17,8 @@ import { import { Input } from "@/components/ui/input"; import { ScrollArea } from "@/components/ui/scroll-area"; import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"; +import { useInstancesStore } from "../models/instances"; import { useGameStore } from "../stores/game-store"; -import { useInstancesStore } from "../stores/instances-store"; import type { Version } from "../types/bindings/manifest"; interface InstalledModdedVersion { @@ -31,7 +31,7 @@ type TypeFilter = "all" | "release" | "snapshot" | "installed"; export function VersionsView() { const { versions, selectedVersion, loadVersions, setSelectedVersion } = useGameStore(); - const { activeInstanceId } = useInstancesStore(); + const { activeInstance } = useInstancesStore(); const [searchQuery, setSearchQuery] = useState(""); const [typeFilter, setTypeFilter] = useState<TypeFilter>("all"); @@ -54,7 +54,7 @@ export function VersionsView() { // Load installed modded versions with Java version info const loadInstalledModdedVersions = useCallback(async () => { - if (!activeInstanceId) { + if (!activeInstance) { setInstalledModdedVersions([]); setIsLoadingModded(false); return; |