* migrate settingsMachine
* Guard events with properties instead
* migrate settingsMachine
* Migrate auth machine
* Migrate file machine
* Migrate depracated types
* Migrate home machine
* Migrate command bar machine
* Version fixes
* Migrate command bar machine
* Migrate modeling machine
* Migrate types, state.can, state.matches and state.nextEvents
* Fix syntax
* Pass in modelingState into editor manager instead of modeling event
* Fix issue with missing command bar provider
* Fix state transition
* Fix type issue in Home
* Make sure no guards rely on event type
* Fix up command bar submission logic
* Home machine tweaks to get things running
* Fix AST fillet function args
* Handle "Set selection" when it is called by actor onDone
* Remove unused imports
* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)
* Fix injectin project to the fileTree machine
* Revert "A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)"
This reverts commit 4b43ff69d1
.
* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)
* Re-run CI
* Restore success toasts on file/folder deletion
* Replace casting with guarding against event.type
* Remove console.log
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
* Replace all instances of event casting with guards against event.type
---------
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Kurt Hutten Irev-Dev <k.hutten@protonmail.ch>
Co-authored-by: Jonathan Tran <jonnytran@gmail.com>
Co-authored-by: Frank Noirot <frank@zoo.dev>
150 lines
4.3 KiB
TypeScript
150 lines
4.3 KiB
TypeScript
import {
|
|
Command,
|
|
CommandArgument,
|
|
CommandArgumentConfig,
|
|
} from '../commandTypes'
|
|
import {
|
|
SettingsPaths,
|
|
SettingsLevel,
|
|
SettingProps,
|
|
} from 'lib/settings/settingsTypes'
|
|
import { settingsMachine } from 'machines/settingsMachine'
|
|
import { PathValue } from 'lib/types'
|
|
import { Actor, AnyStateMachine, ContextFrom } from 'xstate'
|
|
import { getPropertyByPath } from 'lib/objectPropertyByPath'
|
|
import { buildCommandArgument } from 'lib/createMachineCommand'
|
|
import decamelize from 'decamelize'
|
|
import { isDesktop } from 'lib/isDesktop'
|
|
import { Setting } from 'lib/settings/initialSettings'
|
|
|
|
// An array of the paths to all of the settings that have commandConfigs
|
|
export const settingsWithCommandConfigs = (
|
|
s: ContextFrom<typeof settingsMachine>
|
|
) =>
|
|
Object.entries(s).flatMap(([categoryName, categorySettings]) =>
|
|
Object.entries(categorySettings)
|
|
.filter(([_, setting]) => setting.commandConfig !== undefined)
|
|
.map(([settingName]) => `${categoryName}.${settingName}`)
|
|
) as SettingsPaths[]
|
|
|
|
const levelArgConfig = <T extends AnyStateMachine = AnyStateMachine>(
|
|
actor: Actor<T>,
|
|
isProjectAvailable: boolean,
|
|
hideOnLevel?: SettingsLevel
|
|
): CommandArgument<SettingsLevel, T> => ({
|
|
inputType: 'options' as const,
|
|
required: true,
|
|
defaultValue:
|
|
isProjectAvailable && hideOnLevel !== 'project' ? 'project' : 'user',
|
|
skip: true,
|
|
options:
|
|
isProjectAvailable && hideOnLevel !== 'project'
|
|
? [
|
|
{ name: 'User', value: 'user' as SettingsLevel },
|
|
{
|
|
name: 'Project',
|
|
value: 'project' as SettingsLevel,
|
|
isCurrent: true,
|
|
},
|
|
]
|
|
: [{ name: 'User', value: 'user' as SettingsLevel, isCurrent: true }],
|
|
machineActor: actor,
|
|
})
|
|
|
|
interface CreateSettingsArgs {
|
|
type: SettingsPaths
|
|
send: Function
|
|
context: ContextFrom<typeof settingsMachine>
|
|
actor: Actor<typeof settingsMachine>
|
|
isProjectAvailable: boolean
|
|
}
|
|
|
|
// Takes a Setting with a commandConfig and creates a Command
|
|
// that can be used in the CommandBar component.
|
|
export function createSettingsCommand({
|
|
type,
|
|
send,
|
|
context,
|
|
actor,
|
|
isProjectAvailable,
|
|
}: CreateSettingsArgs) {
|
|
type S = PathValue<typeof context, typeof type>
|
|
|
|
const settingConfig = getPropertyByPath(context, type) as SettingProps<
|
|
S['default']
|
|
>
|
|
const valueArgPartialConfig = settingConfig['commandConfig']
|
|
const shouldHideOnThisLevel =
|
|
settingConfig?.hideOnLevel === 'user' && !isProjectAvailable
|
|
const shouldHideOnThisPlatform =
|
|
settingConfig.hideOnPlatform &&
|
|
(isDesktop()
|
|
? settingConfig.hideOnPlatform === 'desktop'
|
|
: settingConfig.hideOnPlatform === 'web')
|
|
if (
|
|
!valueArgPartialConfig ||
|
|
shouldHideOnThisLevel ||
|
|
shouldHideOnThisPlatform
|
|
)
|
|
return null
|
|
|
|
let valueArgConfig = {
|
|
...valueArgPartialConfig,
|
|
required: true,
|
|
} as CommandArgumentConfig<S['default']>
|
|
|
|
// If the setting is a boolean, we coerce it into an options input type
|
|
if (valueArgConfig.inputType === 'boolean') {
|
|
valueArgConfig = {
|
|
...valueArgConfig,
|
|
inputType: 'options',
|
|
options: (cmdBarContext, machineContext) => {
|
|
const setting = getPropertyByPath(
|
|
machineContext,
|
|
type
|
|
) as Setting<boolean>
|
|
const level = cmdBarContext.argumentsToSubmit.level as SettingsLevel
|
|
const isCurrent =
|
|
setting[level] === undefined
|
|
? setting.getFallback(level) === true
|
|
: setting[level] === true
|
|
return [
|
|
{ name: 'On', value: true, isCurrent },
|
|
{ name: 'Off', value: false, isCurrent: !isCurrent },
|
|
]
|
|
},
|
|
}
|
|
}
|
|
|
|
// @ts-ignore - TODO figure out this typing for valueArgConfig
|
|
const valueArg = buildCommandArgument(valueArgConfig, context, actor)
|
|
|
|
const command: Command = {
|
|
name: type,
|
|
displayName: `Settings · ${decamelize(type.replaceAll('.', ' · '), {
|
|
separator: ' ',
|
|
})}`,
|
|
description: settingConfig.description,
|
|
groupId: 'settings',
|
|
icon: 'settings',
|
|
needsReview: false,
|
|
onSubmit: (data) => {
|
|
if (data !== undefined && data !== null) {
|
|
send({ type: `set.${type}`, data })
|
|
} else {
|
|
send({ type })
|
|
}
|
|
},
|
|
args: {
|
|
level: levelArgConfig(
|
|
actor,
|
|
isProjectAvailable,
|
|
settingConfig.hideOnLevel
|
|
),
|
|
value: valueArg,
|
|
},
|
|
}
|
|
|
|
return command
|
|
}
|