aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/packages/ui-new/src/pages
diff options
context:
space:
mode:
author苏向夜 <fu050409@163.com>2026-02-25 00:16:53 +0800
committer苏向夜 <fu050409@163.com>2026-02-25 00:16:53 +0800
commita6773bd092db654360c599ca6b0108ea0e456e8c (patch)
treec78c802a2563fff7aef908532a0706c0299830ac /packages/ui-new/src/pages
parentb275a3668b140d9ce4663de646519d2dbd4297e7 (diff)
downloadDropOut-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.tsx187
-rw-r--r--packages/ui-new/src/pages/instances-view.tsx87
-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;