import { open, save } from "@tauri-apps/plugin-dialog"; import { CopyIcon, EditIcon, EllipsisIcon, FolderOpenIcon, Plus, RocketIcon, Trash2Icon, XIcon, } from "lucide-react"; import { useEffect, useState } from "react"; import { useNavigate } from "react-router"; import { toast } from "sonner"; import { openFileExplorer } from "@/client"; import InstanceEditorModal from "@/components/instance-editor-modal"; import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { cn } from "@/lib/utils"; import { useAuthStore } from "@/models/auth"; import { useGameStore } from "@/models/game"; import { useInstanceStore } from "@/models/instance"; import type { Instance } from "@/types"; export function InstancesPage() { const instancesStore = useInstanceStore(); const navigate = useNavigate(); const account = useAuthStore((state) => state.account); const { startGame, runningInstanceId, stoppingInstanceId, launchingInstanceId, stopGame, } = useGameStore(); const [showEditModal, setShowEditModal] = useState(false); const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); const [showDuplicateModal, setShowDuplicateModal] = useState(false); const [isImporting, setIsImporting] = useState(false); const [repairing, setRepairing] = useState(false); const [exportingId, setExportingId] = useState(null); // Selected / editing instance state const [selectedInstance, setSelectedInstance] = useState( null, ); const [editingInstance, setEditingInstance] = useState(null); // Form fields const [duplicateName, setDuplicateName] = useState(""); useEffect(() => { instancesStore.refresh(); }, [instancesStore.refresh]); // Handlers to open modals const openCreate = () => { navigate("/instances/create"); }; const openEdit = (instance: Instance) => { setEditingInstance({ ...instance }); setShowEditModal(true); }; const openDelete = (instance: Instance) => { setSelectedInstance(instance); setShowDeleteConfirm(true); }; const openDuplicate = (instance: Instance) => { setSelectedInstance(instance); setDuplicateName(`${instance.name} (Copy)`); setShowDuplicateModal(true); }; const confirmDelete = async () => { if (!selectedInstance) return; await instancesStore.delete(selectedInstance.id); setSelectedInstance(null); setShowDeleteConfirm(false); }; const confirmDuplicate = async () => { if (!selectedInstance) return; const name = duplicateName.trim(); if (!name) return; await instancesStore.duplicate(selectedInstance.id, name); setSelectedInstance(null); setDuplicateName(""); setShowDuplicateModal(false); }; const handleImport = async () => { setIsImporting(true); try { const selected = await open({ multiple: false, filters: [{ name: "Zip Archive", extensions: ["zip"] }], }); if (typeof selected !== "string") { return; } await instancesStore.importArchive(selected); } finally { setIsImporting(false); } }; const handleRepair = async () => { setRepairing(true); try { await instancesStore.repair(); } finally { setRepairing(false); } }; const handleExport = async (instance: Instance) => { setExportingId(instance.id); try { const filePath = await save({ defaultPath: `${instance.name.replace(/[\\/:*?"<>|]/g, "_")}.zip`, filters: [{ name: "Zip Archive", extensions: ["zip"] }], }); if (!filePath) { return; } await instancesStore.exportArchive(instance.id, filePath); } finally { setExportingId(null); } }; return (

Instances

{instancesStore.instances.length === 0 ? (

No instances yet

Create your first instance to get started

) : (
    {instancesStore.instances.map((instance) => { const isActive = instancesStore.activeInstance?.id === instance.id; const isLaunching = launchingInstanceId === instance.id; const isStopping = stoppingInstanceId === instance.id; const isRunning = runningInstanceId === instance.id; return (
  • instancesStore.setActiveInstance(instance)} onKeyDown={async (e) => { if (e.key === "Enter") { try { await instancesStore.setActiveInstance(instance); } catch (e) { console.error("Failed to set active instance:", e); toast.error("Error setting active instance"); } } }} className="cursor-pointer" >
    {instance.iconPath ? (
    {instance.name}
    ) : (
    {instance.name.charAt(0).toUpperCase()}
    )}

    {instance.name}

    {instance.versionId ? (

    {instance.versionId}

    ) : (

    No version selected

    )}
  • ); })}
)} {/**/} { setShowEditModal(open); if (!open) setEditingInstance(null); }} /> {/* Delete Confirmation */} Delete Instance Are you sure you want to delete "{selectedInstance?.name}"? This action cannot be undone. {/* Duplicate Modal */} Duplicate Instance Provide a name for the duplicated instance.
setDuplicateName(e.target.value)} placeholder="New instance name" onKeyDown={(e) => e.key === "Enter" && confirmDuplicate()} />
); }