Skip to content

Commit

Permalink
keyboardActions: Use event.preventDefault only when an action has bee…
Browse files Browse the repository at this point in the history
…n found (#9559)

* keyboardActions: Use event.preventDefault only when an action has been found

... and handle multiple registered actions for bound keys

* Simplify code for event listener addition/removal

* Use useEventListener from @vueuse

* Fix lint

* Register keyboardActions globally to avoid focus issues

* Disable shortcut handling in certain contexts
  • Loading branch information
dschmidt authored Aug 10, 2023
1 parent 0da2ebb commit 65831b6
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 38 deletions.
2 changes: 1 addition & 1 deletion packages/web-app-files/src/components/Search/List.vue
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ export default defineComponent({
const resourcesView = useResourcesViewDefaults<Resource, any, any[]>()
const keyActions = useKeyboardActions('files-view')
const keyActions = useKeyboardActions()
useKeyboardTableNavigation(keyActions, resourcesView.paginatedResources)
useKeyboardTableMouseActions(keyActions)
useKeyboardTableActions(keyActions)
Expand Down
2 changes: 1 addition & 1 deletion packages/web-app-files/src/components/SideBar/SideBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
:loading="loading"
:is-header-compact="!!loadedResource"
v-bind="$attrs"
data-custom-key-bindings="true"
data-custom-key-bindings-disabled="true"
@before-unmount="destroySideBar"
@mounted="focusSideBar"
@file-changed="focusSideBar"
Expand Down
2 changes: 1 addition & 1 deletion packages/web-app-files/src/views/spaces/GenericSpace.vue
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,7 @@ export default defineComponent({
const resourcesViewDefaults = useResourcesViewDefaults<Resource, any, any[]>()
const keyActions = useKeyboardActions('files-view')
const keyActions = useKeyboardActions()
useKeyboardTableNavigation(keyActions, resourcesViewDefaults.paginatedResources)
useKeyboardTableMouseActions(keyActions)
useKeyboardTableSpaceActions(keyActions, props.space)
Expand Down
2 changes: 1 addition & 1 deletion packages/web-app-search/src/portals/SearchBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
id="files-global-search"
ref="searchBar"
class="oc-flex"
data-custom-key-bindings="true"
data-custom-key-bindings-disabled="true"
>
<oc-search-bar
id="files-global-search-bar"
Expand Down
3 changes: 2 additions & 1 deletion packages/web-pkg/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
"directory": "packages/web-pkg"
},
"peerDependencies": {
"@microsoft/fetch-event-source": "^2.0.1",
"@casl/ability": "^6.3.3",
"@casl/vue": "^2.2.1",
"@microsoft/fetch-event-source": "^2.0.1",
"@vueuse/core": "^10.0.0",
"axios": "^0.27.2 || ^1.0.0",
"design-system": "workspace:@ownclouders/design-system@*",
"filesize": "^9.0.11",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { onBeforeUnmount, onMounted, Ref, ref } from 'vue'
import { Ref, ref, unref } from 'vue'
import { useEventListener } from '@vueuse/core'
import * as uuid from 'uuid'

export enum Key {
C = 'c',
V = 'v',
X = 'x',
A = 'a',
S = 's',
Space = ' ',
ArrowUp = 'ArrowUp',
ArrowDown = 'ArrowDown',
Expand All @@ -32,24 +34,59 @@ export interface KeyboardAction {
callback: (event: KeyboardEvent) => void
}

export const useKeyboardActions = (keyBindOnElementId: string | null = null): KeyboardActions => {
const areCustomKeyBindingsDisabled = () => {
const activeElementTag = document.activeElement.tagName
const type = document.activeElement.getAttribute('type')
if (
['textarea', 'input', 'select'].includes(activeElementTag.toLowerCase()) &&
type !== 'checkbox'
) {
return true
}
const closestSelectionEl = window.getSelection().focusNode as HTMLElement
if (!closestSelectionEl) {
return false
}
let customKeyBindings
try {
customKeyBindings = closestSelectionEl?.closest("[data-custom-key-bindings-disabled='true']")
} catch {
customKeyBindings = closestSelectionEl?.parentElement.closest(
"[data-custom-key-bindings-disabled='true']"
)
}
if (customKeyBindings) {
return true
}

const isTextSelected = window.getSelection().type === 'Range'
return isTextSelected
}

export const useKeyboardActions = (): KeyboardActions => {
const actions = ref<Array<KeyboardAction>>([])
const selectionCursor = ref(0)

const listener = (event: KeyboardEvent): void => {
event.preventDefault()
if (areCustomKeyBindingsDisabled()) {
return
}

const { key, ctrlKey, metaKey, shiftKey } = event
let modifier = null
if (metaKey || ctrlKey) {
modifier = ModifierKey.Ctrl
} else if (shiftKey) {
modifier = ModifierKey.Shift
}
const action = actions.value.find((action) => {
return action.primary === key && action.modifier === modifier
})
if (action) {
action.callback(event)
}
unref(actions)
.filter((action) => {
return action.primary === key && action.modifier === modifier
})
.forEach((action) => {
event.preventDefault()
action.callback(event)
})
}
const bindKeyAction = (
keys: { primary: Key; modifier?: ModifierKey },
Expand All @@ -73,25 +110,7 @@ export const useKeyboardActions = (keyBindOnElementId: string | null = null): Ke
selectionCursor.value = 0
}

onMounted(() => {
let element = null
if (keyBindOnElementId) {
element = document.getElementById(keyBindOnElementId)
}
element
? element.addEventListener('keydown', listener)
: document.addEventListener('keydown', listener)
})

onBeforeUnmount(() => {
let element = null
if (keyBindOnElementId) {
element = document.getElementById(keyBindOnElementId)
}
element
? element.removeEventListener('keydown', listener)
: document.removeEventListener('keydown', listener)
})
useEventListener(document, 'keydown', listener)

return {
actions,
Expand Down
17 changes: 12 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 65831b6

Please sign in to comment.