Skip to content

Commit

Permalink
refactor: un-thunk keyboard events
Browse files Browse the repository at this point in the history
  • Loading branch information
will-stone committed Jan 2, 2022
1 parent 69a873e commit e2dfe0e
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 85 deletions.
60 changes: 51 additions & 9 deletions src/main/state/middleware.action-hub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ import { B_URL, ISSUES_URL } from '../../config/CONSTANTS'
import {
clickedApp,
clickedUrlBar,
pressedAppKey,
pressedCopyKey,
pressedEscapeKey,
pressedKey,
startedPicker,
} from '../../renderers/picker/state/actions'
import {
Expand Down Expand Up @@ -103,7 +101,12 @@ export const actionHubMiddleware =
}

// Copy to clipboard
else if (clickedUrlBar.match(action) || pressedCopyKey.match(action)) {
else if (
clickedUrlBar.match(action) ||
(pressedKey.match(action) &&
action.payload.metaKey &&
action.payload.virtualKey === 'c')
) {
if (nextState.data.url) {
copyToClipboard(nextState.data.url)
pickerWindow?.hide()
Expand Down Expand Up @@ -147,8 +150,8 @@ export const actionHubMiddleware =
getInstalledAppIds()
}

// Open app
else if (pressedAppKey.match(action) || clickedApp.match(action)) {
// Clicked app
else if (clickedApp.match(action)) {
const { appId, url = '', isAlt, isShift } = action.payload

// Bail if app's bundle id is missing
Expand Down Expand Up @@ -180,9 +183,48 @@ export const actionHubMiddleware =
pickerWindow?.hide()
}

// Escape key
else if (pressedEscapeKey.match(action)) {
pickerWindow?.hide()
// Pressed key in picker window
else if (pressedKey.match(action)) {
// Escape key
if (action.payload.physicalKey === 'Escape') {
pickerWindow?.hide()
}
// App hotkey
else {
const foundApp = nextState.storage.apps.find(
(storedApp) => storedApp.hotCode === action.payload.physicalKey,
)

if (!action.payload.metaKey && foundApp) {
const selectedApp = apps[foundApp.id]

const processedUrlTemplate =
'urlTemplate' in selectedApp
? selectedApp.urlTemplate.replace(
/\{\{URL\}\}/u,
nextState.data.url,
)
: nextState.data.url

const openArguments: string[] = [
'-b',
foundApp.id,
action.payload.altKey ? '--background' : [],
action.payload.shiftKey && 'privateArg' in selectedApp
? ['--new', '--args', selectedApp.privateArg]
: [],
// In order for private/incognito mode to work the URL needs to be passed
// in last, _after_ the respective app.privateArg flag
processedUrlTemplate,
]
.filter(Boolean)
.flat()

execFile('open', openArguments)

pickerWindow?.hide()
}
}
}

// Open URL
Expand Down
68 changes: 14 additions & 54 deletions src/renderers/picker/components/hooks/use-keyboard-events.ts
Original file line number Diff line number Diff line change
@@ -1,69 +1,29 @@
import { useEffect } from 'react'
import { useDispatch } from 'react-redux'

import type { AppThunk } from '../../../../shared/state/reducer.root'
import {
pressedAppKey,
pressedBackspaceKey,
pressedCopyKey,
pressedEscapeKey,
} from '../../state/actions'
import { pressedKey } from '../../state/actions'

const keyboardEvent =
(event: KeyboardEvent): AppThunk =>
(dispatch, getState) => {
const { url } = getState().data
const { apps } = getState().storage

const virtualKey = event.key.toLowerCase()
const physicalKey = event.code

// Escape
if (virtualKey === 'escape') {
dispatch(pressedEscapeKey())
}

// Backspace
if (virtualKey === 'backspace') {
event.preventDefault()
dispatch(pressedBackspaceKey())
}

// ⌘C
else if (event.metaKey && virtualKey === 'c') {
event.preventDefault()

if (url) {
dispatch(pressedCopyKey(url))
}
}
export const useKeyboardEvents = (): void => {
const dispatch = useDispatch()

// App hotkey
else {
const foundApp = apps.find((app) => app.hotCode === physicalKey)
useEffect(() => {
const handler = (event: KeyboardEvent) => {
// Allow these keys to function as normal
const ignoredKeys = ['Tab', 'Enter', 'Space']

if (!event.metaKey && foundApp) {
if (!ignoredKeys.includes(event.code)) {
event.preventDefault()

dispatch(
pressedAppKey({
url,
appId: foundApp.id,
isAlt: event.altKey,
isShift: event.shiftKey,
pressedKey({
virtualKey: event.key.toLowerCase(),
physicalKey: event.code,
metaKey: event.metaKey,
altKey: event.altKey,
shiftKey: event.shiftKey,
}),
)
}
}
}

export const useKeyboardEvents = (): void => {
const dispatch = useDispatch()

useEffect(() => {
const handler = (event: KeyboardEvent) => {
dispatch(keyboardEvent(event))
}

document.addEventListener('keydown', handler)

Expand Down
24 changes: 13 additions & 11 deletions src/renderers/picker/components/organisms/apps.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { defaultData } from '../../../../shared/state/reducer.data'
import { addChannelToAction } from '../../../../shared/utils/add-channel-to-action'
import { reorderedApp } from '../../../prefs/state/actions'
import { customWindow } from '../../../shared/custom.window'
import { clickedApp, pressedAppKey } from '../../state/actions'
import { clickedApp, pressedKey } from '../../state/actions'
import Wrapper from '../_bootstrap'

const originalNavigator = cloneDeep(customWindow.navigator)
Expand Down Expand Up @@ -144,11 +144,12 @@ test('use hotkey', () => {
expect(electron.ipcRenderer.send).toHaveBeenCalledWith(
Channel.PICKER,
addChannelToAction(
pressedAppKey({
url,
appId: 'com.apple.Safari',
isAlt: false,
isShift: false,
pressedKey({
virtualKey: 's',
physicalKey: 'KeyS',
altKey: false,
shiftKey: false,
metaKey: false,
}),
Channel.PICKER,
),
Expand Down Expand Up @@ -187,11 +188,12 @@ test('use hotkey with alt', () => {
expect(electron.ipcRenderer.send).toHaveBeenCalledWith(
Channel.PICKER,
addChannelToAction(
pressedAppKey({
url,
appId: 'com.apple.Safari',
isAlt: true,
isShift: false,
pressedKey({
virtualKey: 's',
physicalKey: 'KeyS',
altKey: true,
shiftKey: false,
metaKey: false,
}),
Channel.PICKER,
),
Expand Down
16 changes: 8 additions & 8 deletions src/renderers/picker/state/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@ const startedPicker = cA('started')

const clickedApp = cA<OpenAppArguments>('app/clicked')

const pressedEscapeKey = cA('escape-key/pressed')
const pressedBackspaceKey = cA('backspace-key/pressed')
const pressedCopyKey = cA<string>('copy-key/pressed')
const pressedAppKey = cA<OpenAppArguments>('app-key/pressed')
const pressedKey = cA<{
virtualKey: string
physicalKey: string
metaKey: boolean
altKey: boolean
shiftKey: boolean
}>('key/pressed')

const clickedUrlBar = cA('url-bar/clicked')

Expand All @@ -29,9 +32,6 @@ export {
clickedDonate,
clickedMaybeLater,
clickedUrlBar,
pressedAppKey,
pressedBackspaceKey,
pressedCopyKey,
pressedEscapeKey,
pressedKey,
startedPicker,
}
9 changes: 6 additions & 3 deletions src/shared/state/reducer.data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
} from '../../main/state/actions'
import {
clickedDonate,
pressedBackspaceKey,
pressedKey,
startedPicker,
} from '../../renderers/picker/state/actions'
import {
Expand Down Expand Up @@ -65,8 +65,11 @@ export const data = createReducer<Data>(defaultData, (builder) =>
state.prefsStarted = true
})

.addCase(pressedBackspaceKey, (state) => {
state.url = backspaceUrlParse(state.url)
// Pressed key in picker window
.addCase(pressedKey, (state, action) => {
if (action.payload.physicalKey === 'Backspace') {
state.url = backspaceUrlParse(state.url)
}
})

.addCase(gotDefaultBrowserStatus, (state, action) => {
Expand Down

0 comments on commit e2dfe0e

Please sign in to comment.