mirror of
https://github.com/heyman/heynote.git
synced 2024-11-21 23:43:22 +01:00
Settings improvements (#88)
* Organize Settings in different tabs * Add setting for turning off/on auto updates. * Remove debug log * Use a better variable name (systemTheme -> themeSetting) * Store theme setting for Heynote webapp in local storage
This commit is contained in:
parent
77ed45cfa2
commit
6022356478
@ -25,6 +25,7 @@ const schema = {
|
||||
"emacsMetaKey": { "enum": [null, "alt", "meta"], default: null },
|
||||
"showLineNumberGutter": {type: "boolean", default:true},
|
||||
"showFoldGutter": {type: "boolean", default:true},
|
||||
"autoUpdate": {type: "boolean", default: true},
|
||||
"allowBetaVersions": {type: "boolean", default: false},
|
||||
"enableGlobalHotkey": {type: "boolean", default: false},
|
||||
"globalHotkey": {type: "string", default: "CmdOrCtrl+Shift+H"},
|
||||
@ -49,6 +50,7 @@ const defaults = {
|
||||
emacsMetaKey: "meta",
|
||||
showLineNumberGutter: true,
|
||||
showFoldGutter: true,
|
||||
autoUpdate: true,
|
||||
allowBetaVersions: false,
|
||||
enableGlobalHotkey: false,
|
||||
globalHotkey: "CmdOrCtrl+Shift+H",
|
||||
|
@ -21,7 +21,7 @@
|
||||
languageAuto: true,
|
||||
theme: window.heynote.themeMode.initial,
|
||||
initialTheme: window.heynote.themeMode.initial,
|
||||
systemTheme: 'system',
|
||||
themeSetting: 'system',
|
||||
development: window.location.href.indexOf("dev=1") !== -1,
|
||||
showLanguageSelector: false,
|
||||
showSettings: false,
|
||||
@ -32,7 +32,7 @@
|
||||
mounted() {
|
||||
window.heynote.themeMode.get().then((mode) => {
|
||||
this.theme = mode.computed
|
||||
this.systemTheme = mode.theme
|
||||
this.themeSetting = mode.theme
|
||||
})
|
||||
const onThemeChange = (theme) => {
|
||||
this.theme = theme
|
||||
@ -69,12 +69,12 @@
|
||||
let newTheme
|
||||
// when the "system" theme is used, make sure that the first click always results in amn actual theme change
|
||||
if (this.initialTheme === "light") {
|
||||
newTheme = this.systemTheme === "system" ? "dark" : (this.systemTheme === "dark" ? "light" : "system")
|
||||
newTheme = this.themeSetting === "system" ? "dark" : (this.themeSetting === "dark" ? "light" : "system")
|
||||
} else {
|
||||
newTheme = this.systemTheme === "system" ? "light" : (this.systemTheme === "light" ? "dark" : "system")
|
||||
newTheme = this.themeSetting === "system" ? "light" : (this.themeSetting === "light" ? "dark" : "system")
|
||||
}
|
||||
window.heynote.themeMode.set(newTheme)
|
||||
this.systemTheme = newTheme
|
||||
this.themeSetting = newTheme
|
||||
this.$refs.editor.focus()
|
||||
},
|
||||
|
||||
@ -129,7 +129,8 @@
|
||||
:language="language"
|
||||
:languageAuto="languageAuto"
|
||||
:theme="theme"
|
||||
:systemTheme="systemTheme"
|
||||
:themeSetting="themeSetting"
|
||||
:autoUpdate="settings.autoUpdate"
|
||||
:allowBetaVersions="settings.allowBetaVersions"
|
||||
@toggleTheme="toggleTheme"
|
||||
@openLanguageSelector="openLanguageSelector"
|
||||
|
@ -13,7 +13,8 @@
|
||||
"language",
|
||||
"languageAuto",
|
||||
"theme",
|
||||
"systemTheme",
|
||||
"themeSetting",
|
||||
"autoUpdate",
|
||||
"allowBetaVersions",
|
||||
],
|
||||
|
||||
@ -84,9 +85,13 @@
|
||||
>
|
||||
<span class="icon icon-format"></span>
|
||||
</div>
|
||||
<UpdateStatusItem v-if="updatesEnabled" :allowBetaVersions="allowBetaVersions" />
|
||||
<UpdateStatusItem
|
||||
v-if="updatesEnabled"
|
||||
:autoUpdate="autoUpdate"
|
||||
:allowBetaVersions="allowBetaVersions"
|
||||
/>
|
||||
<div class="status-block theme clickable" @click="$emit('toggleTheme')" title="Toggle dark/light mode">
|
||||
<span :class="'icon ' + systemTheme"></span>
|
||||
<span :class="'icon ' + themeSetting"></span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -1,6 +1,7 @@
|
||||
<script>
|
||||
export default {
|
||||
props: [
|
||||
"autoUpdate",
|
||||
"allowBetaVersions",
|
||||
],
|
||||
|
||||
@ -16,7 +17,6 @@
|
||||
total: 0.0,
|
||||
bytesPerSecond: 0.0,
|
||||
},
|
||||
|
||||
checkForUpdateIntervalId: null,
|
||||
}
|
||||
},
|
||||
@ -50,14 +50,6 @@
|
||||
this.updateProgress = progress
|
||||
}
|
||||
})
|
||||
|
||||
// check for update now
|
||||
this.checkForUpdate()
|
||||
|
||||
// check for updates every 8 hours
|
||||
this.checkForUpdateIntervalId = setInterval(() => {
|
||||
this.checkForUpdate()
|
||||
}, 1000 * 3600 * 8)
|
||||
},
|
||||
|
||||
beforeUnmount() {
|
||||
@ -67,11 +59,27 @@
|
||||
},
|
||||
|
||||
watch: {
|
||||
allowBetaVersions: {
|
||||
handler: function (newValue) {
|
||||
this.checkForUpdate()
|
||||
autoUpdate: {
|
||||
immediate: true,
|
||||
handler(autoUpdate) {
|
||||
if (this.checkForUpdateIntervalId) {
|
||||
clearInterval(this.checkForUpdateIntervalId)
|
||||
}
|
||||
if (autoUpdate) {
|
||||
// check for update now
|
||||
this.checkForUpdate()
|
||||
|
||||
// check for updates every 8 hours
|
||||
this.checkForUpdateIntervalId = setInterval(() => {
|
||||
this.checkForUpdate()
|
||||
}, 1000 * 3600 * 8)
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
allowBetaVersions(newValue) {
|
||||
this.checkForUpdate()
|
||||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
|
@ -1,5 +1,7 @@
|
||||
<script>
|
||||
import KeyboardHotkey from "./KeyboardHotkey.vue"
|
||||
import TabListItem from "./TabListItem.vue"
|
||||
import TabContent from "./TabContent.vue"
|
||||
|
||||
export default {
|
||||
props: {
|
||||
@ -8,6 +10,8 @@
|
||||
},
|
||||
components: {
|
||||
KeyboardHotkey,
|
||||
TabListItem,
|
||||
TabContent,
|
||||
},
|
||||
|
||||
data() {
|
||||
@ -24,6 +28,9 @@
|
||||
allowBetaVersions: this.initialSettings.allowBetaVersions,
|
||||
enableGlobalHotkey: this.initialSettings.enableGlobalHotkey,
|
||||
globalHotkey: this.initialSettings.globalHotkey,
|
||||
autoUpdate: this.initialSettings.autoUpdate,
|
||||
|
||||
activeTab: "general",
|
||||
}
|
||||
},
|
||||
|
||||
@ -51,8 +58,9 @@
|
||||
allowBetaVersions: this.allowBetaVersions,
|
||||
enableGlobalHotkey: this.enableGlobalHotkey,
|
||||
globalHotkey: this.globalHotkey,
|
||||
autoUpdate: this.autoUpdate,
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -61,77 +69,122 @@
|
||||
<div class="settings">
|
||||
<div class="dialog">
|
||||
<div class="dialog-content">
|
||||
<h1>Settings</h1>
|
||||
<div class="row">
|
||||
<div class="entry">
|
||||
<h2>Keymap</h2>
|
||||
<select ref="keymapSelector" v-model="keymap" @change="updateSettings">
|
||||
<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">
|
||||
<option :selected="metaKey === 'meta'" value="meta">Command</option>
|
||||
<option :selected="metaKey === 'alt'" value="alt">Option</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<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">
|
||||
<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"
|
||||
<nav class="sidebar">
|
||||
<h1>Settings</h1>
|
||||
<ul>
|
||||
<TabListItem
|
||||
name="General"
|
||||
tab="general"
|
||||
:activeTab="activeTab"
|
||||
@click="activeTab = 'general'"
|
||||
/>
|
||||
</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>
|
||||
<TabListItem
|
||||
name="Appearance"
|
||||
tab="appearance"
|
||||
:activeTab="activeTab"
|
||||
@click="activeTab = 'appearance'"
|
||||
/>
|
||||
<TabListItem
|
||||
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">
|
||||
<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">
|
||||
<option :selected="metaKey === 'meta'" value="meta">Command</option>
|
||||
<option :selected="metaKey === 'alt'" value="alt">Option</option>
|
||||
</select>
|
||||
</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>
|
||||
</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>
|
||||
</TabContent>
|
||||
|
||||
<TabContent tab="updates" :activeTab="activeTab">
|
||||
<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>
|
||||
|
||||
@ -190,34 +243,46 @@
|
||||
box-shadow: 0 0 25px rgba(0, 0, 0, 0.3)
|
||||
.dialog-content
|
||||
flex-grow: 1
|
||||
padding: 40px
|
||||
h1
|
||||
font-size: 20px
|
||||
font-weight: 600
|
||||
margin-bottom: 20px
|
||||
|
||||
.row
|
||||
display: flex
|
||||
.entry
|
||||
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
|
||||
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
|
||||
.row
|
||||
display: flex
|
||||
.entry
|
||||
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
|
||||
.bottom-bar
|
||||
border-radius: 0 0 5px 5px
|
||||
background: #eee
|
||||
|
24
src/components/settings/TabContent.vue
Normal file
24
src/components/settings/TabContent.vue
Normal file
@ -0,0 +1,24 @@
|
||||
<script>
|
||||
export default {
|
||||
props: ["tab", "activeTab"],
|
||||
|
||||
computed: {
|
||||
className() {
|
||||
return "tab-content " + (this.tab === this.activeTab ? "active" : "")
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="className">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="sass">
|
||||
.tab-content
|
||||
display: none
|
||||
&.active
|
||||
display: block
|
||||
</style>
|
34
src/components/settings/TabListItem.vue
Normal file
34
src/components/settings/TabListItem.vue
Normal file
@ -0,0 +1,34 @@
|
||||
<script>
|
||||
export default {
|
||||
props: ["tab", "activeTab", "name"],
|
||||
|
||||
computed: {
|
||||
tabClass() {
|
||||
return this.tab === this.activeTab ? "active" : ""
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<li :class="tabClass">{{ name }}</li>
|
||||
</template>
|
||||
|
||||
<style scoped lang="sass">
|
||||
li
|
||||
padding: 9px 20px
|
||||
font-size: 13px
|
||||
user-select: none
|
||||
cursor: pointer
|
||||
&:hover
|
||||
background: #f1f1f1
|
||||
+dark-mode
|
||||
background: #292929
|
||||
&.active
|
||||
background: #48b57e
|
||||
color: #fff
|
||||
cursor: default
|
||||
+dark-mode
|
||||
background: #1b6540
|
||||
|
||||
</style>
|
@ -1,5 +1,3 @@
|
||||
=dark-mode()
|
||||
@media (prefers-color-scheme: dark)
|
||||
@content
|
||||
body[theme=dark] &
|
||||
@content
|
||||
|
@ -1,11 +1,15 @@
|
||||
const mediaMatch = window.matchMedia('(prefers-color-scheme: dark)')
|
||||
let themeModeChangeListener = null
|
||||
let autoUpdateCallbacks = null
|
||||
let themeCallback = null
|
||||
mediaMatch.addEventListener("change", async (event) => {
|
||||
if (themeCallback) {
|
||||
themeCallback((await Heynote.themeMode.get()).computed)
|
||||
}
|
||||
})
|
||||
|
||||
let autoUpdateCallbacks = null
|
||||
let currencyData = null
|
||||
|
||||
export default {
|
||||
const Heynote = {
|
||||
platform: {
|
||||
isMac: true,
|
||||
isWindows: false,
|
||||
@ -41,27 +45,25 @@ export default {
|
||||
|
||||
themeMode: {
|
||||
set: (mode) => {
|
||||
localStorage.setItem("theme", mode)
|
||||
themeCallback(mode)
|
||||
document.body.setAttribute("theme", mode === "dark" ? "dark" : "light")
|
||||
console.log("set theme to", mode)
|
||||
},
|
||||
get: async () => {
|
||||
const theme = localStorage.getItem("theme") || "system"
|
||||
const systemTheme = mediaMatch.matches ? "dark" : "light"
|
||||
return {
|
||||
theme: "light",
|
||||
computed: "light",
|
||||
theme: theme,
|
||||
computed: theme === "system" ? systemTheme : theme,
|
||||
}
|
||||
},
|
||||
onChange: (callback) => {
|
||||
themeCallback = callback
|
||||
themeModeChangeListener = (event) => {
|
||||
callback(event.matches ? "dark" : "light")
|
||||
}
|
||||
mediaMatch.addEventListener('change', themeModeChangeListener)
|
||||
return mediaMatch
|
||||
},
|
||||
removeListener() {
|
||||
mediaMatch.removeEventListener('change', themeModeChangeListener)
|
||||
themeCallback = null
|
||||
},
|
||||
initial: "light",
|
||||
initial: localStorage.getItem("theme") || "system",
|
||||
},
|
||||
|
||||
settings: {
|
||||
@ -77,3 +79,5 @@ export default {
|
||||
return currencyData
|
||||
},
|
||||
}
|
||||
|
||||
export default Heynote
|
||||
|
Loading…
Reference in New Issue
Block a user