GUI - Tracker assignment options (#1009)

Co-authored-by: Erimel <marioluigivideo@gmail.com>
Co-authored-by: loucass003 <loucass003@gmail.com>
This commit is contained in:
Ondrej Hruska
2024-06-17 08:45:06 -07:00
committed by GitHub
parent cfd9223390
commit d9da5544bb
8 changed files with 333 additions and 168 deletions

View File

@@ -688,6 +688,24 @@ onboarding-assign_trackers-assigned = { $assigned } of { $trackers ->
onboarding-assign_trackers-advanced = Show advanced assign locations
onboarding-assign_trackers-next = I assigned all the trackers
onboarding-assign_trackers-mirror_view = Mirror view
onboarding-assign_trackers-option-amount = { $trackersCount ->
[one] x{ $trackersCount }
*[other] x{ $trackersCount }
}
onboarding-assign_trackers-option-label = { $mode ->
[lower-body] Lower-Body Set
[core] Core Set
[enhanced-core] Enhanced Core Set
[full-body] Full-Body Set
*[all] All Trackers
}
onboarding-assign_trackers-option-description = { $mode ->
[lower-body] Minimum for VR full-body tracking
[core] + Enhanced spine tracking
[enhanced-core] + Foot rotation
[full-body] + Elbow tracking
*[all] All available tracker assignments
}
## Tracker assignment warnings
# Note for devs, number is used for representing boolean states per bit.

View File

@@ -1,6 +1,7 @@
import classNames from 'classnames';
import { Control, Controller } from 'react-hook-form';
import { Typography } from './Typography';
import { ReactNode } from 'react';
export function Radio({
control,
@@ -8,15 +9,17 @@ export function Radio({
label,
value,
description,
children,
// input props
disabled,
...props
}: {
control: Control<any>;
name: string;
label: string;
label?: string;
value: string;
description?: string | null;
children?: ReactNode;
} & React.HTMLProps<HTMLInputElement>) {
return (
<Controller
@@ -27,7 +30,7 @@ export function Radio({
className={classNames('w-full p-3 rounded-md flex gap-3 border-2', {
'border-accent-background-30': value == checked,
'border-transparent': value != checked,
'bg-background-60 cursor-pointer': !disabled,
'bg-background-60 cursor-pointer hover:bg-background-50': !disabled,
'bg-background-80 cursor-not-allowed': disabled,
})}
>
@@ -46,7 +49,7 @@ export function Radio({
{...props}
/>
<div className="flex flex-col gap-2">
<Typography bold>{label}</Typography>
{children ? children : <Typography bold>{label}</Typography>}
{description && (
<Typography variant="standard" color="secondary">
{description}

View File

@@ -1,19 +1,29 @@
import { useMemo } from 'react';
import { useCallback, useMemo } from 'react';
import { BodyPart } from 'solarxr-protocol';
import { FlatDeviceTracker } from '@/hooks/app';
import { AssignMode } from '@/hooks/config';
import { useTrackers } from '@/hooks/tracker';
import { BodyInteractions } from '@/components/commons/BodyInteractions';
import { TrackerPartCard } from '@/components/tracker/TrackerPartCard';
import { BodyPartError } from './pages/trackers-assign/TrackerAssignment';
import { SIDES } from '@/components/commons/PersonFrontIcon';
export const ARMS_PARTS = new Set([
BodyPart.LEFT_UPPER_ARM,
BodyPart.RIGHT_UPPER_ARM,
BodyPart.LEFT_LOWER_ARM,
BodyPart.RIGHT_LOWER_ARM,
]);
export const LEGS_PARTS = new Set([
BodyPart.LEFT_UPPER_LEG,
BodyPart.RIGHT_UPPER_LEG,
BodyPart.LEFT_LOWER_LEG,
BodyPart.RIGHT_LOWER_LEG,
]);
export const LOWER_BODY = new Set([
BodyPart.LEFT_FOOT,
BodyPart.RIGHT_FOOT,
BodyPart.LEFT_LOWER_LEG,
BodyPart.RIGHT_LOWER_LEG,
BodyPart.LEFT_UPPER_LEG,
BodyPart.RIGHT_UPPER_LEG,
...LEGS_PARTS,
]);
export const SPINE_PARTS = [
BodyPart.UPPER_CHEST,
@@ -44,8 +54,47 @@ export const ASSIGNMENT_RULES: Partial<
// Also don't warn if no legs.
};
export const ASSIGNMENT_MODES: Record<AssignMode, BodyPart[]> = {
// x5
[AssignMode.LowerBody]: [BodyPart.CHEST, ...LEGS_PARTS],
// x6 (5 + 1)
[AssignMode.Core]: [BodyPart.CHEST, BodyPart.HIP, ...LEGS_PARTS],
// x8 (5 + 3)
[AssignMode.EnhancedCore]: [
BodyPart.CHEST,
BodyPart.HIP,
...LEGS_PARTS,
BodyPart.LEFT_FOOT,
BodyPart.RIGHT_FOOT,
],
// x10 (7 + 3)
[AssignMode.FullBody]: [
BodyPart.CHEST,
BodyPart.HIP,
BodyPart.LEFT_UPPER_ARM,
BodyPart.RIGHT_UPPER_ARM,
...LEGS_PARTS,
BodyPart.LEFT_FOOT,
BodyPart.RIGHT_FOOT,
],
// special case with all body parts
[AssignMode.All]: [
BodyPart.HEAD,
BodyPart.NECK,
BodyPart.LEFT_SHOULDER,
BodyPart.RIGHT_SHOULDER,
BodyPart.LEFT_HAND,
BodyPart.RIGHT_HAND,
BodyPart.LEFT_FOOT,
BodyPart.RIGHT_FOOT,
...SPINE_PARTS,
...ARMS_PARTS,
...LEGS_PARTS,
],
};
export function BodyAssignment({
advanced,
assignMode,
mirror,
onRoleSelected,
rolesWithErrors = {},
@@ -53,7 +102,7 @@ export function BodyAssignment({
onlyAssigned = false,
width,
}: {
advanced: boolean;
assignMode: AssignMode;
mirror: boolean;
onlyAssigned?: boolean;
rolesWithErrors?: Partial<Record<BodyPart, BodyPartError>>;
@@ -94,6 +143,13 @@ export function BodyAssignment({
const left = +!mirror;
const right = +mirror;
const hasBodyPart = useCallback(
(part: BodyPart) =>
assignMode === AssignMode.All ||
ASSIGNMENT_MODES[assignMode].indexOf(part) > -1,
[assignMode]
);
return (
<>
<BodyInteractions
@@ -105,7 +161,7 @@ export function BodyAssignment({
leftControls={
<div className="flex flex-col justify-between h-full text-right">
<div className="flex flex-col gap-2">
{advanced && (
{hasBodyPart(BodyPart.HEAD) && (
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[BodyPart.HEAD]?.label}
@@ -115,7 +171,8 @@ export function BodyAssignment({
direction="right"
/>
)}
{advanced && (
{hasBodyPart(BodyPart.NECK) && (
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[BodyPart.NECK]?.label}
@@ -126,9 +183,8 @@ export function BodyAssignment({
/>
)}
</div>
<div className="flex flex-col gap-2">
{advanced && (
{hasBodyPart(SIDES[left].shoulder) && (
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[SIDES[left].shoulder]?.label}
@@ -138,26 +194,31 @@ export function BodyAssignment({
direction="right"
/>
)}
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[SIDES[left].upperArm]?.label}
td={trackerPartGrouped[SIDES[left].upperArm]}
role={SIDES[left].upperArm}
onClick={() => onRoleSelected(SIDES[left].upperArm)}
direction="right"
/>
{hasBodyPart(SIDES[left].upperArm) && (
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[SIDES[left].upperArm]?.label}
td={trackerPartGrouped[SIDES[left].upperArm]}
role={SIDES[left].upperArm}
onClick={() => onRoleSelected(SIDES[left].upperArm)}
direction="right"
/>
)}
</div>
<div className="flex flex-col gap-2">
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[SIDES[left].lowerArm]?.label}
td={trackerPartGrouped[SIDES[left].lowerArm]}
role={SIDES[left].lowerArm}
onClick={() => onRoleSelected(SIDES[left].lowerArm)}
direction="right"
/>
{hasBodyPart(SIDES[left].lowerArm) && (
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[SIDES[left].lowerArm]?.label}
td={trackerPartGrouped[SIDES[left].lowerArm]}
role={SIDES[left].lowerArm}
onClick={() => onRoleSelected(SIDES[left].lowerArm)}
direction="right"
/>
)}
{advanced && (
{hasBodyPart(SIDES[left].hand) && (
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[SIDES[left].hand]?.label}
@@ -169,37 +230,44 @@ export function BodyAssignment({
)}
</div>
<div className="flex flex-col gap-2">
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[SIDES[left].upperLeg]?.label}
td={trackerPartGrouped[SIDES[left].upperLeg]}
role={SIDES[left].upperLeg}
onClick={() => onRoleSelected(SIDES[left].upperLeg)}
direction="right"
/>
{hasBodyPart(SIDES[left].upperLeg) && (
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[SIDES[left].upperLeg]?.label}
td={trackerPartGrouped[SIDES[left].upperLeg]}
role={SIDES[left].upperLeg}
onClick={() => onRoleSelected(SIDES[left].upperLeg)}
direction="right"
/>
)}
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[SIDES[left].lowerLeg]?.label}
td={trackerPartGrouped[SIDES[left].lowerLeg]}
role={SIDES[left].lowerLeg}
onClick={() => onRoleSelected(SIDES[left].lowerLeg)}
direction="right"
/>
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[SIDES[left].foot]?.label}
td={trackerPartGrouped[SIDES[left].foot]}
role={SIDES[left].foot}
onClick={() => onRoleSelected(SIDES[left].foot)}
direction="right"
/>
{hasBodyPart(SIDES[left].lowerLeg) && (
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[SIDES[left].lowerLeg]?.label}
td={trackerPartGrouped[SIDES[left].lowerLeg]}
role={SIDES[left].lowerLeg}
onClick={() => onRoleSelected(SIDES[left].lowerLeg)}
direction="right"
/>
)}
{hasBodyPart(SIDES[left].foot) && (
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[SIDES[left].foot]?.label}
td={trackerPartGrouped[SIDES[left].foot]}
role={SIDES[left].foot}
onClick={() => onRoleSelected(SIDES[left].foot)}
direction="right"
/>
)}
</div>
</div>
}
rightControls={
<div className="flex flex-col justify-between h-full">
{advanced && (
{hasBodyPart(BodyPart.UPPER_CHEST) && (
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[BodyPart.UPPER_CHEST]?.label}
@@ -210,17 +278,19 @@ export function BodyAssignment({
/>
)}
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[BodyPart.CHEST]?.label}
td={trackerPartGrouped[BodyPart.CHEST]}
role={BodyPart.CHEST}
onClick={() => onRoleSelected(BodyPart.CHEST)}
direction="left"
/>
{hasBodyPart(BodyPart.CHEST) && (
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[BodyPart.CHEST]?.label}
td={trackerPartGrouped[BodyPart.CHEST]}
role={BodyPart.CHEST}
onClick={() => onRoleSelected(BodyPart.CHEST)}
direction="left"
/>
)}
<div className="flex flex-col gap-2">
{advanced && (
{hasBodyPart(SIDES[right].shoulder) && (
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[SIDES[right].shoulder]?.label}
@@ -231,45 +301,53 @@ export function BodyAssignment({
/>
)}
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[SIDES[right].upperArm]?.label}
td={trackerPartGrouped[SIDES[right].upperArm]}
role={SIDES[right].upperArm}
onClick={() => onRoleSelected(SIDES[right].upperArm)}
direction="left"
/>
{hasBodyPart(SIDES[right].upperArm) && (
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[SIDES[right].upperArm]?.label}
td={trackerPartGrouped[SIDES[right].upperArm]}
role={SIDES[right].upperArm}
onClick={() => onRoleSelected(SIDES[right].upperArm)}
direction="left"
/>
)}
</div>
<div className="flex flex-col gap-2">
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[BodyPart.WAIST]?.label}
td={trackerPartGrouped[BodyPart.WAIST]}
onClick={() => onRoleSelected(BodyPart.WAIST)}
role={BodyPart.WAIST}
direction="left"
/>
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[BodyPart.HIP]?.label}
td={trackerPartGrouped[BodyPart.HIP]}
onClick={() => onRoleSelected(BodyPart.HIP)}
role={BodyPart.HIP}
direction="left"
/>
{hasBodyPart(BodyPart.WAIST) && (
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[BodyPart.WAIST]?.label}
td={trackerPartGrouped[BodyPart.WAIST]}
onClick={() => onRoleSelected(BodyPart.WAIST)}
role={BodyPart.WAIST}
direction="left"
/>
)}
{hasBodyPart(BodyPart.HIP) && (
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[BodyPart.HIP]?.label}
td={trackerPartGrouped[BodyPart.HIP]}
onClick={() => onRoleSelected(BodyPart.HIP)}
role={BodyPart.HIP}
direction="left"
/>
)}
</div>
<div className="flex flex-col gap-2">
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[SIDES[right].lowerArm]?.label}
td={trackerPartGrouped[SIDES[right].lowerArm]}
role={SIDES[right].lowerArm}
onClick={() => onRoleSelected(SIDES[right].lowerArm)}
direction="left"
/>
{advanced && (
{hasBodyPart(SIDES[right].lowerArm) && (
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[SIDES[right].lowerArm]?.label}
td={trackerPartGrouped[SIDES[right].lowerArm]}
role={SIDES[right].lowerArm}
onClick={() => onRoleSelected(SIDES[right].lowerArm)}
direction="left"
/>
)}
{hasBodyPart(SIDES[right].hand) && (
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[SIDES[right].hand]?.label}
@@ -280,33 +358,39 @@ export function BodyAssignment({
/>
)}
</div>
<div className="flex flex-col gap-2">
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[SIDES[right].upperLeg]?.label}
td={trackerPartGrouped[SIDES[right].upperLeg]}
role={SIDES[right].upperLeg}
onClick={() => onRoleSelected(SIDES[right].upperLeg)}
direction="left"
/>
{hasBodyPart(SIDES[right].upperLeg) && (
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[SIDES[right].upperLeg]?.label}
td={trackerPartGrouped[SIDES[right].upperLeg]}
role={SIDES[right].upperLeg}
onClick={() => onRoleSelected(SIDES[right].upperLeg)}
direction="left"
/>
)}
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[SIDES[right].lowerLeg]?.label}
td={trackerPartGrouped[SIDES[right].lowerLeg]}
role={SIDES[right].lowerLeg}
onClick={() => onRoleSelected(SIDES[right].lowerLeg)}
direction="left"
/>
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[SIDES[right].foot]?.label}
td={trackerPartGrouped[SIDES[right].foot]}
role={SIDES[right].foot}
onClick={() => onRoleSelected(SIDES[right].foot)}
direction="left"
/>
{hasBodyPart(SIDES[right].lowerLeg) && (
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[SIDES[right].lowerLeg]?.label}
td={trackerPartGrouped[SIDES[right].lowerLeg]}
role={SIDES[right].lowerLeg}
onClick={() => onRoleSelected(SIDES[right].lowerLeg)}
direction="left"
/>
)}
{hasBodyPart(SIDES[right].foot) && (
<TrackerPartCard
onlyAssigned={onlyAssigned}
roleError={rolesWithErrors[SIDES[right].foot]?.label}
td={trackerPartGrouped[SIDES[right].foot]}
role={SIDES[right].foot}
onClick={() => onRoleSelected(SIDES[right].foot)}
direction="left"
/>
)}
</div>
</div>
}

View File

@@ -38,7 +38,9 @@ export function OnboardingLayout({ children }: { children: ReactNode }) {
</>
) : (
<MainLayoutRoute widgets={false} isMobile={isMobile}>
<div className="flex-grow xs:pt-10 mobile:pt-2">{children}</div>
<div className="flex-grow xs:pt-10 mobile:pt-2 overflow-y-auto">
{children}
</div>
</MainLayoutRoute>
);
}

View File

@@ -13,7 +13,7 @@ import { MountingSelectionMenu } from './MountingSelectionMenu';
import { useLocalization } from '@fluent/react';
import { useBreakpoint } from '@/hooks/breakpoint';
import { Quaternion } from 'three';
import { defaultConfig, useConfig } from '@/hooks/config';
import { AssignMode, defaultConfig, useConfig } from '@/hooks/config';
export function ManualMountingPage() {
const { isMobile } = useBreakpoint('mobile');
@@ -104,7 +104,7 @@ export function ManualMountingPage() {
width={isMobile ? 160 : undefined}
mirror={config?.mirrorView ?? defaultConfig.mirrorView}
onlyAssigned={true}
advanced={true}
assignMode={AssignMode.All}
onRoleSelected={setSelectRole}
></BodyAssignment>
</div>

View File

@@ -24,15 +24,17 @@ import { CheckBox } from '@/components/commons/Checkbox';
import { TipBox } from '@/components/commons/TipBox';
import { Typography } from '@/components/commons/Typography';
import {
ASSIGNMENT_MODES,
ASSIGNMENT_RULES,
BodyAssignment,
LOWER_BODY,
} from '@/components/onboarding/BodyAssignment';
import { NeckWarningModal } from '@/components/onboarding/NeckWarningModal';
import { TrackerSelectionMenu } from './TrackerSelectionMenu';
import { useConfig } from '@/hooks/config';
import { AssignMode, defaultConfig, useConfig } from '@/hooks/config';
import { playTapSetupSound } from '@/sounds/sounds';
import { useBreakpoint } from '@/hooks/breakpoint';
import { Radio } from '@/components/commons/Radio';
export type BodyPartError = {
label: string | undefined;
@@ -46,27 +48,54 @@ interface FlatDeviceTrackerDummy {
};
}
// Ordered collection of assign modes with the number of IMU trackers
const ASSIGN_MODE_OPTIONS = [
AssignMode.LowerBody,
AssignMode.Core,
AssignMode.EnhancedCore,
AssignMode.FullBody,
AssignMode.All,
].reduce(
(options, mode) => ({ ...options, [mode]: ASSIGNMENT_MODES[mode].length }),
{} as Record<AssignMode, number>
);
export function TrackersAssignPage() {
const { isMobile } = useBreakpoint('mobile');
const { l10n } = useLocalization();
const { config, setConfig } = useConfig();
const { useAssignedTrackers, trackers } = useTrackers();
const { useAssignedTrackers, useConnectedIMUTrackers, trackers } =
useTrackers();
const { applyProgress, state } = useOnboarding();
const { sendRPCPacket, useRPCPacket } = useWebsocketAPI();
const defaultValues = {
advanced: config?.advancedAssign ?? false,
mirrorView: config?.mirrorView ?? true,
assignMode: config?.assignMode ?? defaultConfig.assignMode,
mirrorView: config?.mirrorView ?? defaultConfig.mirrorView,
};
const { control, watch } = useForm<{
advanced: boolean;
const { control, watch, setValue } = useForm<{
assignMode: AssignMode;
mirrorView: boolean;
}>({ defaultValues });
const { advanced, mirrorView } = watch();
const { assignMode, mirrorView } = watch();
const [selectedRole, setSelectRole] = useState<BodyPart>(BodyPart.NONE);
const assignedTrackers = useAssignedTrackers();
useEffect(() => {
setConfig({ advancedAssign: advanced, mirrorView });
}, [advanced, mirrorView]);
setConfig({ assignMode, mirrorView });
}, [assignMode, mirrorView]);
const connectedIMUTrackers = useConnectedIMUTrackers().length;
useEffect(() => {
if (connectedIMUTrackers <= ASSIGN_MODE_OPTIONS[assignMode]) return;
const selectedAssignMode =
(Object.entries(ASSIGN_MODE_OPTIONS).find(
([_, count]) => count >= connectedIMUTrackers
)?.[0] as AssignMode) ?? AssignMode.All;
if (assignMode !== selectedAssignMode) {
setValue('assignMode', selectedAssignMode);
}
}, [connectedIMUTrackers, assignMode]);
const [tapDetectionSettings, setTapDetectionSettings] = useState<Omit<
TapDetectionSettingsT,
@@ -290,13 +319,54 @@ export function TrackersAssignPage() {
</Typography>
</div>
<TipBox>{l10n.getString('tips-find_tracker')}</TipBox>
<div>
<CheckBox
control={control}
label={l10n.getString('onboarding-assign_trackers-advanced')}
name="advanced"
variant="toggle"
></CheckBox>
{!!firstError && (
<div className="bg-status-warning text-background-60 px-3 py-2 text-justify rounded-md">
<div className="flex flex-col gap-1 whitespace-normal">
<span>{firstError.label}</span>
</div>
</div>
)}
<div className="flex flex-col md:gap-4 sm:gap-2 mobile:gap-4">
{Object.entries(ASSIGN_MODE_OPTIONS).map(
([mode, trackersCount]) => (
<Radio
key={mode}
name="assignMode"
control={control}
value={mode}
disabled={
connectedIMUTrackers > trackersCount &&
mode !== AssignMode.All
}
className="hidden"
>
<div className="flex flex-row md:gap-4 sm:gap-2 mobile:gap-2">
<div style={{ width: '2.5rem', textAlign: 'right' }}>
<Typography variant="mobile-title">
{l10n.getString(
'onboarding-assign_trackers-option-amount',
{ trackersCount }
)}
</Typography>
</div>
<div className="flex flex-col">
<Typography>
{l10n.getString(
'onboarding-assign_trackers-option-label',
{ mode }
)}
</Typography>
<Typography variant="standard" color="secondary">
{l10n.getString(
'onboarding-assign_trackers-option-description',
{ mode }
)}
</Typography>
</div>
</div>
</Radio>
)
)}
<CheckBox
control={control}
label={l10n.getString(
@@ -306,13 +376,6 @@ export function TrackersAssignPage() {
variant="toggle"
></CheckBox>
</div>
{!!firstError && (
<div className="bg-status-warning text-background-60 px-3 py-2 text-justify rounded-md">
<div className="flex flex-col gap-1 whitespace-normal">
<span>{firstError.label}</span>
</div>
</div>
)}
<div className="flex flex-row">
{!state.alonePage && (
<>
@@ -342,7 +405,7 @@ export function TrackersAssignPage() {
onlyAssigned={false}
highlightedRoles={firstError?.affectedRoles || []}
rolesWithErrors={rolesWithErrors}
advanced={advanced ?? defaultValues.advanced}
assignMode={assignMode ?? defaultValues.assignMode}
mirror={mirrorView ?? defaultValues.mirrorView}
onRoleSelected={tryOpenChokerWarning}
></BodyAssignment>

View File

@@ -1,9 +1,7 @@
import classNames from 'classnames';
import { useForm } from 'react-hook-form';
import ReactModal from 'react-modal';
import { BodyPart } from 'solarxr-protocol';
import { Button } from '@/components/commons/Button';
import { CheckBox } from '@/components/commons/Checkbox';
import { Typography } from '@/components/commons/Typography';
import { BodyAssignment } from '@/components/onboarding/BodyAssignment';
import { useLocalization } from '@fluent/react';
@@ -24,9 +22,6 @@ export function SingleTrackerBodyAssignmentMenu({
const { isMobile } = useBreakpoint('mobile');
const { l10n } = useLocalization();
const { config } = useConfig();
const defaultValues = { advanced: false };
const { control, watch } = useForm<{ advanced: boolean }>({ defaultValues });
const { advanced } = watch();
const { closeChokerWarning, tryOpenChokerWarning, shouldShowChokerWarn } =
useChokerWarning({
@@ -56,14 +51,6 @@ export function SingleTrackerBodyAssignmentMenu({
<Typography color="secondary">
{l10n.getString('body_assignment_menu-description')}
</Typography>
<CheckBox
control={control}
label={l10n.getString(
'body_assignment_menu-show_advanced_locations'
)}
name="advanced"
variant="toggle"
></CheckBox>
<div className="flex">
<Button
variant="secondary"
@@ -79,7 +66,7 @@ export function SingleTrackerBodyAssignmentMenu({
mirror={config?.mirrorView ?? defaultConfig.mirrorView}
width={isMobile ? 160 : undefined}
onlyAssigned={false}
advanced={advanced ?? defaultValues.advanced}
assignMode={config?.assignMode ?? defaultConfig.assignMode}
onRoleSelected={tryOpenChokerWarning}
></BodyAssignment>
<div className="flex justify-center">

View File

@@ -13,6 +13,14 @@ export interface WindowConfig {
y: number;
}
export enum AssignMode {
LowerBody = 'lower-body',
Core = 'core',
EnhancedCore = 'enhanced-core',
FullBody = 'full-body',
All = 'all',
}
export interface Config {
debug: boolean;
lang: string;
@@ -25,10 +33,10 @@ export interface Config {
theme: string;
textSize: number;
fonts: string[];
advancedAssign: boolean;
useTray: boolean | null;
doneManualMounting: boolean;
mirrorView: boolean;
assignMode: AssignMode;
discordPresence: boolean;
}
@@ -51,10 +59,10 @@ export const defaultConfig: Omit<Config, 'devSettings'> = {
theme: 'slime',
textSize: 12,
fonts: ['poppins'],
advancedAssign: false,
useTray: null,
doneManualMounting: false,
mirrorView: true,
assignMode: AssignMode.Core,
discordPresence: false,
};