Drag and drop UI

This commit is contained in:
Kr4ight
2026-04-05 18:17:49 +02:00
parent d71c0c437d
commit e71617d535
5 changed files with 110 additions and 35 deletions
+27 -1
View File
@@ -16,6 +16,7 @@
"lucide-react": "^1.7.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-hot-toast": "^2.6.0",
"tailwind-merge": "^3.5.0",
"tailwindcss": "^4.2.2"
},
@@ -1776,7 +1777,6 @@
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
"dev": true,
"license": "MIT"
},
"node_modules/debug": {
@@ -1945,6 +1945,15 @@
"node": ">=6.9.0"
}
},
"node_modules/goober": {
"version": "2.1.18",
"resolved": "https://registry.npmjs.org/goober/-/goober-2.1.18.tgz",
"integrity": "sha512-2vFqsaDVIT9Gz7N6kAL++pLpp41l3PfDuusHcjnGLfR6+huZkl6ziX+zgVC3ZxpqWhzH6pyDdGrCeDhMIvwaxw==",
"license": "MIT",
"peerDependencies": {
"csstype": "^3.0.10"
}
},
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
@@ -2384,6 +2393,23 @@
"react": "^19.2.4"
}
},
"node_modules/react-hot-toast": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.6.0.tgz",
"integrity": "sha512-bH+2EBMZ4sdyou/DPrfgIouFpcRLCJ+HoCA32UoAYHn6T3Ur5yfcDCeSr5mwldl6pFOsiocmrXMuoCJ1vV8bWg==",
"license": "MIT",
"dependencies": {
"csstype": "^3.1.3",
"goober": "^2.1.16"
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
"react": ">=16",
"react-dom": ">=16"
}
},
"node_modules/react-refresh": {
"version": "0.17.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz",
+1
View File
@@ -18,6 +18,7 @@
"lucide-react": "^1.7.0",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-hot-toast": "^2.6.0",
"tailwind-merge": "^3.5.0",
"tailwindcss": "^4.2.2"
},
+4 -4
View File
@@ -290,11 +290,11 @@ pub fn update_version(state: State<SharedState>, version: String) {
#[tauri::command]
pub async fn install_paths(
app: &AppHandle,
state: &SharedState,
paths: &Vec<String>,
app: AppHandle,
state: State<'_, SharedState>,
paths: Vec<String>,
) -> Result<(), String> {
for path in paths {
for path in &paths {
let file = Path::new(&path)
.file_name()
.and_then(|name| name.to_str())
+1
View File
@@ -20,6 +20,7 @@ fn main() {
saturn_launcher_lib::commands::update_settings,
saturn_launcher_lib::commands::get_version,
saturn_launcher_lib::commands::update_version,
saturn_launcher_lib::commands::install_paths,
// Launcher Commands
saturn_launcher_lib::launcher::launch_game,
// Auth Commands
+77 -30
View File
@@ -7,8 +7,10 @@ import SettingsSection from "./components/SettingsSection";
import { versions } from "./lib/launcher";
import { GameVersion } from "./lib/types";
import { MinecraftAccount } from "./lib/auth";
import { getVersion, updateVersion } from "./lib/saturn";
import { getVersion, installPaths, updateVersion } from "./lib/saturn";
import { getCurrentWindow } from "@tauri-apps/api/window";
import { listen } from "@tauri-apps/api/event";
import toast, { Toaster } from "react-hot-toast";
type Section = "play" | "mods" | "settings";
@@ -68,37 +70,82 @@ export default function App() {
window.show();
}, []);
useEffect(() => {
if (!selectedVersion?.id) return;
const version = selectedVersion?.id;
const unlistenInstalls = listen<string[]>("install-paths", (event) => {
event.payload.forEach((path) => {
const fileName = path.split(/[\\/]/).pop();
toast.promise(installPaths(version, [path]), {
loading: `${fileName}`,
success: `${fileName}`,
error: `${fileName} Failed`
}).catch(console.error);
});
});
return () => {
unlistenInstalls.then((f) => f());
};
}, [selectedVersion]);
return (
<div className="flex h-screen">
<Sidebar active={active} setActive={setActive} />
<>
<Toaster position="bottom-right" toastOptions={{
loading: {
style: {
backgroundColor: 'var(--color-saturn-panel)',
color: 'var(--color-saturn-text-primary)'
}
},
success: {
style: {
backgroundColor: 'var(--color-saturn-panel)',
color: 'var(--color-saturn-text-primary)'
}
},
error: {
style: {
backgroundColor: 'var(--color-saturn-panel)',
color: 'var(--color-saturn-text-primary)'
}
}
}} />
<main className="flex-1 flex flex-col">
<TopBar
versions={versions}
selectedVersion={selectedVersion}
setSelectedVersion={setSelectedVersion}
isVersionDropdownOpen={isVersionDropdownOpen}
setIsVersionDropdownOpen={setIsVersionDropdownOpen}
isAccountDropdownOpen={isAccountDropdownOpen}
setIsAccountDropdownOpen={setIsAccountDropdownOpen}
versionRef={versionRef}
accountRef={accountRef}
accounts={accounts}
setAccounts={setAccounts}
activeAccount={activeAccount}
setActiveAccount={setActiveAccount}
/>
<div className="flex h-screen">
<Sidebar active={active} setActive={setActive} />
<div className="flex-1 p-8 overflow-y-scroll">
{active === "play" && (
<PlaySection version={selectedVersion} account={activeAccount} />
)}
{active === "mods" && selectedVersion && (
<ModsSection version={selectedVersion} />
)}
{active === "settings" && <SettingsSection />}
</div>
</main>
</div>
<main className="flex-1 flex flex-col">
<TopBar
versions={versions}
selectedVersion={selectedVersion}
setSelectedVersion={setSelectedVersion}
isVersionDropdownOpen={isVersionDropdownOpen}
setIsVersionDropdownOpen={setIsVersionDropdownOpen}
isAccountDropdownOpen={isAccountDropdownOpen}
setIsAccountDropdownOpen={setIsAccountDropdownOpen}
versionRef={versionRef}
accountRef={accountRef}
accounts={accounts}
setAccounts={setAccounts}
activeAccount={activeAccount}
setActiveAccount={setActiveAccount}
/>
<div className="flex-1 p-8 overflow-y-scroll">
{active === "play" && (
<PlaySection version={selectedVersion} account={activeAccount} />
)}
{active === "mods" && selectedVersion && (
<ModsSection version={selectedVersion} />
)}
{active === "settings" && <SettingsSection />}
</div>
</main>
</div>
</>
);
}