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:
andrewwallacespeckle
2024-07-10 11:11:20 +01:00
committed by GitHub
parent 0b2ca9a515
commit d12e80035d
2 changed files with 80 additions and 62 deletions
@@ -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)
}
/**