Make commands disable, not unregister, based on their machineActor (#5070)
* Make "Find and select command" global to commandBarMachine * Make commands not removed based on their actor state, only disabled * Sort commands better in CommandComboBox * Break out sort logic, add a few unit tests * Fix missed name change * Needed to make one more change from source branch: since `optionsFromContext` now only gets fired once, I/O-based options need to use the `options` config instead. --------- Co-authored-by: 49fl <ircsurfer33@gmail.com>
This commit is contained in:
@ -4,6 +4,8 @@ import { useCommandsContext } from 'hooks/useCommandsContext'
|
||||
import { Command } from 'lib/commandTypes'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { CustomIcon } from './CustomIcon'
|
||||
import { getActorNextEvents } from 'lib/utils'
|
||||
import { sortCommands } from 'lib/commandUtils'
|
||||
|
||||
function CommandComboBox({
|
||||
options,
|
||||
@ -18,8 +20,16 @@ function CommandComboBox({
|
||||
|
||||
const defaultOption =
|
||||
options.find((o) => 'isCurrent' in o && o.isCurrent) || null
|
||||
// sort disabled commands to the bottom
|
||||
const sortedOptions = options
|
||||
.map((command) => ({
|
||||
command,
|
||||
disabled: optionIsDisabled(command),
|
||||
}))
|
||||
.sort(sortCommands)
|
||||
.map(({ command }) => command)
|
||||
|
||||
const fuse = new Fuse(options, {
|
||||
const fuse = new Fuse(sortedOptions, {
|
||||
keys: ['displayName', 'name', 'description'],
|
||||
threshold: 0.3,
|
||||
ignoreLocation: true,
|
||||
@ -27,7 +37,7 @@ function CommandComboBox({
|
||||
|
||||
useEffect(() => {
|
||||
const results = fuse.search(query).map((result) => result.item)
|
||||
setFilteredOptions(query.length > 0 ? results : options)
|
||||
setFilteredOptions(query.length > 0 ? results : sortedOptions)
|
||||
}, [query])
|
||||
|
||||
function handleSelection(command: Command) {
|
||||
@ -73,7 +83,8 @@ function CommandComboBox({
|
||||
<Combobox.Option
|
||||
key={option.groupId + option.name + (option.displayName || '')}
|
||||
value={option}
|
||||
className="flex items-center gap-4 px-4 py-1.5 first:mt-2 last:mb-2 ui-active:bg-primary/10 dark:ui-active:bg-chalkboard-90"
|
||||
className="flex items-center gap-4 px-4 py-1.5 first:mt-2 last:mb-2 ui-active:bg-primary/10 dark:ui-active:bg-chalkboard-90 ui-disabled:!text-chalkboard-50"
|
||||
disabled={optionIsDisabled(option)}
|
||||
>
|
||||
{'icon' in option && option.icon && (
|
||||
<CustomIcon name={option.icon} className="w-5 h-5" />
|
||||
@ -96,3 +107,11 @@ function CommandComboBox({
|
||||
}
|
||||
|
||||
export default CommandComboBox
|
||||
|
||||
function optionIsDisabled(option: Command): boolean {
|
||||
return (
|
||||
'machineActor' in option &&
|
||||
option.machineActor !== undefined &&
|
||||
!getActorNextEvents(option.machineActor.getSnapshot()).includes(option.name)
|
||||
)
|
||||
}
|
||||
|
Reference in New Issue
Block a user