Clusters
Something something in corporate style fashion about picking your preferred gamemodes and versions and optionally loader so that oneclient can pick something for them
diff --git a/apps/oneclient/frontend/src/routes/onboarding/account.tsx b/apps/oneclient/frontend/src/routes/onboarding/account.tsx
new file mode 100644
index 00000000..60a283e7
--- /dev/null
+++ b/apps/oneclient/frontend/src/routes/onboarding/account.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/onboarding/account')({
+ component: RouteComponent,
+})
+
+function RouteComponent() {
+ return
Hello "/onboarding/account"!
+}
diff --git a/apps/oneclient/frontend/src/routes/onboarding/finished.tsx b/apps/oneclient/frontend/src/routes/onboarding/finished.tsx
new file mode 100644
index 00000000..63221c15
--- /dev/null
+++ b/apps/oneclient/frontend/src/routes/onboarding/finished.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/onboarding/finished')({
+ component: RouteComponent,
+})
+
+function RouteComponent() {
+ return
Hello "/onboarding/finished"!
+}
diff --git a/apps/oneclient/frontend/src/routes/onboarding/index.tsx b/apps/oneclient/frontend/src/routes/onboarding/index.tsx
new file mode 100644
index 00000000..75d55f23
--- /dev/null
+++ b/apps/oneclient/frontend/src/routes/onboarding/index.tsx
@@ -0,0 +1,15 @@
+import { createFileRoute } from '@tanstack/react-router';
+
+export const Route = createFileRoute('/onboarding/')({
+ component: RouteComponent,
+});
+
+function RouteComponent() {
+ return (
+ <>
+
+
OneClient
+
+ >
+ );
+}
diff --git a/apps/oneclient/frontend/src/routes/onboarding/language.tsx b/apps/oneclient/frontend/src/routes/onboarding/language.tsx
new file mode 100644
index 00000000..eaa4214b
--- /dev/null
+++ b/apps/oneclient/frontend/src/routes/onboarding/language.tsx
@@ -0,0 +1,13 @@
+import { createFileRoute } from '@tanstack/react-router';
+
+export const Route = createFileRoute('/onboarding/language')({
+ component: RouteComponent,
+});
+
+function RouteComponent() {
+ return (
+
+ Hello "/onboarding/language"!
+
+ );
+}
diff --git a/apps/oneclient/frontend/src/routes/onboarding/preferences/index.tsx b/apps/oneclient/frontend/src/routes/onboarding/preferences/index.tsx
new file mode 100644
index 00000000..39adfe28
--- /dev/null
+++ b/apps/oneclient/frontend/src/routes/onboarding/preferences/index.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/onboarding/preferences/')({
+ component: RouteComponent,
+})
+
+function RouteComponent() {
+ return
Hello "/onboarding/preferences/"!
+}
diff --git a/apps/oneclient/frontend/src/routes/onboarding/preferences/mods.tsx b/apps/oneclient/frontend/src/routes/onboarding/preferences/mods.tsx
new file mode 100644
index 00000000..48e17f3f
--- /dev/null
+++ b/apps/oneclient/frontend/src/routes/onboarding/preferences/mods.tsx
@@ -0,0 +1,9 @@
+import { createFileRoute } from '@tanstack/react-router'
+
+export const Route = createFileRoute('/onboarding/preferences/mods')({
+ component: RouteComponent,
+})
+
+function RouteComponent() {
+ return
Hello "/onboarding/preferences/mods"!
+}
diff --git a/apps/oneclient/frontend/src/routes/onboarding/preferences/versions.tsx b/apps/oneclient/frontend/src/routes/onboarding/preferences/versions.tsx
new file mode 100644
index 00000000..b02241c2
--- /dev/null
+++ b/apps/oneclient/frontend/src/routes/onboarding/preferences/versions.tsx
@@ -0,0 +1,88 @@
+import CavesAndCliffs from '@/assets/backgrounds/CavesAndCliffs.jpg';
+import { Button } from '@onelauncher/common/components';
+import { createFileRoute } from '@tanstack/react-router';
+import { DotsVerticalIcon, PlusIcon } from '@untitled-theme/icons-react';
+
+export const Route = createFileRoute('/onboarding/preferences/versions')({
+ component: RouteComponent,
+});
+
+// placeholder
+const versions = [
+ {
+ version: '1.8.9',
+ tags: ['PvP', 'Skyblock', 'Bedwars', 'UHC'],
+ },
+ {
+ version: '1.21.4',
+ tags: ['Nostalgia', 'Survival', 'UHC'],
+ },
+ {
+ version: '1.21.4',
+ tags: ['PvP', 'Minigames', 'Survival', 'UHC'],
+ },
+];
+
+function RouteComponent() {
+ return (
+
+
+
Starting Versions
+
+ Something something in corporate style fashion about picking your preferred gamemodes and versions and
+ optionally loader so that oneclient can pick something for them
+
+
+
+ {versions.map(version => (
+
+ ))}
+
+
+
+
+ );
+}
+
+interface VersionCardProps {
+ version: string;
+ tags: Array
;
+}
+
+export function VersionCard({ version, tags }: VersionCardProps) {
+ return (
+
+
+

+
+
+ {tags.map(tag => (
+
+ {tag}
+
+ ))}
+
+
+
+
+
+ {version}
+
+
+
+ );
+}
diff --git a/apps/oneclient/frontend/src/routes/onboarding/route.tsx b/apps/oneclient/frontend/src/routes/onboarding/route.tsx
new file mode 100644
index 00000000..b534dc2a
--- /dev/null
+++ b/apps/oneclient/frontend/src/routes/onboarding/route.tsx
@@ -0,0 +1,230 @@
+import type { PropsWithChildren } from 'react';
+import Logo from '@/assets/logos/oneclient2.svg';
+import { LoaderSuspense, NavbarButton } from '@/components';
+import { GameBackground } from '@/components/GameBackground';
+import { Stepper } from '@/components/Stepper';
+import useAppShellStore from '@/stores/appShellStore';
+import { Button } from '@onelauncher/common/components';
+import { createFileRoute, Link, Outlet } from '@tanstack/react-router';
+import { Window } from '@tauri-apps/api/window';
+import { MinusIcon, SquareIcon, XCloseIcon } from '@untitled-theme/icons-react';
+import { MouseParallax } from 'react-just-parallax';
+
+export const Route = createFileRoute('/onboarding')({
+ component: RouteComponent,
+ loader: ({ location }) => {
+ const currentStepIndex = LINEAR_ONBOARDING_STEPS.findIndex(
+ step => step.path === location.pathname,
+ );
+
+ const isFirstStep = currentStepIndex === 0;
+ const isLastStep = currentStepIndex === LINEAR_ONBOARDING_STEPS.length - 1;
+
+ return {
+ isFirstStep,
+ isLastStep,
+ previousPath:
+ currentStepIndex > 0
+ ? LINEAR_ONBOARDING_STEPS[currentStepIndex - 1]?.path
+ : undefined,
+ nextPath:
+ currentStepIndex < LINEAR_ONBOARDING_STEPS.length - 1
+ ? LINEAR_ONBOARDING_STEPS[currentStepIndex + 1]?.path
+ : undefined,
+ currentStepIndex,
+ };
+ },
+});
+
+export interface OnboardingStep {
+ path: string;
+ title: string;
+ subSteps?: Array;
+};
+
+const ONBOARDING_STEPS: Array = [
+ {
+ path: '/onboarding',
+ title: 'Welcome',
+ },
+ {
+ path: '/onboarding/language',
+ title: 'Set Language',
+ },
+ {
+ path: '/onboarding/account',
+ title: 'Account',
+ },
+ {
+ path: '/onboarding/preferences/',
+ title: 'Preferences',
+ subSteps: [
+ {
+ path: '/onboarding/preferences/versions',
+ title: 'Versions',
+ },
+ {
+ path: '/onboarding/preferences/mods',
+ title: 'Mods',
+ },
+ ],
+ },
+ {
+ path: '/onboarding/finished',
+ title: 'Finished',
+ },
+];
+
+function getLinearSteps(steps: Array): Array> {
+ return steps.flatMap(step => (step.subSteps ? step.subSteps : step));
+}
+
+const LINEAR_ONBOARDING_STEPS = getLinearSteps(ONBOARDING_STEPS);
+
+function RouteComponent() {
+ return (
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+function AppShell({
+ children,
+}: PropsWithChildren) {
+ const { isFirstStep } = Route.useLoaderData();
+
+ return (
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+ {children}
+
+
+
+ );
+}
+
+function BackgroundGradient() {
+ const background = useAppShellStore(state => state.background);
+
+ if (background === 'none')
+ return undefined;
+
+ return (
+
+ {/* Linear black gradient: left -> right */}
+ {/*
+
*/}
+
+ {/* Radial black gradient */}
+
+
+
+ {/* Linear black gradient: bottom -> 200 px up */}
+
+
+
+
+
+
+
+ );
+}
+
+export function OnboardingNavigation() {
+ const { isFirstStep, isLastStep, previousPath, nextPath } = Route.useLoaderData();
+
+ return (
+
+
+ {!isFirstStep && previousPath && (
+
+
+
+ )}
+
+
+ {nextPath && (
+
+
+
+ )}
+
+
+ );
+}
+
+export function Navbar() {
+ const onMinimize = () => Window.getCurrent().minimize();
+ const onMaximize = () => Window.getCurrent().toggleMaximize();
+ const onClose = () => Window.getCurrent().close();
+
+ return (
+
+ );
+}
diff --git a/apps/oneclient/frontend/src/styles/animations.css b/apps/oneclient/frontend/src/styles/animations.css
index 1fd64fb9..95bb2b4a 100644
--- a/apps/oneclient/frontend/src/styles/animations.css
+++ b/apps/oneclient/frontend/src/styles/animations.css
@@ -9,6 +9,15 @@
opacity: 0;
}
}
+
+ @keyframes custom-anim-zoom {
+ 0% {
+ transform: scale(0);
+ }
+ 100% {
+ transform: scale(1);
+ }
+ }
}
@utility animate-fade-scale {
@@ -16,3 +25,8 @@
opacity: 1;
animation: custom-anim-fade-scale var(--default-animation-duration, 1s) var(--default-animation-timing-function, cubic-bezier(0, 0, 0.2, 1)) var(--default-animation-delay, 0s) forwards;
}
+
+@utility animate-zoom {
+ transform: scale(0);
+ animation: custom-anim-zoom var(--default-animation-duration, 1s) var(--default-animation-timing-function, cubic-bezier(0, 0, 0.2, 1)) var(--default-animation-delay, 0s) forwards;
+}
diff --git a/apps/oneclient/frontend/src/utils/minecraft.ts b/apps/oneclient/frontend/src/utils/minecraft.ts
new file mode 100644
index 00000000..5fc6d7f7
--- /dev/null
+++ b/apps/oneclient/frontend/src/utils/minecraft.ts
@@ -0,0 +1,5 @@
+import SteveSkin from '@onelauncher/common/assets/skin/steve.png';
+
+export function getSkinUrl(skinUrl: string | undefined | null) {
+ return skinUrl || SteveSkin;
+}
diff --git a/apps/oneclient/frontend/tsconfig.json b/apps/oneclient/frontend/tsconfig.json
index 2d4316bf..bb407a80 100644
--- a/apps/oneclient/frontend/tsconfig.json
+++ b/apps/oneclient/frontend/tsconfig.json
@@ -25,5 +25,5 @@
"skipLibCheck": true,
"noUncheckedSideEffectImports": true
},
- "include": ["**/*.ts", "**/*.tsx", "vite.config.ts", "../../../packages/web_common/src/utils/error.ts"]
+ "include": ["**/*.ts", "**/*.tsx", "vite.config.ts", "../../../packages/web_common/src/utils/error.ts", "src/components/AccountAvatar.tsx"]
}
diff --git a/packages/core/src/api/game/launch.rs b/packages/core/src/api/game/launch.rs
index 4df851f8..75cc1bc6 100644
--- a/packages/core/src/api/game/launch.rs
+++ b/packages/core/src/api/game/launch.rs
@@ -118,7 +118,7 @@ pub async fn launch_minecraft(
arguments::java_arguments(
args.get(&interpulse::api::minecraft::ArgumentType::Jvm)
.map(Vec::as_slice),
- &dirs.natives_dir().join(&version.id),
+ &dirs.natives_dir().join(&version_name),
&dirs.libraries_dir(),
&arguments::classpaths(
&dirs.libraries_dir(),
diff --git a/packages/core/src/api/tauri/commands.rs b/packages/core/src/api/tauri/commands.rs
index 8d9bcd21..29a9b414 100644
--- a/packages/core/src/api/tauri/commands.rs
+++ b/packages/core/src/api/tauri/commands.rs
@@ -24,7 +24,7 @@ use onelauncher_entity::prelude::model::*;
#[taurpc::procedures(path = "core")]
pub trait TauriLauncherApi {
- // Clusters
+ // MARK: API: clusters
#[taurpc(alias = "getClusters")]
async fn get_clusters() -> LauncherResult>;
@@ -55,7 +55,7 @@ pub trait TauriLauncherApi {
#[taurpc(alias = "getLogByName")]
async fn get_log_by_name(id: ClusterId, name: String) -> LauncherResult