fix: OneClient Onboarding Stepper (#409)

This commit is contained in:
Jacob 2025-11-15 07:00:44 +00:00 • committed by GitHub
parent 6c97a914c2
commit a4d07d3fa3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 41 additions and 82 deletions

View file

@ -255,8 +255,13 @@ export type VersionType =
*/
"old_beta"
const ARGS_MAP = { 'oneclient':'{"getClustersGroupedByMajor":[],"openDevTools":[],"getBundlesFor":["cluster_id"]}', 'core':'{"downloadPackage":["provider","package_id","version_id","cluster_id","skip_compatibility"],"getRunningProcesses":[],"getClusters":[],"updateClusterById":["id","request"],"getGameVersions":[],"getLoadersForVersion":["mc_version"],"getUsers":[],"setDefaultUser":["uuid"],"changeSkin":["access_token","skin_url","skin_variant"],"getWorlds":["id"],"fetchLoggedInProfile":["access_token"],"createCluster":["options"],"getScreenshots":["id"],"searchPackages":["provider","query"],"installModpack":["modpack","cluster_id"],"changeCape":["access_token","cape_uuid"],"getLogs":["id"],"readSettings":[],"getRunningProcessesByClusterId":["cluster_id"],"getUsersFromAuthor":["provider","author"],"createSettingsProfile":["name"],"getPackageBody":["provider","body"],"convertUsernameUUID":["username_uuid"],"getClusterById":["id"],"getUser":["uuid"],"launchCluster":["id","uuid"],"getLogByName":["id","name"],"openMsaLogin":[],"getPackage":["provider","slug"],"getDefaultUser":["fallback"],"updateClusterProfile":["name","profile"],"open":["input"],"getGlobalProfile":[],"isClusterRunning":["cluster_id"],"removeCluster":["id"],"killProcess":["pid"],"writeSettings":["setting"],"removeUser":["uuid"],"getPackageVersions":["provider","slug","mc_version","loader","offset","limit"],"getMultiplePackages":["provider","slugs"],"fetchMinecraftProfile":["uuid"],"uploadSkinBytes":["access_token","skin_data","image_format","skin_variant"],"removeCape":["access_token"],"getProfileOrDefault":["name"]}', 'events':'{"message":["event"],"ingress":["event"],"process":["event"]}', 'folders':'{"fromCluster":["folder_name"],"openCluster":["folder_name"]}' }
export type Router = { 'core': { getClusters: () => Promise<ClusterModel[]>,
const ARGS_MAP = { 'oneclient':'{"getBundlesFor":["cluster_id"],"openDevTools":[],"getClustersGroupedByMajor":[]}', 'events':'{"ingress":["event"],"process":["event"],"message":["event"]}', 'core':'{"removeUser":["uuid"],"updateClusterProfile":["name","profile"],"readSettings":[],"getRunningProcesses":[],"isClusterRunning":["cluster_id"],"openMsaLogin":[],"writeSettings":["setting"],"removeCluster":["id"],"getPackageBody":["provider","body"],"getClusterById":["id"],"getLogs":["id"],"getLoadersForVersion":["mc_version"],"setDefaultUser":["uuid"],"fetchMinecraftProfile":["uuid"],"getScreenshots":["id"],"getGameVersions":[],"searchPackages":["provider","query"],"uploadSkinBytes":["access_token","skin_data","image_format","skin_variant"],"changeSkin":["access_token","skin_url","skin_variant"],"removeCape":["access_token"],"convertUsernameUUID":["username_uuid"],"getProfileOrDefault":["name"],"updateClusterById":["id","request"],"getWorlds":["id"],"getGlobalProfile":[],"getUsersFromAuthor":["provider","author"],"changeCape":["access_token","cape_uuid"],"createCluster":["options"],"getClusters":[],"launchCluster":["id","uuid"],"getMultiplePackages":["provider","slugs"],"getPackage":["provider","slug"],"getUsers":[],"installModpack":["modpack","cluster_id"],"createSettingsProfile":["name"],"getLogByName":["id","name"],"getUser":["uuid"],"downloadPackage":["provider","package_id","version_id","cluster_id","skip_compatibility"],"fetchLoggedInProfile":["access_token"],"getDefaultUser":["fallback"],"open":["input"],"killProcess":["pid"],"getRunningProcessesByClusterId":["cluster_id"],"getPackageVersions":["provider","slug","mc_version","loader","offset","limit"]}', 'folders':'{"fromCluster":["folder_name"],"openCluster":["folder_name"]}' }
export type Router = { 'events': { ingress: (event: IngressPayload) => Promise<void>,
message: (event: MessagePayload) => Promise<void>,
process: (event: ProcessPayload) => Promise<void> },
'folders': { fromCluster: (folderName: string) => Promise<string>,
openCluster: (folderName: string) => Promise<null> },
'core': { getClusters: () => Promise<ClusterModel[]>,
getClusterById: (id: number) => Promise<ClusterModel | null>,
removeCluster: (id: number) => Promise<null>,
createCluster: (options: CreateCluster) => Promise<ClusterModel>,
@ -302,12 +307,7 @@ convertUsernameUUID: (usernameUuid: string) => Promise<MowojangProfile>,
open: (input: string) => Promise<null> },
'oneclient': { openDevTools: () => Promise<void>,
getClustersGroupedByMajor: () => Promise<Partial<{ [key in number]: ClusterModel[] }>>,
getBundlesFor: (clusterId: number) => Promise<ModpackArchive[]> },
'folders': { fromCluster: (folderName: string) => Promise<string>,
openCluster: (folderName: string) => Promise<null> },
'events': { ingress: (event: IngressPayload) => Promise<void>,
message: (event: MessagePayload) => Promise<void>,
process: (event: ProcessPayload) => Promise<void> } };
getBundlesFor: (clusterId: number) => Promise<ModpackArchive[]> } };
export type { InferCommandOutput }

View file

@ -1,75 +1,24 @@
import type { OnboardingStep } from '@/routes/onboarding/route';
import { twMerge } from 'tailwind-merge';
interface VerticalStepperProps {
steps: Array<OnboardingStep>;
currentLinearIndex: number;
linearSteps: Array<Omit<OnboardingStep, 'subSteps'>>;
currentStepIndex: number;
};
export function Stepper({ steps, linearSteps, currentLinearIndex }: VerticalStepperProps) {
// const matchRoute = useMatchRoute();
// const currentLinearIndex = linearSteps.findIndex(step =>
// matchRoute({ to: step.path }));
const progressHeight = currentLinearIndex >= 0 ? `${Math.min((currentLinearIndex + 0.5) / (linearSteps.length - 1), 1) * 100}%` : '0%';
// const nextStep = () => {
// if (currentStep < steps.length - 1)
// setCurrentStep(currentStep + 1);
// };
// const prevStep = () => {
// if (currentStep > 0)
// setCurrentStep(currentStep - 1);
// };
// const goToStep = (stepIndex: number) => {
// setCurrentStep(stepIndex);
// };
export function Stepper({ steps, currentStepIndex }: VerticalStepperProps) {
return (
<div>
<div className="max-w-md mx-auto">
<div className="relative">
<div className="absolute left-4 top-0 w-0.5 h-full bg-gray-600"></div>
<div
className="absolute left-4 top-0 w-0.5 bg-brand transition-all duration-500 ease-in-out"
style={{
height: `${progressHeight}`,
}}
>
</div>
<ul className="relative space-y-4">
{steps.map((step, index) => (
<li
className="relative flex items-center cursor-pointer group"
key={index}
// onClick={() => goToStep(index)}
>
<div className="ml-8">
<span
className="
transition-all duration-300 font-medium
text-gray-400
text-base
data-active:text-white
data-active:text-lg
data-complete:text-base
"
data-active={index === currentLinearIndex || null}
data-complete={index < currentLinearIndex || null}
>
{step.title}
</span>
</div>
</li>
))}
</ul>
<div className="max-w-md mx-auto">
{steps.map((step, index) => (
<div
className={twMerge('transition-all duration-300 relative flex items-center cursor-pointer py-2 pl-4 border-l-3 border-gray-600 font-medium text-gray-400 text-base data-active:border-brand data-active:text-white data-active:text-lg data-complete:border-brand', index === 0 ? 'pt-0' : '', index === steps.length - 1 ? 'pb-0' : '')}
data-active={index === currentStepIndex || null}
data-complete={index < currentStepIndex || null}
key={index}
>
<span>{step.title}</span>
</div>
</div>
))}
</div>
);
}

View file

@ -15,24 +15,34 @@ import { MouseParallax } from 'react-just-parallax';
export const Route = createFileRoute('/onboarding')({
component: RouteComponent,
loader: ({ location }) => {
const currentStepIndex = LINEAR_ONBOARDING_STEPS.findIndex(
const currentStepIndex = ONBOARDING_STEPS.findIndex((step) => {
if (step.path === location.pathname)
return true;
if (step.subSteps)
return step.subSteps.some(sub => sub.path === location.pathname);
return false;
});
const currentLinearStepIndex = LINEAR_ONBOARDING_STEPS.findIndex(
step => step.path === location.pathname,
);
const isFirstStep = currentStepIndex === 0;
const isLastStep = currentStepIndex === LINEAR_ONBOARDING_STEPS.length - 1;
const isFirstStep = currentLinearStepIndex === 0;
const isLastStep = currentLinearStepIndex === LINEAR_ONBOARDING_STEPS.length - 1;
return {
isFirstStep,
isLastStep,
previousPath:
currentStepIndex > 0
? LINEAR_ONBOARDING_STEPS[currentStepIndex - 1]?.path
currentLinearStepIndex > 0
? LINEAR_ONBOARDING_STEPS[currentLinearStepIndex - 1]?.path
: undefined,
nextPath:
currentStepIndex < LINEAR_ONBOARDING_STEPS.length - 1
? LINEAR_ONBOARDING_STEPS[currentStepIndex + 1]?.path
currentLinearStepIndex < LINEAR_ONBOARDING_STEPS.length - 1
? LINEAR_ONBOARDING_STEPS[currentLinearStepIndex + 1]?.path
: undefined,
currentLinearStepIndex,
currentStepIndex,
};
},
@ -138,7 +148,7 @@ function AppShell({
</div>
<nav className="flex-1 p-4">
<Stepper currentLinearIndex={currentStepIndex} linearSteps={LINEAR_ONBOARDING_STEPS} steps={ONBOARDING_STEPS} />
<Stepper currentStepIndex={currentStepIndex} steps={ONBOARDING_STEPS} />
</nav>
<div className="p-4 text-xs text-fg-secondary">
@ -198,9 +208,9 @@ function BackgroundGradient() {
}
export function OnboardingNavigation() {
const { isFirstStep, previousPath, nextPath, currentStepIndex } = Route.useLoaderData();
const { isFirstStep, previousPath, nextPath, currentLinearStepIndex } = Route.useLoaderData();
const { data: currentAccount } = useCommandSuspense(['getDefaultUser'], () => bindings.core.getDefaultUser(true));
const forceLoginDisable = currentStepIndex === 2 && currentAccount === null;
const forceLoginDisable = currentLinearStepIndex === 2 && currentAccount === null;
return (
<div className="absolute bottom-2 right-2 flex flex-row gap-2">