fix(fe2): keyboard shortcuts in viewer don't work (#2389)
* feat: use shift for shortcuts. Swap onKeyStroke for useMagicKeys * refactor: simplify control shortcuts * Revert changes to input.ts * refactor: Make more DRY * Revert "refactor: Make more DRY" This reverts commit a508fcfb9d2fef0cd2635911bc57410989166a50. * Revert "Revert changes to input.ts" This reverts commit c47300d0104d09f9fa0ae9bc9e86e994f0a46206. * Revert "refactor: simplify control shortcuts" This reverts commit a867d6e34d06a7a6436ff4bdb6c4a7db94d3ca21. * Fix broken space * Refactor Viewer Controls and Keyboard Shortcuts * Fix keyboard shortcut mapping to handle string keys correctly * refactor: string enum * remove filters shortcut
This commit is contained in:
committed by
GitHub
parent
0b2ca9a515
commit
d12e80035d
@@ -275,6 +275,16 @@ import { useFunctionRunsStatusSummary } from '~/lib/automate/composables/runStat
|
||||
|
||||
const isGendoEnabled = useIsGendoModuleEnabled()
|
||||
|
||||
enum ViewerKeyboardActions {
|
||||
ToggleModels = 'ToggleModels',
|
||||
ToggleExplorer = 'ToggleExplorer',
|
||||
ToggleDiscussions = 'ToggleDiscussions',
|
||||
ToggleMeasurements = 'ToggleMeasurements',
|
||||
ToggleProjection = 'ToggleProjection',
|
||||
ToggleSectionBox = 'ToggleSectionBox',
|
||||
ZoomExtentsOrSelection = 'ZoomExtentsOrSelection'
|
||||
}
|
||||
|
||||
const width = ref(360)
|
||||
const scrollableControlsContainer = ref(null as Nullable<HTMLDivElement>)
|
||||
|
||||
@@ -364,28 +374,72 @@ const {
|
||||
diff: { enabled }
|
||||
} = useInjectedViewerInterfaceState()
|
||||
|
||||
const map: Record<ViewerKeyboardActions, [ModifierKeys[], string]> = {
|
||||
[ViewerKeyboardActions.ToggleModels]: [[ModifierKeys.Shift], 'm'],
|
||||
[ViewerKeyboardActions.ToggleExplorer]: [[ModifierKeys.Shift], 'e'],
|
||||
[ViewerKeyboardActions.ToggleDiscussions]: [[ModifierKeys.Shift], 't'],
|
||||
[ViewerKeyboardActions.ToggleMeasurements]: [[ModifierKeys.Shift], 'r'],
|
||||
[ViewerKeyboardActions.ToggleProjection]: [[ModifierKeys.Shift], 'p'],
|
||||
[ViewerKeyboardActions.ToggleSectionBox]: [[ModifierKeys.Shift], 'b'],
|
||||
[ViewerKeyboardActions.ZoomExtentsOrSelection]: [[ModifierKeys.Shift], 'space']
|
||||
}
|
||||
|
||||
const getShortcutTitle = (action: ViewerKeyboardActions) =>
|
||||
`(${getKeyboardShortcutTitle([...map[action][0], map[action][1]])})`
|
||||
|
||||
const modelsShortcut = ref(
|
||||
`Models (${getKeyboardShortcutTitle([ModifierKeys.AltOrOpt, 'm'])})`
|
||||
`Models ${getShortcutTitle(ViewerKeyboardActions.ToggleModels)}`
|
||||
)
|
||||
const explorerShortcut = ref(
|
||||
`Scene Explorer (${getKeyboardShortcutTitle([ModifierKeys.AltOrOpt, 'e'])})`
|
||||
`Scene Explorer ${getShortcutTitle(ViewerKeyboardActions.ToggleExplorer)}`
|
||||
)
|
||||
const discussionsShortcut = ref(
|
||||
`Discussions (${getKeyboardShortcutTitle([ModifierKeys.AltOrOpt, 't'])})`
|
||||
`Discussions ${getShortcutTitle(ViewerKeyboardActions.ToggleDiscussions)}`
|
||||
)
|
||||
const zoomExtentsShortcut = ref(
|
||||
`Fit to screen (${getKeyboardShortcutTitle([ModifierKeys.AltOrOpt, 'Space'])})`
|
||||
`Fit to screen ${getShortcutTitle(ViewerKeyboardActions.ZoomExtentsOrSelection)}`
|
||||
)
|
||||
const projectionShortcut = ref(
|
||||
`Projection (${getKeyboardShortcutTitle([ModifierKeys.AltOrOpt, 'p'])})`
|
||||
`Projection ${getShortcutTitle(ViewerKeyboardActions.ToggleProjection)}`
|
||||
)
|
||||
const sectionBoxShortcut = ref(
|
||||
`Section Box (${getKeyboardShortcutTitle([ModifierKeys.AltOrOpt, 'b'])})`
|
||||
`Section Box ${getShortcutTitle(ViewerKeyboardActions.ToggleSectionBox)}`
|
||||
)
|
||||
const measureShortcut = ref(
|
||||
`Measure Mode (${getKeyboardShortcutTitle([ModifierKeys.AltOrOpt, 'd'])})`
|
||||
`Measure Mode ${getShortcutTitle(ViewerKeyboardActions.ToggleMeasurements)}`
|
||||
)
|
||||
|
||||
const handleKeyboardAction = (action: ViewerKeyboardActions) => {
|
||||
switch (action) {
|
||||
case ViewerKeyboardActions.ToggleModels:
|
||||
toggleActiveControl('models')
|
||||
break
|
||||
case ViewerKeyboardActions.ToggleExplorer:
|
||||
toggleActiveControl('explorer')
|
||||
break
|
||||
case ViewerKeyboardActions.ToggleDiscussions:
|
||||
toggleActiveControl('discussions')
|
||||
break
|
||||
case ViewerKeyboardActions.ToggleMeasurements:
|
||||
toggleMeasurements()
|
||||
break
|
||||
case ViewerKeyboardActions.ToggleProjection:
|
||||
trackAndtoggleProjection()
|
||||
break
|
||||
case ViewerKeyboardActions.ToggleSectionBox:
|
||||
toggleSectionBox()
|
||||
break
|
||||
case ViewerKeyboardActions.ZoomExtentsOrSelection:
|
||||
trackAndzoomExtentsOrSelection()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
Object.entries(map).forEach(([actionKey, [modifiers, key]]) => {
|
||||
const action = actionKey as ViewerKeyboardActions
|
||||
onKeyboardShortcut(modifiers, key, () => handleKeyboardAction(action))
|
||||
})
|
||||
|
||||
const { isSmallerOrEqualSm } = useIsSmallerOrEqualThanBreakpoint()
|
||||
|
||||
const toggleActiveControl = (control: ActiveControl) => {
|
||||
@@ -396,33 +450,6 @@ const toggleActiveControl = (control: ActiveControl) => {
|
||||
activeControl.value = activeControl.value === control ? 'none' : control
|
||||
}
|
||||
|
||||
onKeyboardShortcut([ModifierKeys.AltOrOpt], 'm', () => {
|
||||
toggleActiveControl('models')
|
||||
})
|
||||
onKeyboardShortcut([ModifierKeys.AltOrOpt], 'e', () => {
|
||||
toggleActiveControl('explorer')
|
||||
})
|
||||
onKeyboardShortcut([ModifierKeys.AltOrOpt], 'f', () => {
|
||||
toggleActiveControl('filters')
|
||||
})
|
||||
onKeyboardShortcut([ModifierKeys.AltOrOpt], ['t'], () => {
|
||||
toggleActiveControl('discussions')
|
||||
})
|
||||
onKeyboardShortcut([ModifierKeys.AltOrOpt], 'd', () => {
|
||||
toggleActiveControl('measurements')
|
||||
})
|
||||
|
||||
// Viewer actions kbd shortcuts
|
||||
onKeyboardShortcut([ModifierKeys.AltOrOpt], ' ', () => {
|
||||
trackAndzoomExtentsOrSelection()
|
||||
})
|
||||
onKeyboardShortcut([ModifierKeys.AltOrOpt], 'p', () => {
|
||||
toggleProjection()
|
||||
})
|
||||
onKeyboardShortcut([ModifierKeys.AltOrOpt], 'b', () => {
|
||||
toggleSectionBox()
|
||||
})
|
||||
|
||||
const mp = useMixpanel()
|
||||
watch(activeControl, (newVal) => {
|
||||
mp.track('Viewer Action', { type: 'action', name: 'controls-toggle', action: newVal })
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { onKeyDown } from '@vueuse/core'
|
||||
import { useMagicKeys, whenever } from '@vueuse/core'
|
||||
import { OperatingSystem } from '@speckle/shared'
|
||||
import { clientOs, ModifierKeys } from '~~/src/helpers/form/input'
|
||||
import { computed, ref } from 'vue'
|
||||
@@ -9,36 +9,27 @@ import type { Ref } from 'vue'
|
||||
*/
|
||||
export function onKeyboardShortcut(
|
||||
modifiers: ModifierKeys[],
|
||||
...args: Parameters<typeof onKeyDown>
|
||||
key: string,
|
||||
callback: () => void
|
||||
) {
|
||||
onKeyDown(
|
||||
args[0],
|
||||
(e) => {
|
||||
const isAltOrOpt = e.getModifierState('Alt')
|
||||
const isCtrlOrCmd =
|
||||
clientOs === OperatingSystem.Mac
|
||||
? e.getModifierState('Meta')
|
||||
: e.getModifierState('Control')
|
||||
const isShift = e.getModifierState('Shift')
|
||||
const keys = useMagicKeys()
|
||||
|
||||
for (const modifier of modifiers) {
|
||||
switch (modifier) {
|
||||
case ModifierKeys.CtrlOrCmd:
|
||||
if (!isCtrlOrCmd) return
|
||||
break
|
||||
case ModifierKeys.AltOrOpt:
|
||||
if (!isAltOrOpt) return
|
||||
break
|
||||
case ModifierKeys.Shift:
|
||||
if (!isShift) return
|
||||
break
|
||||
}
|
||||
}
|
||||
const modifierKeys = modifiers.map((modifier) => {
|
||||
switch (modifier) {
|
||||
case ModifierKeys.CtrlOrCmd:
|
||||
return clientOs === OperatingSystem.Mac ? 'Meta' : 'Control'
|
||||
case ModifierKeys.AltOrOpt:
|
||||
return 'Alt'
|
||||
case ModifierKeys.Shift:
|
||||
return 'Shift'
|
||||
default:
|
||||
return ''
|
||||
}
|
||||
})
|
||||
|
||||
args[1](e)
|
||||
},
|
||||
args[2]
|
||||
)
|
||||
const keyCombination = `${modifierKeys.join('+')}+${key}`
|
||||
|
||||
whenever(keys[keyCombination], callback)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user