mirror of
https://github.com/heyman/heynote.git
synced 2025-07-14 13:05:02 +02:00
461 lines
20 KiB
Vue
461 lines
20 KiB
Vue
<script>
|
|
import KeyboardHotkey from "./KeyboardHotkey.vue"
|
|
import TabListItem from "./TabListItem.vue"
|
|
import TabContent from "./TabContent.vue"
|
|
import { defaultFontFamily, defaultFontSize } from "@/src/editor/theme/font-theme.js"
|
|
|
|
export default {
|
|
props: {
|
|
initialKeymap: String,
|
|
initialSettings: Object,
|
|
},
|
|
components: {
|
|
KeyboardHotkey,
|
|
TabListItem,
|
|
TabContent,
|
|
},
|
|
|
|
data() {
|
|
return {
|
|
keymaps: [
|
|
{ name: "Default", value: "default" },
|
|
{ name: "Emacs", value: "emacs" },
|
|
],
|
|
keymap: this.initialSettings.keymap,
|
|
metaKey: this.initialSettings.emacsMetaKey,
|
|
isMac: window.heynote.platform.isMac,
|
|
showLineNumberGutter: this.initialSettings.showLineNumberGutter,
|
|
showFoldGutter: this.initialSettings.showFoldGutter,
|
|
allowBetaVersions: this.initialSettings.allowBetaVersions,
|
|
enableGlobalHotkey: this.initialSettings.enableGlobalHotkey,
|
|
globalHotkey: this.initialSettings.globalHotkey,
|
|
showInDock: this.initialSettings.showInDock,
|
|
showInMenu: this.initialSettings.showInMenu,
|
|
bracketClosing: this.initialSettings.bracketClosing,
|
|
autoUpdate: this.initialSettings.autoUpdate,
|
|
bufferPath: this.initialSettings.bufferPath,
|
|
fontFamily: this.initialSettings.fontFamily || defaultFontFamily,
|
|
fontSize: this.initialSettings.fontSize || defaultFontSize,
|
|
|
|
activeTab: "general",
|
|
isWebApp: window.heynote.isWebApp,
|
|
customBufferLocation: !!this.initialSettings.bufferPath,
|
|
systemFonts: [[defaultFontFamily, defaultFontFamily + " (default)"]],
|
|
defaultFontSize: defaultFontSize,
|
|
}
|
|
},
|
|
|
|
async mounted() {
|
|
if (window.queryLocalFonts !== undefined) {
|
|
let localFonts = [... new Set((await window.queryLocalFonts()).map(f => f.family))].filter(f => f !== "Hack")
|
|
localFonts = [...new Set(localFonts)].map(f => [f, f])
|
|
this.systemFonts = [[defaultFontFamily, defaultFontFamily + " (default)"], ...localFonts]
|
|
}
|
|
|
|
window.addEventListener("keydown", this.onKeyDown);
|
|
this.$refs.keymapSelector.focus()
|
|
},
|
|
beforeUnmount() {
|
|
window.removeEventListener("keydown", this.onKeyDown);
|
|
},
|
|
|
|
methods: {
|
|
onKeyDown(event) {
|
|
if (event.key === "Escape") {
|
|
this.$emit("closeSettings")
|
|
}
|
|
},
|
|
|
|
updateSettings() {
|
|
window.heynote.setSettings({
|
|
showLineNumberGutter: this.showLineNumberGutter,
|
|
showFoldGutter: this.showFoldGutter,
|
|
keymap: this.keymap,
|
|
emacsMetaKey: window.heynote.platform.isMac ? this.metaKey : "alt",
|
|
allowBetaVersions: this.allowBetaVersions,
|
|
enableGlobalHotkey: this.enableGlobalHotkey,
|
|
globalHotkey: this.globalHotkey,
|
|
showInDock: this.showInDock,
|
|
showInMenu: this.showInMenu || !this.showInDock,
|
|
autoUpdate: this.autoUpdate,
|
|
bracketClosing: this.bracketClosing,
|
|
bufferPath: this.bufferPath,
|
|
fontFamily: this.fontFamily === defaultFontFamily ? undefined : this.fontFamily,
|
|
fontSize: this.fontSize === defaultFontSize ? undefined : this.fontSize,
|
|
})
|
|
if (!this.showInDock) {
|
|
this.showInMenu = true
|
|
}
|
|
},
|
|
|
|
async selectBufferLocation() {
|
|
const path = await window.heynote.buffer.selectLocation()
|
|
if (path) {
|
|
this.bufferPath = path
|
|
this.updateSettings()
|
|
}
|
|
},
|
|
|
|
onCustomBufferLocationChange() {
|
|
if (!this.customBufferLocation) {
|
|
this.bufferPath = ""
|
|
this.updateSettings()
|
|
}
|
|
},
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="settings">
|
|
<div class="dialog">
|
|
<div class="dialog-content">
|
|
<nav class="sidebar">
|
|
<h1>Settings</h1>
|
|
<ul>
|
|
<TabListItem
|
|
name="General"
|
|
tab="general"
|
|
:activeTab="activeTab"
|
|
@click="activeTab = 'general'"
|
|
/>
|
|
<TabListItem
|
|
name="Editing"
|
|
tab="editing"
|
|
:activeTab="activeTab"
|
|
@click="activeTab = 'editing'"
|
|
/>
|
|
<TabListItem
|
|
name="Appearance"
|
|
tab="appearance"
|
|
:activeTab="activeTab"
|
|
@click="activeTab = 'appearance'"
|
|
/>
|
|
<TabListItem
|
|
v-if="!isWebApp"
|
|
name="Updates"
|
|
tab="updates"
|
|
:activeTab="activeTab"
|
|
@click="activeTab = 'updates'"
|
|
/>
|
|
</ul>
|
|
</nav>
|
|
<div class="settings-content">
|
|
<TabContent tab="general" :activeTab="activeTab">
|
|
<div class="row">
|
|
<div class="entry">
|
|
<h2>Keymap</h2>
|
|
<select ref="keymapSelector" v-model="keymap" @change="updateSettings" class="keymap">
|
|
<template v-for="km in keymaps" :key="km.value">
|
|
<option :selected="km.value === keymap" :value="km.value">{{ km.name }}</option>
|
|
</template>
|
|
</select>
|
|
</div>
|
|
<div class="entry" v-if="keymap === 'emacs' && isMac">
|
|
<h2>Meta Key</h2>
|
|
<select v-model="metaKey" @change="updateSettings" class="metaKey">
|
|
<option :selected="metaKey === 'meta'" value="meta">Command</option>
|
|
<option :selected="metaKey === 'alt'" value="alt">Option</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="row" v-if="!isWebApp">
|
|
<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" v-if="!isWebApp">
|
|
<div class="entry">
|
|
<h2>Show In</h2>
|
|
<label v-if="isMac">
|
|
<input
|
|
type="checkbox"
|
|
v-model="showInDock"
|
|
@change="updateSettings"
|
|
/>
|
|
Show in dock
|
|
</label>
|
|
<label>
|
|
<input
|
|
type="checkbox"
|
|
:disabled="!showInDock"
|
|
v-model="showInMenu"
|
|
@change="updateSettings"
|
|
/>
|
|
<template v-if="isMac">
|
|
Show in menu bar
|
|
</template>
|
|
<template v-else>
|
|
Show in system tray
|
|
</template>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="row" v-if="!isWebApp">
|
|
<div class="entry buffer-location">
|
|
<h2>Buffer File Path</h2>
|
|
<label class="keyboard-shortcut-label">
|
|
<input
|
|
type="checkbox"
|
|
v-model="customBufferLocation"
|
|
@change="onCustomBufferLocationChange"
|
|
/>
|
|
Use custom buffer file location
|
|
</label>
|
|
<div class="file-path">
|
|
<button
|
|
:disabled="!customBufferLocation"
|
|
@click="selectBufferLocation"
|
|
>Select Directory</button>
|
|
<span class="path" v-show="customBufferLocation && bufferPath">{{ bufferPath }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</TabContent>
|
|
|
|
<TabContent tab="editing" :activeTab="activeTab">
|
|
<div class="row">
|
|
<div class="entry">
|
|
<h2>Input settings</h2>
|
|
<label>
|
|
<input
|
|
type="checkbox"
|
|
v-model="bracketClosing"
|
|
@change="updateSettings"
|
|
/>
|
|
Auto-close brackets and quotation marks
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</TabContent>
|
|
|
|
<TabContent tab="appearance" :activeTab="activeTab">
|
|
<div class="row">
|
|
<div class="entry">
|
|
<h2>Gutters</h2>
|
|
<label>
|
|
<input
|
|
type="checkbox"
|
|
v-model="showLineNumberGutter"
|
|
@change="updateSettings"
|
|
/>
|
|
Show line numbers
|
|
</label>
|
|
|
|
<label>
|
|
<input
|
|
type="checkbox"
|
|
v-model="showFoldGutter"
|
|
@change="updateSettings"
|
|
/>
|
|
Show fold gutter
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="row font-settings">
|
|
<div class="entry">
|
|
<h2>Font Family</h2>
|
|
<select v-model="fontFamily" @change="updateSettings" class="font-family">
|
|
<option
|
|
v-for="[font, label] in systemFonts"
|
|
:selected="font === fontFamily"
|
|
:value="font"
|
|
>{{ label }}</option>
|
|
</select>
|
|
</div>
|
|
<div class="entry">
|
|
<h2>Font Size</h2>
|
|
<select v-model="fontSize" @change="updateSettings" class="font-size">
|
|
<option
|
|
v-for="size in [8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]"
|
|
:selected="size === fontSize"
|
|
:value="size"
|
|
>{{ size }}px{{ size === defaultFontSize ? " (default)" : "" }}</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</TabContent>
|
|
|
|
<TabContent tab="updates" :activeTab="activeTab" v-if="!isWebApp">
|
|
<div class="row">
|
|
<div class="entry">
|
|
<h2>Auto Update</h2>
|
|
<label>
|
|
<input
|
|
type="checkbox"
|
|
v-model="autoUpdate"
|
|
@change="updateSettings"
|
|
/>
|
|
Periodically check for new updates
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="entry">
|
|
<h2>Beta Versions</h2>
|
|
<label>
|
|
<input
|
|
type="checkbox"
|
|
v-model="allowBetaVersions"
|
|
@change="updateSettings"
|
|
/>
|
|
Use beta versions of Heynote
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</TabContent>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="bottom-bar">
|
|
<button
|
|
@click="$emit('closeSettings')"
|
|
class="close"
|
|
>Close</button>
|
|
</div>
|
|
</div>
|
|
<div class="shader"></div>
|
|
</div>
|
|
</template>
|
|
|
|
<style lang="sass" scoped>
|
|
.settings
|
|
position: fixed
|
|
top: 0
|
|
left: 0
|
|
bottom: 0
|
|
right: 0
|
|
|
|
.shader
|
|
z-index: 1
|
|
position: absolute
|
|
top: 0
|
|
left: 0
|
|
bottom: 0
|
|
right: 0
|
|
background: rgba(0, 0, 0, 0.5)
|
|
|
|
.dialog
|
|
box-sizing: border-box
|
|
z-index: 2
|
|
position: absolute
|
|
left: 50%
|
|
top: 50%
|
|
transform: translate(-50%, -50%)
|
|
width: 700px
|
|
height: 560px
|
|
max-width: 100%
|
|
max-height: 100%
|
|
display: flex
|
|
flex-direction: column
|
|
border-radius: 5px
|
|
background: #fff
|
|
color: #333
|
|
box-shadow: 0 0 25px rgba(0, 0, 0, 0.2)
|
|
overflow-y: auto
|
|
&:active, &:selected, &:focus, &:focus-visible
|
|
border: none
|
|
outline: none
|
|
+dark-mode
|
|
background: #333
|
|
color: #eee
|
|
box-shadow: 0 0 25px rgba(0, 0, 0, 0.3)
|
|
.dialog-content
|
|
flex-grow: 1
|
|
display: flex
|
|
.sidebar
|
|
box-sizing: border-box
|
|
width: 140px
|
|
border-right: 1px solid #eee
|
|
padding-top: 20px
|
|
+dark-mode
|
|
border-right: 1px solid #222
|
|
h1
|
|
font-size: 16px
|
|
font-weight: 700
|
|
margin-bottom: 20px
|
|
padding: 0 20px
|
|
margin-bottom: 20px
|
|
.settings-content
|
|
flex-grow: 1
|
|
padding: 40px
|
|
overflow-y: auto
|
|
select
|
|
height: 22px
|
|
.row
|
|
display: flex
|
|
.entry
|
|
margin-bottom: 24px
|
|
margin-right: 20px
|
|
&:last-child
|
|
margin-right: 0
|
|
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
|
|
&.font-settings
|
|
display: flex
|
|
.font-family
|
|
width: 280px
|
|
.font-size
|
|
width: 120px
|
|
|
|
.buffer-location
|
|
width: 100%
|
|
.file-path
|
|
display: flex
|
|
> button
|
|
flex-shrink: 0
|
|
padding: 3px 8px
|
|
.path
|
|
flex-grow: 1
|
|
margin-left: 10px
|
|
font-size: 12px
|
|
font-family: "Hack"
|
|
padding: 5px 8px
|
|
border-radius: 3px
|
|
background: #f1f1f1
|
|
color: #555
|
|
white-space: nowrap
|
|
overflow-x: auto
|
|
+dark-mode
|
|
background: #222
|
|
color: #aaa
|
|
.bottom-bar
|
|
border-radius: 0 0 5px 5px
|
|
background: #eee
|
|
text-align: right
|
|
padding: 10px 20px
|
|
+dark-mode
|
|
background: #222
|
|
.close
|
|
height: 28px
|
|
</style>
|