Skip to content
Open
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions gui/public/i18n/en/translation.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -934,6 +934,38 @@ onboarding-setup_warning =
onboarding-setup_warning-skip = Skip setup
onboarding-setup_warning-cancel = Continue setup

## Quiz
onboarding-quiz_continue= Continue

onboarding-quiz-slimeSet-title = Tracker Type
onboarding-quiz-slimeSet-description = Are you using an official regular slime or a Butterfly tracker
(If you have third party trackers and are not sure, ask your seller)
onboarding-quiz-slimeSet-answer-Regular = Regular Slime
onboarding-quiz-slimeSet-answer-Butterfly = Butterfly

onboarding-quiz-Usage-title = Use Case
onboarding-quiz-Usage-description = What are you using your trackers for? If you plan on using SlimeVR for multiple purposes, dont worry, you can change the according settings later.
onboarding-quiz-Usage-answer-VRC = VR Gaming (e.g. VRChat)
onboarding-quiz-Usage-answer-mocap = Mocap (Motion Capture)
onboarding-quiz-Usage-answer-vtubing = VTubing

onboarding-quiz-runtime-title = Runtime
onboarding-quiz-runtime-description = Are you using SlimeVR on SteamVR or on a Standalone headset such as the meta quest or Pico heaset, if you are using Quest link or Virtual desktop, you should
select SteamVR
onboarding-quiz-runtime-answer-steamvr = SteamVR
onboarding-quiz-runtime-answer-standalone = Standalone

onboarding-quiz-mocapPos-title = Mocap Head Tracker
onboarding-quiz-mocapPos-description = If you are using a head tracker such as a Vive tracker or SlimeVR tracker on your forehead, then select forehead, if you are wearing a VR Headset for example then
you should select Face, since the tracking point is on your face.
onboarding-quiz-mocapPos-answer-forehead = Forehead
onboarding-quiz-mocapPos-answer-face = Face

onboarding-quiz-Update-title = Tracker Update
onboarding-quiz-Update-description = Would you like to update your trackers to make sure they have the most up to date firmware?
onboarding-quiz-Update-answer-yes = Yes
onboarding-quiz-Update-answer-no = No

## Wi-Fi setup
onboarding-wifi_creds-back = Go back to introduction
onboarding-wifi_creds-v2 = Trackers using Wi-Fi
Expand Down Expand Up @@ -1468,6 +1500,7 @@ firmware_tool-flashing_step-description =
firmware_tool-flashing_step-warning-v2 = Do not unplug or turn off the tracker during the upload process unless told to, it may make your board unusable
firmware_tool-flashing_step-flash_more = Flash more trackers
firmware_tool-flashing_step-exit = Exit
firmware_tool-flashing_step-onboarding_continue = Continue

## firmware tool build status
firmware_tool-build-QUEUED = Waiting to build....
Expand Down
13 changes: 13 additions & 0 deletions gui/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ import { AutomaticMountingPage } from './components/onboarding/pages/mounting/Au
import { ManualMountingPage } from './components/onboarding/pages/mounting/ManualMounting';
import { TrackersAssignPage } from './components/onboarding/pages/trackers-assign/TrackerAssignment';
import { WifiCredsPage } from './components/onboarding/pages/WifiCreds';
import { QuizSlimeSetQuestion } from './components/onboarding/pages/Quiz/QuizSteps/SlimeSetQuestion';
import { QuizUsageQuestion } from './components/onboarding/pages/Quiz/QuizSteps/UsageQuestion';
import { QuizRuntimeQuestion } from './components/onboarding/pages/Quiz/QuizSteps/RuntimeQuestionLast';
import { QuizMocapPosQuestion } from './components/onboarding/pages/Quiz/QuizSteps/MocapPosQuestionLast';
import { UpdateQuestion } from './components/onboarding/pages/Quiz/QuizSteps/UpdateQuestion';
import { DonglePage } from './components/onboarding/pages/Dongle';
import { ConfigContextProvider } from './components/providers/ConfigContext';
import { SerialDetectionModal } from './components/SerialDetectionModal';
import { VRCOSCSettings } from './components/settings/pages/VRCOSCSettings';
Expand Down Expand Up @@ -153,6 +159,13 @@ function Layout() {
>
<Route path="home" element={<HomePage />} />
<Route path="wifi-creds" element={<WifiCredsPage />} />
<Route path="quiz/slime-set" element={<QuizSlimeSetQuestion />} />
<Route path="quiz/usage" element={<QuizUsageQuestion />} />
<Route path="quiz/runtime" element={<QuizRuntimeQuestion />} />
<Route path="quiz/mocap-pos" element={<QuizMocapPosQuestion />} />
<Route path="quiz/update?" element={<UpdateQuestion />} />
<Route path="dongle" element={<DonglePage />} />
<Route path="firmware-tool" element={<FirmwareToolSettings />} />
<Route path="connect-trackers" element={<ConnectTrackersPage />} />
<Route path="trackers-assign" element={<TrackersAssignPage />} />
<Route path="mounting/choose" element={<MountingChoose />} />
Expand Down
2 changes: 1 addition & 1 deletion gui/src/components/commons/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ export function Dropdown({
const {
field: { value, onChange },
} = useController({ name, control, rules });

return (
<DropdownInside value={value} name={name} {...props} onChange={onChange} />
);
Expand Down
33 changes: 23 additions & 10 deletions gui/src/components/firmware-tool/steps/FlashingStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export function FlashingStep({
const { l10n } = useLocalization();
const { selectedDevices, selectDevices, files, selectedDefault } =
useFirmwareTool();
const { state: onboardingState } = useOnboarding();
const { state: onboardingState, state } = useOnboarding();
const { sendRPCPacket, useRPCPacket } = useWebsocketAPI();
const [status, setStatus] = useState<{
[key: string]: {
Expand Down Expand Up @@ -203,15 +203,28 @@ export function FlashingStep({
onClick={() => goTo('FlashingMethod')}
/>
</Localized>
<Localized id="firmware_tool-flashing_step-exit">
<Button
variant="primary"
onClick={() => {
clear();
nav('/');
}}
/>
</Localized>
{state.alonePage && (
<Localized id="firmware_tool-flashing_step-exit">
<Button
variant="primary"
onClick={() => {
clear();
nav('/');
}}
/>
</Localized>
)}
{!state.alonePage && (
<Localized id="firmware_tool-flashing_step-onboarding_continue">
<Button
variant="primary"
onClick={() => {
clear();
nav('/onboarding/trackers-assign');
}}
/>
</Localized>
)}
</div>
</div>
</div>
Expand Down
10 changes: 8 additions & 2 deletions gui/src/components/onboarding/pages/ConnectTracker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export function ConnectTrackersPage() {
const { visibleSteps } = useTrackingChecklist();

const connectedIMUTrackers = useAtomValue(connectedIMUTrackersAtom);
const { applyProgress, state } = useOnboarding();
const { applyProgress, state, update } = useOnboarding();
const navigate = useNavigate();
const { sendRPCPacket, useRPCPacket } = useWebsocketAPI();
const [provisioningStatus, setProvisioningStatus] =
Expand Down Expand Up @@ -320,7 +320,13 @@ export function ConnectTrackersPage() {
</Button>
<Button
variant="primary"
to={state.alonePage ? '/' : '/onboarding/trackers-assign'}
to={
state.alonePage
? '/'
: update === true
? '/onboarding/firmware-tool'
: '/onboarding/trackers-assign'
}
className="ml-auto"
>
{l10n.getString('onboarding-connect_tracker-next')}
Expand Down
45 changes: 45 additions & 0 deletions gui/src/components/onboarding/pages/Dongle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Localized } from '@fluent/react';
import { useOnboarding } from '@/hooks/onboarding';
import { Button } from '@/components/commons/Button';
import { Typography } from '@/components/commons/Typography';
import classNames from 'classnames';
import { USBIcon } from '@/components/commons/icon/UsbIcon';
import { WarningBox } from '@/components/commons/TipBox';

export function DonglePage() {
const { applyProgress, state } = useOnboarding();

applyProgress(0.5);

return (
<div className="flex flex-col w-full h-full xs:justify-center items-center">
<div className="flex flex-col gap-2">
<div className="flex gap-2 items-center">
<div className="bg-accent-background-30 rounded-full p-2 fill-background-10">
<USBIcon size={24} />
</div>
<Typography
variant="main-title"
id="onboarding-wifi_creds-dongle-title"
/>
</div>
<div className={classNames('flex flex-col gap-2 flex-grow p-2')}>
<Typography
whitespace="whitespace-pre-wrap"
id="onboarding-wifi_creds-dongle-description"
/>
<Localized id="onboarding-wifi_creds-dongle-wip">
<WarningBox whitespace>WARNING</WarningBox>
</Localized>
</div>
<div className="flex px-2 p-6">
<Button
variant="primary"
to={state.alonePage ? '/' : '/onboarding/trackers-assign'}
id="onboarding-wifi_creds-dongle-continue"
/>
</div>
</div>
</div>
);
}
2 changes: 1 addition & 1 deletion gui/src/components/onboarding/pages/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function HomePage() {
<Typography variant="mobile-title">
{l10n.getString('onboarding-home')}
</Typography>
<Button variant="primary" to="/onboarding/wifi-creds">
<Button variant="primary" to="/onboarding/quiz/slime-set">
{l10n.getString('onboarding-home-start')}
</Button>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import { useOnboarding } from '@/hooks/onboarding';
import classNames from 'classnames';
import { useState, useEffect, createContext } from 'react';
import { Typography } from '@/components/commons/Typography';
import { Button } from '@/components/commons/Button';
import { useWebsocketAPI } from '@/hooks/websocket-api';
import { Localized } from '@fluent/react';
import {
RpcMessage,
SettingsResponseT,
ChangeSettingsRequestT,
ModelSettingsT,
SettingsRequestT,
ResetsSettingsT,
ModelTogglesT,
} from 'solarxr-protocol';
export const LevelContext = createContext(1);

export function QuizMocapPosQuestion() {
const { applyProgress, setMocapPos, usage, slimeSet, update, mocapPos } =

Check warning on line 20 in gui/src/components/onboarding/pages/Quiz/QuizSteps/MocapPosQuestionLast.tsx

View workflow job for this annotation

GitHub Actions / lint

'update' is assigned a value but never used. Allowed unused vars must match /^_/u
useOnboarding();
const { sendRPCPacket, useRPCPacket } = useWebsocketAPI();
const [settings, setSettings] = useState<SettingsResponseT>();
const [to, setTo] = useState('');
const [disabled, setDisabled] = useState(true);

applyProgress(0.4);

useEffect(() => {
sendRPCPacket(RpcMessage.SettingsRequest, new SettingsRequestT());
}, []);

useRPCPacket(RpcMessage.SettingsResponse, (settings: SettingsResponseT) => {
setSettings(settings);
});

const updateTo = () => {
if (slimeSet === 'butterfly') {
setTo('/onboarding/dongle');
} else {
setTo('/onboarding/wifi-creds');
}
};

const applySettings = () => {
if (!settings?.modelSettings || !settings?.vrcOsc)
throw 'settings should be set';
const req = new ChangeSettingsRequestT();
const modelSettings = new ModelSettingsT();
const resetSettings = new ResetsSettingsT();

if (usage === 'mocap') {
const toggles = Object.assign(
new ModelTogglesT(),
settings.modelSettings.toggles
);
toggles.selfLocalization = true;
modelSettings.toggles = toggles;
req.modelSettings = modelSettings;

if (mocapPos === 'forehead') {
const resets = Object.assign(resetSettings, settings.resetsSettings);
resets.resetHmdPitch = true;
req.resetsSettings = resets;
}
}

sendRPCPacket(RpcMessage.ChangeSettingsRequest, req);
};

applyProgress(0.2);

return (
<div className="flex flex-col w-full h-full xs:justify-center items-center">
<div className="flex flex-col gap-2">
<div className="flex gap-2 items-center">
<Typography
variant="main-title"
id="onboarding-quiz-mocapPos-title"
/>
</div>
<div className="">
<div className={classNames('flex flex-col gap-2 flex-grow p-2')}>
<Typography
whitespace="whitespace-pre-wrap"
id="onboarding-quiz-mocapPos-description"
/>
</div>
<div className="flex gap-2 px-2 p-6">
<div
onClick={() => {
setMocapPos('forehead');
updateTo();
setDisabled(false);
}}
className={classNames(
'rounded-lg overflow-hidden transition-[box-shadow] duration-200 ease-linear hover:bg-background-50 cursor-pointer bg-background-60',
mocapPos === 'forehead' &&
'outline outline-3 outline-accent-background-40'
)}
>
<div className="flex flex-col justify-center rounded-md py-3 pr-4 pl-4 w-full gap-2 box-border">
<div className="min-h-9 flex text-default justify-center gap-5 flex-wrap items-center">
<Typography id="onboarding-quiz-mocapPos-answer-forehead" />
</div>
</div>
</div>
<div
onClick={() => {
setMocapPos('face');
updateTo();
setDisabled(false);
}}
className={classNames(
'rounded-lg overflow-hidden transition-[box-shadow] duration-200 ease-linear hover:bg-background-50 cursor-pointer bg-background-60',
mocapPos === 'face' &&
'outline outline-3 outline-accent-background-40'
)}
>
<div className="flex flex-col justify-center rounded-md py-3 pr-4 pl-4 w-full gap-2 box-border">
<div className="min-h-9 flex text-default justify-center gap-5 flex-wrap items-center">
<Typography id="onboarding-quiz-mocapPos-answer-face" />
</div>
</div>
</div>
</div>
</div>
<div className="flex px-2 p-6">
<Localized id="onboarding-quiz_continue">
<Button
to={to}
children="Continue"
variant="primary"
onClick={applySettings}
disabled={disabled}
/>
</Localized>
</div>
</div>
</div>
);
}
Loading
Loading