mirror of
https://github.com/Termix-SSH/Termix.git
synced 2026-10-28 06:05:24 +00:00
76 lines
2.6 KiB
TypeScript
76 lines
2.6 KiB
TypeScript
import { getUiPreferences } from "@/api/ui-preferences-api";
|
|
import {
|
|
getOnboardingPlugins,
|
|
type OnboardingPluginList,
|
|
} from "@/api/plugins-api";
|
|
import { loadPermissionChecker } from "@/hooks/use-permissions";
|
|
import { isElectron } from "@/lib/electron";
|
|
import { isEmbeddedAuthFrame } from "@/lib/embedded-frame";
|
|
import type { UiPreferences } from "@/types/ui-preferences";
|
|
import {
|
|
computeFlow,
|
|
needsFullFlow,
|
|
ONBOARDING_ADMIN_PERMISSION,
|
|
} from "./onboarding-flow";
|
|
import type { OnboardingCtx, OnboardingMode } from "./onboarding-registry";
|
|
import { canEnrollSecondFactor, currentStepDefs } from "./use-onboarding-steps";
|
|
|
|
export interface StartupOnboarding {
|
|
preferences: UiPreferences | null;
|
|
/** Null when there is nothing to show. */
|
|
mode: Exclude<OnboardingMode, "rerun"> | null;
|
|
plugins: OnboardingPluginList | null;
|
|
}
|
|
|
|
/**
|
|
* Decides, after sign in and once plugins have loaded, whether the app opens
|
|
* on onboarding: the full run for a new user, or just the steps someone has
|
|
* not seen yet. Never inside the mobile app or a desktop's link window,
|
|
* which only borrow this page to sign in.
|
|
*/
|
|
export async function resolveStartupOnboarding(): Promise<StartupOnboarding> {
|
|
const none: StartupOnboarding = {
|
|
preferences: null,
|
|
mode: null,
|
|
plugins: null,
|
|
};
|
|
if (isEmbeddedAuthFrame()) return none;
|
|
if (new URLSearchParams(window.location.search).has("view")) return none;
|
|
|
|
let preferences: UiPreferences;
|
|
try {
|
|
preferences = await getUiPreferences();
|
|
} catch {
|
|
return none;
|
|
}
|
|
|
|
const has = await loadPermissionChecker();
|
|
const isAdmin = has(ONBOARDING_ADMIN_PERMISSION);
|
|
const plugins = isAdmin
|
|
? await getOnboardingPlugins().catch(() => null)
|
|
: null;
|
|
|
|
const result: StartupOnboarding = { preferences, mode: null, plugins };
|
|
const { onboarding } = preferences;
|
|
|
|
if (needsFullFlow(onboarding)) return { ...result, mode: "full" };
|
|
|
|
const ctx: OnboardingCtx = {
|
|
mode: "partial",
|
|
isAdmin,
|
|
isDesktop: isElectron(),
|
|
has,
|
|
pluginSetupPending: !!plugins?.pending,
|
|
pluginsManagedElsewhere: !!plugins?.managedByLinkedServer,
|
|
canEnrollSecondFactor: canEnrollSecondFactor(),
|
|
};
|
|
const steps = currentStepDefs(has);
|
|
// Someone carried over from the old onboarding has their plugin steps
|
|
// marked seen by the shell first, so only core steps count for them here.
|
|
const candidates = onboarding.baselinePending
|
|
? steps.filter((step) => !step.pluginId)
|
|
: steps;
|
|
const pending = computeFlow(candidates, onboarding.seen, ctx);
|
|
return { ...result, mode: pending.length > 0 ? "partial" : null };
|
|
}
|