diff --git a/src/components/SettingsAuthProvider.tsx b/src/components/SettingsAuthProvider.tsx index fc2ebac16..28ee19c2f 100644 --- a/src/components/SettingsAuthProvider.tsx +++ b/src/components/SettingsAuthProvider.tsx @@ -171,7 +171,9 @@ export const SettingsAuthProviderBase = ({ }) }, 'Execute AST': () => kclManager.executeCode(true, true), - persistSettings: (context) => + }, + services: { + 'Persist settings': (context) => saveSettings(context, loadedProject?.project?.path), }, } diff --git a/src/lib/paths.ts b/src/lib/paths.ts index 5f0f1794b..91345f39b 100644 --- a/src/lib/paths.ts +++ b/src/lib/paths.ts @@ -17,15 +17,17 @@ const prependRoutes = ) } +type OnboardingPaths = { + [K in keyof typeof onboardingPaths]: `/onboarding${(typeof onboardingPaths)[K]}` +} + export const paths = { INDEX: '/', HOME: '/home', FILE: '/file', SETTINGS: '/settings', SIGN_IN: '/signin', - ONBOARDING: prependRoutes(onboardingPaths)( - '/onboarding' - ) as typeof onboardingPaths, + ONBOARDING: prependRoutes(onboardingPaths)('/onboarding') as OnboardingPaths, } as const export const BROWSER_PATH = `%2F${BROWSER_PROJECT_NAME}%2F${BROWSER_FILE_NAME}${FILE_EXT}` diff --git a/src/machines/settingsMachine.ts b/src/machines/settingsMachine.ts index bcaee4938..f9fe822f9 100644 --- a/src/machines/settingsMachine.ts +++ b/src/machines/settingsMachine.ts @@ -11,98 +11,98 @@ import { export const settingsMachine = createMachine( { - /** @xstate-layout N4IgpgJg5mDOIC5QGUwBc0EsB2VYDpMIAbMAYlnXwEMAHW-Ae2wCNHqAnCHKZNatAFdYAbQAMAXUShajWJizNpIAB6IAbAFZN+AOwAWAIwAOYwE4AzGYBM+-ZosAaEAE9Eh62LP51ls+v0LMWt1awMAX3DnVAweAiJSCio6BjQACzAAWzAAYUZiRg5xKSQQWXlFbGU1BA9vQ0N1CwCxdVbdY1DnNwQzPp8zTTFje1D1QwtjSOj0LFx4knJKNHxMxggwYh58DYAzakFiNABVbAVi5XKFTCVSmotNY3w7YysHRuNDTXV1bvdG7w-IKTcbaazWCzTEAxOZ4QiLJIrFL4dJZMAXUpXSrVDTGazPMQPR4GXRBAx-XoGfDWIadMx4n6EqEwuLwxLLVbrTbbNKYKBpLb8tAAUWgcAxMjk11uoHumn0+DEw2sJkMulCgWsFL6YnwfX0ELsYg61jMumZs1ZCXIACU4OgAATLWGiSSXKXYu4aLz4UwWBr6DqBYYUzSePXqUlBLxmyZmC2xeZs8gxB3UYjEJ2W+YSsoem5VL0IKy6z6EsJifQ2Czq0MTHzq8Yjfz6MQmBMu5NkABUuaxBZxCDD+DD5lJgUjxssFP0xl0I+0pm06uMmg8kSiIGwXPgpRZ83dFQHRYAtA0LCO2tZjGIHJNdB5fq5EK3dc1OsNGkrA+oO1bFoe0qFrKiAnlol7BDed5zo+FK+Doc7qhCNaVv4UwbkAA */ + /** @xstate-layout N4IgpgJg5mDOIC5QGUwBc0EsB2VYDpMIAbMAYlnXwEMAHW-Ae2wCNHqAnCHKZNatAFdYAbQAMAXUShajWJizNpIAB6IALAFYAnPgBMARgDsBsQDY969QGYjmzQBoQAT0SnrADnwePY61r0PAwNtMyMAX3CnVAweAiJSCio6BjQACzAAWzAAYUZiRg5xKSQQWXlFbGU1BD1PfFtfE3UzTUNNaydXBCD1b209PTEPTTMtdQNNSOj0LFx4knJKNHxMxggwYh58DYAzakFiNABVbAVi5XKFTCVSmsGxfCMPM08PQaDNU0cXRG1tLwedTaKxif7+UJTKIgGJzPCERZJFYpfDpLJgC6lK6VaqIEx6fBmCw2Do2IJ6MxdRDvTT4MRDdRGEzWbQ6ELTGGzOIIxLLVbrTbbNKYKBpLaitAAUWgcExMjk11uoBqVgM3jMYhsAIMrVs6ipPWChOeYhC9KMFhGHNh3IS5AASnB0AACZZw0SSS4KnF3PFafADTV1YZ2IxiH7dNpGfCaIzAgE+IzWMzBa1c+Y88gxZ3UYjEV3pvBysrem5VX0IFq0y3aTXWOp6JmU34IKMxuz0joGEYWsxp2IZu1kABUxexZdxtRG+EmQMZmne3dNBs0jKewLBsbCwI81n77vwtDAHHksDhBYHeDIEGYYEI2AAbowANZ3o8nzBnm3zMelpWqRAAFp62sJ4jEsZ4AT0UJGwjPFzH6cwNW0AwWXpbRImhbABXgUpvzwL0KgnCtgJMMCII8KCYLsA11EGOkXneDxmXMCk92hfCFlIQjFXLZUgLjddWhaFkgRCaxOhbEYzBnXwXkmOjAjjfduXfU9zzdOIeJ9fiEEA6ckwMClQ2BFpmJXMF9DjYI6hZfxmMw8IgA */ id: 'Settings', predictableActionArguments: true, context: {} as ReturnType, initial: 'idle', states: { idle: { - entry: ['setThemeClass', 'setClientSideSceneUnits', 'persistSettings'], + entry: ['setThemeClass', 'setClientSideSceneUnits'], on: { '*': { - target: 'idle', - internal: true, - actions: ['setSettingAtLevel', 'toastSuccess', 'persistSettings'], + target: 'persisting settings', + actions: ['setSettingAtLevel', 'toastSuccess'], }, 'set.app.onboardingStatus': { - target: 'idle', - internal: true, - actions: ['setSettingAtLevel', 'persistSettings'], // No toast + target: 'persisting settings', + + // No toast + actions: ['setSettingAtLevel'], }, 'set.app.themeColor': { - target: 'idle', - internal: true, - actions: ['setSettingAtLevel', 'persistSettings'], // No toast + target: 'persisting settings', + + // No toast + actions: ['setSettingAtLevel'], }, 'set.modeling.defaultUnit': { - target: 'idle', - internal: true, + target: 'persisting settings', + actions: [ 'setSettingAtLevel', 'toastSuccess', 'setClientSideSceneUnits', 'Execute AST', - 'persistSettings', ], }, 'set.app.theme': { - target: 'idle', - internal: true, + target: 'persisting settings', + actions: [ 'setSettingAtLevel', 'toastSuccess', 'setThemeClass', 'setEngineTheme', - 'persistSettings', 'setClientTheme', ], }, 'set.modeling.highlightEdges': { - target: 'idle', - internal: true, - actions: [ - 'setSettingAtLevel', - 'toastSuccess', - 'setEngineEdges', - 'persistSettings', - ], + target: 'persisting settings', + + actions: ['setSettingAtLevel', 'toastSuccess', 'setEngineEdges'], }, 'Reset settings': { - target: 'idle', - internal: true, + target: 'persisting settings', + actions: [ 'resetSettings', 'setThemeClass', 'setEngineTheme', 'setClientSideSceneUnits', 'Execute AST', - 'persistSettings', 'setClientTheme', ], }, 'Set all settings': { - target: 'idle', - internal: true, + target: 'persisting settings', + actions: [ 'setAllSettings', 'setThemeClass', 'setEngineTheme', 'setClientSideSceneUnits', 'Execute AST', - 'persistSettings', 'setClientTheme', ], }, }, }, + + 'persisting settings': { + invoke: { + src: 'Persist settings', + id: 'persistSettings', + onDone: 'idle', + }, + }, }, tsTypes: {} as import('./settingsMachine.typegen').Typegen0, schema: { diff --git a/src/routes/Onboarding/index.tsx b/src/routes/Onboarding/index.tsx index 9f2c301f4..147ab4e17 100644 --- a/src/routes/Onboarding/index.tsx +++ b/src/routes/Onboarding/index.tsx @@ -3,7 +3,7 @@ import { Outlet, useNavigate } from 'react-router-dom' import Introduction from './Introduction' import Camera from './Camera' import Sketching from './Sketching' -import { useCallback } from 'react' +import { useCallback, useEffect } from 'react' import makeUrlPathRelative from '../../lib/makeUrlPathRelative' import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext' import Streaming from './Streaming' @@ -94,17 +94,31 @@ export function useNextClick(newStatus: string) { export function useDismiss() { const filePath = useAbsoluteFilePath() const { - settings: { send }, + settings: { state, send }, } = useSettingsAuthContext() const navigate = useNavigate() - return useCallback(() => { + const settingsCallback = useCallback(() => { send({ type: 'set.app.onboardingStatus', data: { level: 'user', value: 'dismissed' }, }) - navigate(filePath) - }, [send, navigate, filePath]) + }, [send]) + + /** + * A "listener" for the XState to return to "idle" state + * when the user dismisses the onboarding, using the callback above + */ + useEffect(() => { + if ( + state.context.app.onboardingStatus.user === 'dismissed' && + state.matches('idle') + ) { + navigate(filePath) + } + }, [filePath, navigate, state]) + + return settingsCallback } // Get the 1-indexed step number of the current onboarding step