2023-08-29 10:48:55 -04:00
|
|
|
import { useMachine } from '@xstate/react'
|
2024-03-14 15:56:45 -04:00
|
|
|
import { useNavigate, useRouteLoaderData } from 'react-router-dom'
|
2024-02-11 12:59:00 +11:00
|
|
|
import { paths } from 'lib/paths'
|
Command bar: add extrude command, nonlinear editing, etc (#1204)
* Tweak toaster look and feel
* Add icons, tweak plus icon names
* Rename commandBarMeta to commandBarConfig
* Refactor command bar, add support for icons
* Create a tailwind plugin for aria-pressed button state
* Remove overlay from behind command bar
* Clean up toolbar
* Button and other style tweaks
* Icon tweaks follow-up: make old icons work with new sizing
* Delete unused static icons
* More CSS tweaks
* Small CSS tweak to project sidebar
* Add command bar E2E test
* fumpt
* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)
* fix typo in a comment
* Fix icon padding (built version only)
* Update onboarding and warning banner icons padding
* Misc minor style fixes
* Get Extrude opening and canceling from command bar
* Iconography tweaks
* Get extrude kind of working
* Refactor command bar config types and organization
* Move command bar configs to be co-located with each other
* Start building a state machine for the command bar
* Start converting command bar to state machine
* Add support for multiple args, confirmation step
* Submission behavior, hotkeys, code organization
* Add new test for extruding from command bar
* Polish step back and selection hotkeys, CSS tweaks
* Loading style tweaks
* Validate selection inputs, polish UX of args re-editing
* Prevent submission with multiple selection on singlular arg
* Remove stray console logs
* Tweak test, CSS nit, remove extrude "result" argument
* Fix linting warnings
* Show Ctrl+/ instead of ⌘K on all platforms but Mac
* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)
* Add "Enter sketch" to command bar
* fix command bar test
* Fix flaky cmd bar extrude test by waiting for engine select response
* Cover both button labels '⌘K' and 'Ctrl+/' in test
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-12-13 12:49:01 -05:00
|
|
|
import { authMachine, TOKEN_PERSIST_KEY } from '../machines/authMachine'
|
2023-08-29 10:48:55 -04:00
|
|
|
import withBaseUrl from '../lib/withBaseURL'
|
2024-03-14 15:56:45 -04:00
|
|
|
import React, { createContext, useEffect } from 'react'
|
2023-08-29 10:48:55 -04:00
|
|
|
import useStateMachineCommands from '../hooks/useStateMachineCommands'
|
2024-03-12 10:37:35 -04:00
|
|
|
import { settingsMachine } from 'machines/settingsMachine'
|
2023-08-29 10:48:55 -04:00
|
|
|
import { toast } from 'react-hot-toast'
|
2024-03-22 09:35:07 -04:00
|
|
|
import { getThemeColorForEngine, setThemeClass, Themes } from 'lib/theme'
|
2024-04-02 10:29:34 -04:00
|
|
|
import decamelize from 'decamelize'
|
2023-08-29 10:48:55 -04:00
|
|
|
import {
|
|
|
|
AnyStateMachine,
|
|
|
|
ContextFrom,
|
|
|
|
InterpreterFrom,
|
|
|
|
Prop,
|
|
|
|
StateFrom,
|
|
|
|
} from 'xstate'
|
2023-09-14 19:31:16 -04:00
|
|
|
import { isTauri } from 'lib/isTauri'
|
Command bar: add extrude command, nonlinear editing, etc (#1204)
* Tweak toaster look and feel
* Add icons, tweak plus icon names
* Rename commandBarMeta to commandBarConfig
* Refactor command bar, add support for icons
* Create a tailwind plugin for aria-pressed button state
* Remove overlay from behind command bar
* Clean up toolbar
* Button and other style tweaks
* Icon tweaks follow-up: make old icons work with new sizing
* Delete unused static icons
* More CSS tweaks
* Small CSS tweak to project sidebar
* Add command bar E2E test
* fumpt
* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)
* fix typo in a comment
* Fix icon padding (built version only)
* Update onboarding and warning banner icons padding
* Misc minor style fixes
* Get Extrude opening and canceling from command bar
* Iconography tweaks
* Get extrude kind of working
* Refactor command bar config types and organization
* Move command bar configs to be co-located with each other
* Start building a state machine for the command bar
* Start converting command bar to state machine
* Add support for multiple args, confirmation step
* Submission behavior, hotkeys, code organization
* Add new test for extruding from command bar
* Polish step back and selection hotkeys, CSS tweaks
* Loading style tweaks
* Validate selection inputs, polish UX of args re-editing
* Prevent submission with multiple selection on singlular arg
* Remove stray console logs
* Tweak test, CSS nit, remove extrude "result" argument
* Fix linting warnings
* Show Ctrl+/ instead of ⌘K on all platforms but Mac
* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)
* Add "Enter sketch" to command bar
* fix command bar test
* Fix flaky cmd bar extrude test by waiting for engine select response
* Cover both button labels '⌘K' and 'Ctrl+/' in test
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-12-13 12:49:01 -05:00
|
|
|
import { authCommandBarConfig } from 'lib/commandBarConfigs/authCommandConfig'
|
2024-03-22 09:35:07 -04:00
|
|
|
import { kclManager, sceneInfra, engineCommandManager } from 'lib/singletons'
|
2024-04-03 19:38:16 +11:00
|
|
|
import { uuidv4 } from 'lib/utils'
|
2024-04-02 10:29:34 -04:00
|
|
|
import { IndexLoaderData } from 'lib/types'
|
|
|
|
import { settings } from 'lib/settings/initialSettings'
|
|
|
|
import {
|
|
|
|
createSettingsCommand,
|
|
|
|
settingsWithCommandConfigs,
|
|
|
|
} from 'lib/commandBarConfigs/settingsCommandConfig'
|
|
|
|
import { useCommandsContext } from 'hooks/useCommandsContext'
|
|
|
|
import { Command } from 'lib/commandTypes'
|
|
|
|
import { BaseUnit } from 'lib/settings/settingsTypes'
|
|
|
|
import { saveSettings } from 'lib/settings/settingsUtils'
|
2023-08-29 10:48:55 -04:00
|
|
|
|
|
|
|
type MachineContext<T extends AnyStateMachine> = {
|
|
|
|
state: StateFrom<T>
|
|
|
|
context: ContextFrom<T>
|
|
|
|
send: Prop<InterpreterFrom<T>, 'send'>
|
|
|
|
}
|
|
|
|
|
2024-03-14 15:56:45 -04:00
|
|
|
type SettingsAuthContextType = {
|
2023-08-29 10:48:55 -04:00
|
|
|
auth: MachineContext<typeof authMachine>
|
|
|
|
settings: MachineContext<typeof settingsMachine>
|
|
|
|
}
|
|
|
|
|
2024-02-20 17:55:06 -08:00
|
|
|
// 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
|
|
|
|
|
2024-03-14 15:56:45 -04:00
|
|
|
export const SettingsAuthContext = createContext({} as SettingsAuthContextType)
|
2023-08-29 10:48:55 -04:00
|
|
|
|
2024-03-11 20:26:13 -04:00
|
|
|
export const SettingsAuthProvider = ({
|
2023-08-29 10:48:55 -04:00
|
|
|
children,
|
|
|
|
}: {
|
|
|
|
children: React.ReactNode
|
|
|
|
}) => {
|
2024-04-02 10:29:34 -04:00
|
|
|
const loadedSettings = useRouteLoaderData(paths.INDEX) as typeof settings
|
|
|
|
const loadedProject = useRouteLoaderData(paths.FILE) as IndexLoaderData
|
2024-03-14 15:56:45 -04:00
|
|
|
return (
|
2024-04-02 10:29:34 -04:00
|
|
|
<SettingsAuthProviderBase
|
|
|
|
loadedSettings={loadedSettings}
|
|
|
|
loadedProject={loadedProject}
|
|
|
|
>
|
2024-03-14 15:56:45 -04:00
|
|
|
{children}
|
|
|
|
</SettingsAuthProviderBase>
|
2023-08-29 10:48:55 -04:00
|
|
|
)
|
2024-03-14 15:56:45 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// For use in jest tests we don't want to use the loader data
|
|
|
|
// and mock the whole Router
|
|
|
|
export const SettingsAuthProviderJest = ({
|
|
|
|
children,
|
|
|
|
}: {
|
|
|
|
children: React.ReactNode
|
|
|
|
}) => {
|
2024-04-02 10:29:34 -04:00
|
|
|
const loadedSettings = settings
|
2024-03-14 15:56:45 -04:00
|
|
|
return (
|
|
|
|
<SettingsAuthProviderBase loadedSettings={loadedSettings}>
|
|
|
|
{children}
|
|
|
|
</SettingsAuthProviderBase>
|
2023-08-29 10:48:55 -04:00
|
|
|
)
|
2024-03-14 15:56:45 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
export const SettingsAuthProviderBase = ({
|
|
|
|
children,
|
|
|
|
loadedSettings,
|
2024-04-02 10:29:34 -04:00
|
|
|
loadedProject,
|
2024-03-14 15:56:45 -04:00
|
|
|
}: {
|
|
|
|
children: React.ReactNode
|
2024-04-02 10:29:34 -04:00
|
|
|
loadedSettings: typeof settings
|
|
|
|
loadedProject?: IndexLoaderData
|
2024-03-14 15:56:45 -04:00
|
|
|
}) => {
|
|
|
|
const navigate = useNavigate()
|
2024-04-02 10:29:34 -04:00
|
|
|
const { commandBarSend } = useCommandsContext()
|
2023-08-29 10:48:55 -04:00
|
|
|
|
2024-03-04 16:06:43 -05:00
|
|
|
const [settingsState, settingsSend, settingsActor] = useMachine(
|
|
|
|
settingsMachine,
|
|
|
|
{
|
2024-04-02 10:29:34 -04:00
|
|
|
context: loadedSettings,
|
2024-03-04 16:06:43 -05:00
|
|
|
actions: {
|
2024-03-14 15:56:45 -04:00
|
|
|
setClientSideSceneUnits: (context, event) => {
|
|
|
|
const newBaseUnit =
|
2024-04-02 10:29:34 -04:00
|
|
|
event.type === 'set.modeling.defaultUnit'
|
|
|
|
? (event.data.value as BaseUnit)
|
|
|
|
: context.modeling.defaultUnit.current
|
2024-03-14 15:56:45 -04:00
|
|
|
sceneInfra.baseUnit = newBaseUnit
|
|
|
|
},
|
2024-03-22 09:35:07 -04:00
|
|
|
setEngineTheme: (context) => {
|
|
|
|
engineCommandManager.sendSceneCommand({
|
|
|
|
cmd_id: uuidv4(),
|
|
|
|
type: 'modeling_cmd_req',
|
|
|
|
cmd: {
|
|
|
|
type: 'set_background_color',
|
2024-04-02 10:29:34 -04:00
|
|
|
color: getThemeColorForEngine(context.app.theme.current),
|
2024-03-22 09:35:07 -04:00
|
|
|
},
|
|
|
|
})
|
|
|
|
},
|
2024-04-15 12:04:17 -04:00
|
|
|
toastSuccess: (_, event) => {
|
2024-04-02 10:29:34 -04:00
|
|
|
const eventParts = event.type.replace(/^set./, '').split('.') as [
|
|
|
|
keyof typeof settings,
|
|
|
|
string
|
|
|
|
]
|
|
|
|
const truncatedNewValue = event.data.value?.toString().slice(0, 28)
|
|
|
|
const message =
|
|
|
|
`Set ${decamelize(eventParts[1], { separator: ' ' })}` +
|
|
|
|
(truncatedNewValue
|
|
|
|
? ` to "${truncatedNewValue}${
|
|
|
|
truncatedNewValue.length === 28 ? '...' : ''
|
|
|
|
}"${
|
|
|
|
event.data.level === 'project'
|
|
|
|
? ' for this project'
|
|
|
|
: ' as a user default'
|
|
|
|
}`
|
|
|
|
: '')
|
|
|
|
toast.success(message, {
|
|
|
|
duration: message.split(' ').length * 100 + 1500,
|
2024-04-05 01:48:12 -04:00
|
|
|
id: `${event.type}.success`,
|
2024-04-02 10:29:34 -04:00
|
|
|
})
|
2024-03-04 16:06:43 -05:00
|
|
|
},
|
2024-04-17 20:18:07 -07:00
|
|
|
'Execute AST': () => kclManager.executeCode(true),
|
2024-04-02 10:29:34 -04:00
|
|
|
persistSettings: (context) =>
|
|
|
|
saveSettings(context, loadedProject?.project?.path),
|
2023-08-29 10:48:55 -04:00
|
|
|
},
|
2024-03-04 16:06:43 -05:00
|
|
|
}
|
|
|
|
)
|
2024-02-20 17:55:06 -08:00
|
|
|
settingsStateRef = settingsState.context
|
2023-08-29 10:48:55 -04:00
|
|
|
|
2024-04-02 10:29:34 -04:00
|
|
|
// Add settings commands to the command bar
|
|
|
|
// They're treated slightly differently than other commands
|
|
|
|
// Because their state machine doesn't have a meaningful .nextEvents,
|
|
|
|
// and they are configured statically in initialiSettings
|
|
|
|
useEffect(() => {
|
|
|
|
// If the user wants to hide the settings commands
|
|
|
|
//from the command bar don't add them.
|
|
|
|
if (settingsState.context.commandBar.includeSettings.current === false)
|
|
|
|
return
|
|
|
|
|
|
|
|
const commands = settingsWithCommandConfigs(settingsState.context)
|
|
|
|
.map((type) =>
|
|
|
|
createSettingsCommand({
|
|
|
|
type,
|
|
|
|
send: settingsSend,
|
|
|
|
context: settingsState.context,
|
|
|
|
actor: settingsActor,
|
|
|
|
isProjectAvailable: loadedProject !== undefined,
|
|
|
|
})
|
|
|
|
)
|
|
|
|
.filter((c) => c !== null) as Command[]
|
|
|
|
|
|
|
|
commandBarSend({ type: 'Add commands', data: { commands: commands } })
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
commandBarSend({
|
|
|
|
type: 'Remove commands',
|
|
|
|
data: { commands },
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}, [
|
|
|
|
settingsState,
|
|
|
|
settingsSend,
|
|
|
|
settingsActor,
|
|
|
|
commandBarSend,
|
|
|
|
settingsWithCommandConfigs,
|
|
|
|
])
|
2023-08-29 10:48:55 -04:00
|
|
|
|
2023-08-31 09:34:13 -04:00
|
|
|
// 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) => {
|
2024-04-02 10:29:34 -04:00
|
|
|
if (settingsState.context.app.theme.current !== 'system') return
|
2023-08-31 09:34:13 -04:00
|
|
|
setThemeClass(e.matches ? Themes.Dark : Themes.Light)
|
|
|
|
}
|
|
|
|
|
|
|
|
matcher.addEventListener('change', listener)
|
|
|
|
return () => matcher.removeEventListener('change', listener)
|
|
|
|
}, [settingsState.context])
|
2023-08-29 10:48:55 -04:00
|
|
|
|
2024-04-05 00:59:02 -04:00
|
|
|
/**
|
|
|
|
* Update the --primary-hue CSS variable
|
|
|
|
* to match the setting app.themeColor.current
|
|
|
|
*/
|
|
|
|
useEffect(() => {
|
|
|
|
document.documentElement.style.setProperty(
|
|
|
|
`--primary-hue`,
|
|
|
|
settingsState.context.app.themeColor.current
|
|
|
|
)
|
|
|
|
}, [settingsState.context.app.themeColor.current])
|
|
|
|
|
2024-04-15 12:04:17 -04:00
|
|
|
/**
|
|
|
|
* Update the --cursor-color CSS variable
|
|
|
|
* based on the setting textEditor.blinkingCursor.current
|
|
|
|
*/
|
|
|
|
useEffect(() => {
|
|
|
|
document.documentElement.style.setProperty(
|
|
|
|
`--cursor-color`,
|
|
|
|
settingsState.context.textEditor.blinkingCursor.current
|
|
|
|
? 'auto'
|
|
|
|
: 'transparent'
|
|
|
|
)
|
|
|
|
}, [settingsState.context.textEditor.blinkingCursor.current])
|
|
|
|
|
2023-08-29 10:48:55 -04:00
|
|
|
// Auth machine setup
|
2024-03-04 16:06:43 -05:00
|
|
|
const [authState, authSend, authActor] = useMachine(authMachine, {
|
2023-08-29 10:48:55 -04:00
|
|
|
actions: {
|
|
|
|
goToSignInPage: () => {
|
|
|
|
navigate(paths.SIGN_IN)
|
2024-02-11 12:59:00 +11:00
|
|
|
logout()
|
2023-08-29 10:48:55 -04:00
|
|
|
},
|
|
|
|
goToIndexPage: () => {
|
|
|
|
if (window.location.pathname.includes(paths.SIGN_IN)) {
|
|
|
|
navigate(paths.INDEX)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
useStateMachineCommands({
|
Command bar: add extrude command, nonlinear editing, etc (#1204)
* Tweak toaster look and feel
* Add icons, tweak plus icon names
* Rename commandBarMeta to commandBarConfig
* Refactor command bar, add support for icons
* Create a tailwind plugin for aria-pressed button state
* Remove overlay from behind command bar
* Clean up toolbar
* Button and other style tweaks
* Icon tweaks follow-up: make old icons work with new sizing
* Delete unused static icons
* More CSS tweaks
* Small CSS tweak to project sidebar
* Add command bar E2E test
* fumpt
* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)
* fix typo in a comment
* Fix icon padding (built version only)
* Update onboarding and warning banner icons padding
* Misc minor style fixes
* Get Extrude opening and canceling from command bar
* Iconography tweaks
* Get extrude kind of working
* Refactor command bar config types and organization
* Move command bar configs to be co-located with each other
* Start building a state machine for the command bar
* Start converting command bar to state machine
* Add support for multiple args, confirmation step
* Submission behavior, hotkeys, code organization
* Add new test for extruding from command bar
* Polish step back and selection hotkeys, CSS tweaks
* Loading style tweaks
* Validate selection inputs, polish UX of args re-editing
* Prevent submission with multiple selection on singlular arg
* Remove stray console logs
* Tweak test, CSS nit, remove extrude "result" argument
* Fix linting warnings
* Show Ctrl+/ instead of ⌘K on all platforms but Mac
* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)
* Add "Enter sketch" to command bar
* fix command bar test
* Fix flaky cmd bar extrude test by waiting for engine select response
* Cover both button labels '⌘K' and 'Ctrl+/' in test
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-12-13 12:49:01 -05:00
|
|
|
machineId: 'auth',
|
2023-08-29 10:48:55 -04:00
|
|
|
state: authState,
|
|
|
|
send: authSend,
|
2023-12-06 14:44:13 -05:00
|
|
|
commandBarConfig: authCommandBarConfig,
|
2024-03-04 16:06:43 -05:00
|
|
|
actor: authActor,
|
2023-08-29 10:48:55 -04:00
|
|
|
})
|
|
|
|
|
|
|
|
return (
|
2024-03-11 20:26:13 -04:00
|
|
|
<SettingsAuthContext.Provider
|
2023-08-29 10:48:55 -04:00
|
|
|
value={{
|
|
|
|
auth: {
|
|
|
|
state: authState,
|
|
|
|
context: authState.context,
|
|
|
|
send: authSend,
|
|
|
|
},
|
|
|
|
settings: {
|
|
|
|
state: settingsState,
|
|
|
|
context: settingsState.context,
|
|
|
|
send: settingsSend,
|
|
|
|
},
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
{children}
|
2024-03-11 20:26:13 -04:00
|
|
|
</SettingsAuthContext.Provider>
|
2023-08-29 10:48:55 -04:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2024-03-11 20:26:13 -04:00
|
|
|
export default SettingsAuthProvider
|
2023-08-29 10:48:55 -04:00
|
|
|
|
|
|
|
export function logout() {
|
|
|
|
localStorage.removeItem(TOKEN_PERSIST_KEY)
|
2023-09-14 19:31:16 -04:00
|
|
|
return (
|
|
|
|
!isTauri() &&
|
|
|
|
fetch(withBaseUrl('/logout'), {
|
|
|
|
method: 'POST',
|
|
|
|
credentials: 'include',
|
|
|
|
})
|
|
|
|
)
|
2023-08-29 10:48:55 -04:00
|
|
|
}
|