Drag and drop UI
This commit is contained in:
Generated
+27
-1
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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
@@ -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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user