Skip to content

Commit

Permalink
Replace the Meta key with CommandOrControl in shortcuts for better in…
Browse files Browse the repository at this point in the history
…teropability with Windows

Signed-off-by: Axel Boberg <[email protected]>
  • Loading branch information
axelboberg committed Feb 18, 2024
1 parent 3e37d7f commit 88eb160
Show file tree
Hide file tree
Showing 10 changed files with 78 additions and 43 deletions.
4 changes: 4 additions & 0 deletions api/events.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,10 @@ function off (event, handler) {
if (handlers.length === 0) {
localHandlers.delete(event)

if (!remoteHandlers.has(event)) {
return
}

/*
Remove the command completely as we don't
have any handlers for this event anymore
Expand Down
26 changes: 26 additions & 0 deletions app/components/Frame/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,32 @@ export function Frame ({ src, api, doUpdateTheme = 1 }) {
setup()
}, [src, api, wrapperRef.current])

/*
Update the bridgeFrameHasFocus property
on the frame's window object whenever
the frame changes focus
*/
React.useEffect(() => {
const contentWindow = frameRef.current?.contentWindow
if (!contentWindow) {
return
}
function onFocus () {
contentWindow.bridgeFrameHasFocus = true
}
contentWindow.addEventListener('focus', onFocus)

function onBlur () {
contentWindow.bridgeFrameHasFocus = false
}
contentWindow.addEventListener('blur', onBlur)

return () => {
contentWindow.removeEventListener('focus', onFocus)
contentWindow.removeEventListener('blur', onBlur)
}
}, [frameRef.current?.contentWindow])

/*
Clean up all event listeners
added by this frame
Expand Down
2 changes: 2 additions & 0 deletions app/components/FrameComponent/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -195,11 +195,13 @@ export function FrameComponent ({ data, onUpdate }) {
}
function onFocus () {
setHasFocus(true)
contentWindow.bridgeFrameHasFocus = true
}
contentWindow.addEventListener('focus', onFocus)

function onBlur () {
setHasFocus(false)
contentWindow.bridgeFrameHasFocus = false
}
contentWindow.addEventListener('blur', onBlur)

Expand Down
26 changes: 14 additions & 12 deletions app/utils/shortcuts.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@

import * as api from '../api'

const TRANSLATIONS = {
Meta: () => window.APP.platform === 'darwin' ? 'CommandOrControl' : 'Meta',
Control: () => 'CommandOrControl'
}

/**
* A set for keeping track of the
* currently pressed keys
Expand Down Expand Up @@ -57,15 +62,7 @@ function normalize (key) {
return key
}

async function dispatchShortcutEvent (target, id) {
/* const event = new window.CustomEvent('shortcut', {
detail: {
id: id
},
bubbles: true
})
target.dispatchEvent(event) */

async function dispatchShortcutEvent (id) {
const bridge = await api.load()
bridge.events.emitLocally('shortcut', id)
}
Expand All @@ -84,7 +81,12 @@ export async function registerKeyDown (e) {
const bridge = await api.load()
const shortcuts = await bridge.shortcuts.getShortcuts()

keys.add(normalize(e.key))
const normalized = normalize(e.key)
const translated = TRANSLATIONS[normalized]
? TRANSLATIONS[normalized]()
: normalized

keys.add(translated)

const matchedShortcuts = shortcuts.filter(shortcut => {
for (const trigger of shortcut.trigger) {
Expand All @@ -100,7 +102,7 @@ export async function registerKeyDown (e) {
}

for (const shortcut of matchedShortcuts) {
dispatchShortcutEvent(e.target, shortcut.id)
dispatchShortcutEvent(shortcut.id)
}

/*
Expand All @@ -126,6 +128,6 @@ export function registerKeyUp (e) {
const identity = await bridge.client.awaitIdentity()

bridge.events.on(`local.${identity}.shortcut`, shortcut => {
dispatchShortcutEvent(document.activeElement, shortcut)
dispatchShortcutEvent(shortcut)
})
})()
9 changes: 2 additions & 7 deletions docs/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -347,16 +347,11 @@ Keyboard shortcuts SHOULD be registered with the API to give the user an index o
Shortcut triggers can be overridden by the user in the settings panel.

### Listening to keyboard shortcuts
Keyboard shortcuts are emitted using **DOM events** and **not `bridge.events`**.
This is because keyboard shortcuts are only an alias for keyboard events and should be handled locally.

Listen to a registered shortcut by subscribing to the `shortcut` DOM event, such as:
Listen to a registered shortcut by subscribing to the `shortcut` event, as such:

```javascript
import bridge from 'bridge'

const el = document.createElement('div')

bridge.events.on('shortcut', id => {
console.log('Shortcut was triggered with id:', id)
// React to action
Expand Down Expand Up @@ -402,6 +397,6 @@ import bridge from 'bridge'
bridge.shortcuts.registerShortcut({
id: 'myPlugin.shortcuts.myShortcut',
description: 'Trigger my command',
trigger: ['Shift', 'Meta', 'A']
trigger: ['Shift', 'CommandOrControl', 'A']
})
```
25 changes: 5 additions & 20 deletions lib/electron.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@ const MENU_TEMPLATE = [
{
label: 'Save',
accelerator: 'CommandOrControl+S',
click: () => save(BrowserWindow.getFocusedWindow())
click: (_, window) => save(window)
},
{
label: 'Save as',
accelerator: 'CommandOrControl+Shift+S',
click: () => saveAs(BrowserWindow.getFocusedWindow())
click: (_, window) => saveAs(window)
}
]
},
Expand All @@ -73,9 +73,9 @@ const MENU_TEMPLATE = [
{ label: 'Undo', accelerator: 'CmdOrCtrl+Z', selector: 'undo:' },
{ label: 'Redo', accelerator: 'Shift+CmdOrCtrl+Z', selector: 'redo:' },
{ type: 'separator' },
{ label: 'Cut', accelerator: 'CmdOrCtrl+X', selector: 'cut:', click: () => performShortcut(BrowserWindow.getFocusedWindow(), 'cut') },
{ label: 'Copy', accelerator: 'CmdOrCtrl+C', selector: 'copy:', click: () => performShortcut(BrowserWindow.getFocusedWindow(), 'copy') },
{ label: 'Paste', accelerator: 'CmdOrCtrl+V', selector: 'paste:', click: () => performShortcut(BrowserWindow.getFocusedWindow(), 'paste') },
{ label: 'Cut', accelerator: 'CmdOrCtrl+X', selector: 'cut:' },
{ label: 'Copy', accelerator: 'CmdOrCtrl+C', selector: 'copy:' },
{ label: 'Paste', accelerator: 'CmdOrCtrl+V', selector: 'paste:' },
{ label: 'Select All', accelerator: 'CmdOrCtrl+A', selector: 'selectAll:' }
]
},
Expand Down Expand Up @@ -281,21 +281,6 @@ async function openWithDialog () {
open(filePaths[0])
}

/**
* Perform a shortcut on a
* window's persistent clients
* (a.k.a. those running in Electron)
* @param { BrowserWindow } window
* @param { String } shortcut
*/
async function performShortcut (window, shortcut) {
const workspace = await electronWindowManager.getWorkspaceFromWindow(window)
const connections = workspace.getConnections()
const persistentConnection = connections.find(({ isPersistent }) => isPersistent)

workspace.api.events.emit(`local.${persistentConnection.id}.shortcut`, shortcut)
}

/**
* Open a project file in a window
* @param { String } filePath
Expand Down
3 changes: 2 additions & 1 deletion lib/schemas/shortcuts.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@
"ArrowUp",
"ArrowDown",
"ArrowLeft",
"ArrowRight"
"ArrowRight",
"CommandOrControl"
]
}
}
Expand Down
18 changes: 18 additions & 0 deletions plugins/rundown/app/views/Rundown.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,30 @@ export function Rundown () {
}
}

function handleSelectAll () {
const elements = elRef.current.querySelectorAll('[data-item-id]')
const ids = []

for (const element of elements) {
ids.push(element.dataset.itemId)
}

bridge.client.setSelection(ids)
}

React.useEffect(() => {
function onShortcut (shortcut) {
if (!window.bridgeFrameHasFocus) {
return
}

switch (shortcut) {
case 'paste':
handlePaste()
break
case 'selectAll':
handleSelectAll()
break
}
}

Expand Down
2 changes: 1 addition & 1 deletion plugins/rundown/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
},
{
"id": "bridge.rundown.select-multiple",
"trigger": ["Meta"]
"trigger": ["CommandOrControl"]
}
]
}
Expand Down
6 changes: 4 additions & 2 deletions plugins/shortcuts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@
"shortcuts": [
{
"id": "copy",
"description": "Copy selected content into the clipboard"
"description": "Copy selected content into the clipboard",
"trigger": ["CommandOrControl", "C"]
},
{
"id": "paste",
"description": "Paste the contents of the clipboard"
"description": "Paste the contents of the clipboard",
"trigger": ["CommandOrControl", "V"]
}
]
},
Expand Down

0 comments on commit 88eb160

Please sign in to comment.