Add global hotkey functionality

This commit is contained in:
Jonatan Heyman 2023-12-10 22:59:42 +01:00
parent 13afe62e11
commit 198ce3066b
4 changed files with 246 additions and 14 deletions

View File

@ -26,6 +26,8 @@ const schema = {
"showLineNumberGutter": {type: "boolean", default:true},
"showFoldGutter": {type: "boolean", default:true},
"allowBetaVersions": {type: "boolean", default: false},
"enableGlobalHotkey": {type: "boolean", default: false},
"globalHotkey": {type: "string", default: "CmdOrCtrl+Alt+H"},
},
},
@ -47,6 +49,8 @@ const defaults = {
showLineNumberGutter: true,
showFoldGutter: true,
allowBetaVersions: false,
enableGlobalHotkey: false,
globalHotkey: "CmdOrCtrl+Alt+H",
},
theme: "system",
}

View File

@ -148,8 +148,22 @@ async function createWindow() {
fixElectronCors(win)
}
function registerGlobalHotkey() {
globalShortcut.unregisterAll()
if (CONFIG.get("settings.enableGlobalHotkey")) {
try {
const ret = globalShortcut.register(CONFIG.get("settings.globalHotkey"), () => {
app.focus({steal: true})
})
} catch (error) {
console.log("Could not register global hotkey:", error)
}
}
}
app.whenReady().then(createWindow).then(async () => {
initializeAutoUpdate(win)
registerGlobalHotkey()
})
app.on('window-all-closed', () => {
@ -212,6 +226,13 @@ ipcMain.handle('settings:set', (event, settings) => {
if (settings.keymap !== CONFIG.get("settings.keymap")) {
currentKeymap = settings.keymap
}
let globalHotkeyChanged = settings.enableGlobalHotkey !== CONFIG.get("settings.enableGlobalHotkey") || settings.globalHotkey !== CONFIG.get("settings.globalHotkey")
CONFIG.set("settings", settings)
win?.webContents.send(SETTINGS_CHANGE_EVENT, settings)
if (globalHotkeyChanged) {
registerGlobalHotkey()
}
})

View File

@ -0,0 +1,171 @@
<script>
export default {
props: [
"disabled",
"modelValue",
],
emits: ["update:modelValue"],
data() {
let keys = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("")
keys = keys.concat([
"Plus",
"Space",
"Tab",
"Capslock",
"Numlock",
"Scrolllock",
"Backspace",
"Delete",
"Insert",
"Return",
"Up",
"Down",
"Left",
"Right",
"Home",
"End",
"PageUp",
"PageDown",
"Escape",
"PrintScreen",
])
for (let i=1; i<=12; i++) {
keys.push("F" + i)
}
for (let i=0; i<=9; i++) {
keys.push("num" + i)
}
keys = keys.concat(')!@#$%^&*(:;:+=<,_->.?/~`{][|\\}"'.split(""))
return {
isMac: window.heynote.platform.isMac,
cmdOrCtrl: false,
ctrl: false,
shift: false,
alt: false,
altGr: false,
super: false,
key: "",
keys: keys,
}
},
watch: {
modelValue: {
immediate: true,
handler(value) {
if (value) {
const keys = value.split("+")
this.cmdOrCtrl = keys.includes("CmdOrCtrl")
this.ctrl = keys.includes("Ctrl")
this.shift = keys.includes("Shift")
this.alt = keys.includes("Alt")
this.altGr = keys.includes("AltGr")
this.super = keys.includes("Super")
this.key = keys[keys.length - 1]
}
}
}
},
computed: {
className() {
return {
"keyboard-hotkey": true,
"disabled": this.disabled,
}
},
},
methods: {
onChange() {
// create accelerator
const acceleratorKeys = []
if (this.cmdOrCtrl) {
acceleratorKeys.push("CmdOrCtrl")
}
if (this.ctrl) {
acceleratorKeys.push("Ctrl")
}
if (this.shift) {
acceleratorKeys.push("Shift")
}
if (this.alt) {
acceleratorKeys.push("Alt")
}
if (this.altGr) {
acceleratorKeys.push("AltGr")
}
if (this.super) {
acceleratorKeys.push("Super")
}
if (this.key) {
acceleratorKeys.push(this.key)
}
if (acceleratorKeys.length > 0) {
const accelerator = acceleratorKeys.join("+")
//console.log("accelerator:", accelerator)
this.$emit("update:modelValue", accelerator)
}
}
},
}
</script>
<template>
<div :class="className">
<label class="modifier">
<input type="checkbox" v-model="cmdOrCtrl" @change="onChange" />
<span v-if="isMac" class="text">Command</span>
<span v-else class="text">Ctrl</span>
</label>
<label class="modifier">
<input type="checkbox" v-model="shift" @change="onChange" />
<span class="text">Shift</span>
</label>
<label v-if="isMac" class="modifier">
<input type="checkbox" v-model="ctrl" @change="onChange" />
<span class="text">Ctrl</span>
</label>
<label class="modifier">
<input type="checkbox" v-model="alt" @change="onChange" />
<span v-if="isMac" class="text">Option</span>
<span v-else class="text">Alt</span>
</label>
<label v-if="!isMac" class="modifier">
<input type="checkbox" v-model="altGr" @change="onChange" />
<span class="text">AltGr</span>
</label>
<label v-if="!isMac" class="modifier">
<input type="checkbox" v-model="super" @change="onChange" />
<span class="text">Win</span>
</label>
<select v-model="key" @change="onChange">
<option v-for="k in keys" :key="k" :value="k">{{ k }}</option>
</select>
</div>
</template>
<style lang="sass" scoped>
.keyboard-hotkey
display: flex
padding: 7px
border-radius: 3px
border: 1px solid #c4c4c4
background: #eee
+dark-mode
border: 1px solid #666
background: #555
&.disabled
opacity: 0.3
.modifier
margin-right: 5px
user-select: none
.text
position: relative
top: -2px
select
margin-right: 5px
</style>

View File

@ -1,9 +1,14 @@
<script>
import KeyboardHotkey from "./KeyboardHotkey.vue"
export default {
props: {
initialKeymap: String,
initialSettings: Object,
},
components: {
KeyboardHotkey,
},
data() {
return {
@ -17,6 +22,8 @@
showLineNumberGutter: this.initialSettings.showLineNumberGutter,
showFoldGutter: this.initialSettings.showFoldGutter,
allowBetaVersions: this.initialSettings.allowBetaVersions,
enableGlobalHotkey: this.initialSettings.enableGlobalHotkey,
globalHotkey: this.initialSettings.globalHotkey,
}
},
@ -42,6 +49,8 @@
keymap: this.keymap,
emacsMetaKey: this.metaKey,
allowBetaVersions: this.allowBetaVersions,
enableGlobalHotkey: this.enableGlobalHotkey,
globalHotkey: this.globalHotkey,
})
}
}
@ -73,38 +82,55 @@
<div class="row">
<div class="entry">
<h2>Gutters</h2>
<div class="checkbox">
<label>
<input
type="checkbox"
id="showLineNumbers"
v-model="showLineNumberGutter"
@change="updateSettings"
/>
<label for="showLineNumbers">Show line numbers</label>
</div>
<div class="checkbox">
Show line numbers
</label>
<label>
<input
type="checkbox"
id="showFoldGutter"
v-model="showFoldGutter"
@change="updateSettings"
/>
<label for="showFoldGutter">Show fold gutter</label>
</div>
Show fold gutter
</label>
</div>
</div>
<div class="row">
<div class="entry">
<h2>Global Keyboard Shortcut</h2>
<label class="keyboard-shortcut-label">
<input
type="checkbox"
v-model="enableGlobalHotkey"
@change="updateSettings"
/>
Enable Global Hotkey
</label>
<KeyboardHotkey
:disabled="!enableGlobalHotkey"
v-model="globalHotkey"
@change="updateSettings"
/>
</div>
</div>
<div class="row">
<div class="entry">
<h2>Beta Versions</h2>
<div class="checkbox">
<label>
<input
type="checkbox"
id="allowBetaVersions"
v-model="allowBetaVersions"
@change="updateSettings"
/>
<label for="allowBetaVersions">Use beta versions of Heynote</label>
</div>
Use beta versions of Heynote
</label>
</div>
</div>
</div>
@ -117,7 +143,7 @@
</div>
</template>
<style lang="sass">
<style lang="sass" scoped>
.settings
position: fixed
top: 0
@ -163,15 +189,25 @@
.row
display: flex
.entry
margin-bottom: 20px
margin-bottom: 24px
margin-right: 20px
h2
font-weight: 600
margin-bottom: 10px
font-size: 14px
select
width: 200px
&:focus
outline: none
label
display: block
user-select: none
&.keyboard-shortcut-label
margin-bottom: 14px
> input[type=checkbox]
position: relative
top: 2px
left: -3px
.close
height: 32px