Files
modeling-app/src/components/GlobalStateProvider.tsx
Jess Frazelle cbd26d29fa updates for units (#1458)
* updates for units

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* scene units

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* start passing in units to tests

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* units tests

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* add more images

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* hacky code for now

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* get settings context outside of react

* fmt

* pull through settings

* fix

* fmt

* move camera with units (#1461)

* temp patch tsc

* update kittycad.rs

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* trait

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix compile

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* update screenshots

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* execute on settings change

* Update src/clientSideScene/sceneInfra.ts

* try zoom

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* more shit image

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* new screenshots

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* udpates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* tests

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* update cam

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* new

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates for units

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixles

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* ;scale

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fixes

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fmt

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* tweak playwright draft segments test

* another test tweak

* last test tweak

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)

* update default plane snapshot scale

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)

* number tweaks for playwright flow checks

* up[date

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
Co-authored-by: Kurt Hutten Irev-Dev <k.hutten@protonmail.ch>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-02-20 17:55:06 -08:00

160 lines
4.6 KiB
TypeScript

import { useMachine } from '@xstate/react'
import { useNavigate } from 'react-router-dom'
import { paths } from 'lib/paths'
import { authMachine, TOKEN_PERSIST_KEY } from '../machines/authMachine'
import withBaseUrl from '../lib/withBaseURL'
import React, { createContext, useEffect, useRef } from 'react'
import useStateMachineCommands from '../hooks/useStateMachineCommands'
import { SETTINGS_PERSIST_KEY, settingsMachine } from 'machines/settingsMachine'
import { toast } from 'react-hot-toast'
import { setThemeClass, Themes } from 'lib/theme'
import {
AnyStateMachine,
ContextFrom,
InterpreterFrom,
Prop,
StateFrom,
} from 'xstate'
import { isTauri } from 'lib/isTauri'
import { settingsCommandBarConfig } from 'lib/commandBarConfigs/settingsCommandConfig'
import { authCommandBarConfig } from 'lib/commandBarConfigs/authCommandConfig'
type MachineContext<T extends AnyStateMachine> = {
state: StateFrom<T>
context: ContextFrom<T>
send: Prop<InterpreterFrom<T>, 'send'>
}
type GlobalContext = {
auth: MachineContext<typeof authMachine>
settings: MachineContext<typeof settingsMachine>
}
// a little hacky for sure, open to changing it
// this implies that we should only even have one instance of this provider mounted at any one time
// but I think that's a safe assumption
let settingsStateRef: (typeof settingsMachine)['context'] | undefined
export const getSettingsState = () => settingsStateRef
export const GlobalStateContext = createContext({} as GlobalContext)
export const GlobalStateProvider = ({
children,
}: {
children: React.ReactNode
}) => {
const navigate = useNavigate()
// Settings machine setup
const retrievedSettings = useRef(
localStorage?.getItem(SETTINGS_PERSIST_KEY) || '{}'
)
const persistedSettings = Object.assign(
settingsMachine.initialState.context,
JSON.parse(retrievedSettings.current) as Partial<
(typeof settingsMachine)['context']
>
)
const [settingsState, settingsSend] = useMachine(settingsMachine, {
context: persistedSettings,
actions: {
toastSuccess: (context, event) => {
const truncatedNewValue =
'data' in event && event.data instanceof Object
? (context[Object.keys(event.data)[0] as keyof typeof context]
.toString()
.substring(0, 28) as any)
: undefined
toast.success(
event.type +
(truncatedNewValue
? ` to "${truncatedNewValue}${
truncatedNewValue.length === 28 ? '...' : ''
}"`
: '')
)
},
},
})
settingsStateRef = settingsState.context
useStateMachineCommands({
machineId: 'settings',
state: settingsState,
send: settingsSend,
commandBarConfig: settingsCommandBarConfig,
})
// Listen for changes to the system theme and update the app theme accordingly
// This is only done if the theme setting is set to 'system'.
// It can't be done in XState (in an invoked callback, for example)
// because there doesn't seem to be a good way to listen to
// events outside of the machine that also depend on the machine's context
useEffect(() => {
const matcher = window.matchMedia('(prefers-color-scheme: dark)')
const listener = (e: MediaQueryListEvent) => {
if (settingsState.context.theme !== 'system') return
setThemeClass(e.matches ? Themes.Dark : Themes.Light)
}
matcher.addEventListener('change', listener)
return () => matcher.removeEventListener('change', listener)
}, [settingsState.context])
// Auth machine setup
const [authState, authSend] = useMachine(authMachine, {
actions: {
goToSignInPage: () => {
navigate(paths.SIGN_IN)
logout()
},
goToIndexPage: () => {
if (window.location.pathname.includes(paths.SIGN_IN)) {
navigate(paths.INDEX)
}
},
},
})
useStateMachineCommands({
machineId: 'auth',
state: authState,
send: authSend,
commandBarConfig: authCommandBarConfig,
})
return (
<GlobalStateContext.Provider
value={{
auth: {
state: authState,
context: authState.context,
send: authSend,
},
settings: {
state: settingsState,
context: settingsState.context,
send: settingsSend,
},
}}
>
{children}
</GlobalStateContext.Provider>
)
}
export default GlobalStateProvider
export function logout() {
localStorage.removeItem(TOKEN_PERSIST_KEY)
return (
!isTauri() &&
fetch(withBaseUrl('/logout'), {
method: 'POST',
credentials: 'include',
})
)
}