* Split ModelingSidebar out into own component * Consolidate all ModelingPane components and config * Make ModelingSidebar a directory of components and config * Remove unused components * Proper pane styling * Make tooltip configurable to visually appear on hover only * Remove debug panel from App * Fix current tests * Rename to more intuitive names * Fix useEffect loop bug with showDebugPanel * Fix snapshot tests * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu) * Rerun CI * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu) * Merge branch 'main' into franknoirot/sidebar * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu) * Rerun CI * Maybe some flakiness in the validation initScripts? * Avoid test flakiness by waiting for more signals that loading is completed * Don't assert, just wait for the element to be enabled * Don't let users accidentally click the gap between the pane and the side of the window * Firm up extrude from command bar test * Get rid of unused imports * Add setting to disable blinking cursor (#2065) * Add support for "current" marker in command bar for boolean settings * Add a cursorBlinking setting * Rename setting to blinkingCursor, honor it in the UI * Fix scroll layout bug in settings modal * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu) * Rerun CI * CSS tweaks * Allow settings hotkey within KclEditorPane * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu) --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * Rerun CI * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu) * Rerun CI * Ensure the KCL code panel is closed for camera movement test * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu) * Make sure that the camera position inputs are ready to be read from * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu) * Remove repeat awaits * Make camera position fields in debug pane update when the pane is initialized * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu) * Undo that CameraControls change because it made other things weird * retry fixing camera move test * Fix race condition where cam setting cam position parts were overwriting each other * Rerun CI * Rerun CI --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
149 lines
4.3 KiB
TypeScript
149 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 { AnyStateMachine, ContextFrom, InterpreterFrom } from 'xstate'
|
|
import { getPropertyByPath } from 'lib/objectPropertyByPath'
|
|
import { buildCommandArgument } from 'lib/createMachineCommand'
|
|
import decamelize from 'decamelize'
|
|
import { isTauri } from 'lib/isTauri'
|
|
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: InterpreterFrom<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: InterpreterFrom<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 &&
|
|
(isTauri()
|
|
? 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: ' ',
|
|
})}`,
|
|
ownerMachine: '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
|
|
}
|