functionality updates for preferences

This commit is contained in:
nicwands
2026-04-09 14:58:06 -04:00
parent b4b627b6bb
commit 1806a612b6
13 changed files with 207 additions and 21 deletions

View File

@@ -96,10 +96,10 @@ async function main() {
return return
} }
// if (isGitTagDirty()) { if (isGitTagDirty()) {
// console.log('Git working directory is dirty. Skipping upload.') console.log('Git working directory is dirty. Skipping upload.')
// return return
// } }
console.log( console.log(
`Uploading artifacts for ${platform} v${version} (tag: ${currentTag})`, `Uploading artifacts for ${platform} v${version} (tag: ${currentTag})`,

View File

@@ -6,6 +6,8 @@ const getDefaultConfig = () => {
return { return {
activeAdapter: 'browser', activeAdapter: 'browser',
theme: 'dark', theme: 'dark',
enableBlackletter: 'true',
openNotesInNewWindow: 'true',
} }
} }

View File

@@ -72,7 +72,13 @@ export const createPluginManagerClient = () => {
}, },
async testPlugin(id, config) { async testPlugin(id, config) {
return window.api.pluginManagerCall('testPlugin', { id, config }) const test = await window.api.pluginManagerCall(
'testPlugin',
id,
config,
)
console.log(test)
return test
}, },
} }
} }

View File

@@ -90,6 +90,8 @@ app.whenReady().then(async () => {
) )
ipcMain.handle('pluginManager:call', async (_, method, ...args) => { ipcMain.handle('pluginManager:call', async (_, method, ...args) => {
console.log(method, ...args)
const methodCall = await pluginManager[method](...args) const methodCall = await pluginManager[method](...args)
if (method === 'setActivePlugin') { if (method === 'setActivePlugin') {

View File

@@ -15,6 +15,7 @@ import SvgSpinner from '@/components/svg/Spinner.vue'
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
pointer-events: none;
svg { svg {
width: 20px; width: 20px;

View File

@@ -0,0 +1,67 @@
<template>
<div class="preferences-boolean-input">
<label :for="key">
{{ label }}
</label>
<button
:class="['toggle-container', { active: model === 'true' }]"
@click="onToggleClick"
>
<div class="toggle-button" />
</button>
</div>
</template>
<script setup>
const props = defineProps({
label: String,
key: String,
required: Boolean,
default: String,
})
const model = defineModel()
const onToggleClick = () => {
if (model.value === 'true') {
model.value = 'false'
} else {
model.value = 'true'
}
}
</script>
<style lang="scss">
.preferences-boolean-input {
display: flex;
align-items: center;
justify-content: space-between;
.toggle-container {
width: 26px;
height: 15px;
border-radius: 10px;
border: 1px solid var(--theme-fg);
position: relative;
.toggle-button {
position: absolute;
top: 0;
left: 0;
width: 13px;
height: 13px;
border-radius: 50%;
background-color: var(--theme-fg);
}
&.active {
background: var(--grey-100);
.toggle-button {
transform: translateX(11px);
}
}
}
}
</style>

View File

@@ -53,6 +53,16 @@ const openDirectoryPicker = async () => {
} }
button { button {
padding: 0.2em 0.5em; padding: 0.2em 0.5em;
background: var(--theme-bg);
color: var(--theme-fg);
border: 1px solid var(--grey-100);
border-radius: 0.2em;
&:hover {
background: var(--theme-fg);
color: var(--theme-bg);
border-color: var(--theme-fg);
}
} }
} }
</style> </style>

View File

@@ -0,0 +1,48 @@
<template>
<div v-if="config" class="preferences-general">
<h2 class="section-title h1 mono">General</h2>
<div class="options">
<preferences-boolean-input
v-model="config.enableBlackletter"
label="Enable Blackletter"
key="enableBlackletter"
/>
<preferences-boolean-input
v-model="config.openNotesInNewWindow"
label="Open Notes in New Window"
key="openNotesInNewWindow"
/>
</div>
</div>
</template>
<script setup>
import PreferencesBooleanInput from '@/components/preferences/BooleanInput.vue'
import useConfig from '@/composables/useConfig'
import { onMounted } from 'vue'
const { config, ensureConfig } = useConfig()
onMounted(async () => {
await ensureConfig()
})
const validate = async () => {
// if (!config.value.encryptionKey) {
// throw new Error('Please fill in the encryption key')
// }
}
defineExpose({ validate })
</script>
<style lang="scss">
.preferences-general {
.options {
display: flex;
flex-direction: column;
gap: 16px;
}
}
</style>

View File

@@ -38,6 +38,11 @@
v-model="config.adapters[plugin.id][field.key]" v-model="config.adapters[plugin.id][field.key]"
v-bind="field" v-bind="field"
/> />
<boolean-input
v-else-if="field.type === 'boolean'"
v-model="config.adapters[plugin.id][field.key]"
v-bind="field"
/>
</div> </div>
</div> </div>
</div> </div>
@@ -47,6 +52,7 @@
<script setup> <script setup>
import DirectoryInput from '@/components/preferences/DirectoryInput.vue' import DirectoryInput from '@/components/preferences/DirectoryInput.vue'
import BooleanInput from '@/components/preferences/BooleanInput.vue'
import TextInput from '@/components/preferences/TextInput.vue' import TextInput from '@/components/preferences/TextInput.vue'
import usePlugins from '@/composables/usePlugins' import usePlugins from '@/composables/usePlugins'
import useConfig from '@/composables/useConfig' import useConfig from '@/composables/useConfig'
@@ -102,11 +108,11 @@ const validate = async () => {
} }
// Test connection // Test connection
// const testResult = await testPlugin(plugin.id, adapterConfig) const testResult = await testPlugin(plugin.id, adapterConfig)
// console.log(testResult) console.log(testResult)
// if (!testResult) { if (!testResult) {
// validationError.value = `Failed to connect to ${plugin.name}` throw new Error(`Failed to connect to ${plugin.name}`)
// } }
} }
await setActivePlugin(selectedPluginId.value, adapterConfig) await setActivePlugin(selectedPluginId.value, adapterConfig)
@@ -137,6 +143,8 @@ defineExpose({ validate })
} }
.info { .info {
flex: 1;
.description { .description {
color: var(--grey-100); color: var(--grey-100);
margin-top: 6px; margin-top: 6px;
@@ -146,7 +154,7 @@ defineExpose({ validate })
.config { .config {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 10px; gap: 16px;
margin-top: 16px; margin-top: 16px;
} }
} }

View File

@@ -2,17 +2,30 @@
<div class="preferences-text-input"> <div class="preferences-text-input">
<label :for="key"> {{ label }}{{ required ? '*' : '' }} </label> <label :for="key"> {{ label }}{{ required ? '*' : '' }} </label>
<input <div class="input-wrapper">
v-model="model" <input
:id="key" v-model="model"
:type="type" :id="key"
:placeholder="default" :type="isPasswordVisible ? 'text' : type"
:required="required" :placeholder="default"
/> :required="required"
/>
<button
v-if="type === 'password'"
type="button"
class="toggle-password"
@click="isPasswordVisible = !isPasswordVisible"
>
👁
</button>
</div>
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref } from 'vue'
const props = defineProps({ const props = defineProps({
label: String, label: String,
key: String, key: String,
@@ -22,6 +35,7 @@ const props = defineProps({
}) })
const model = defineModel() const model = defineModel()
const isPasswordVisible = ref(false)
</script> </script>
<style lang="scss"> <style lang="scss">
@@ -30,11 +44,26 @@ const model = defineModel()
display: block; display: block;
margin-bottom: 6px; margin-bottom: 6px;
} }
.input-wrapper {
position: relative;
display: flex;
align-items: center;
}
input { input {
width: 100%; width: 100%;
border: 1px solid var(--grey-100); border: 1px solid var(--grey-100);
border-radius: 0.2em; border-radius: 0.2em;
padding: 0.2em 0.5em; padding: 0.2em 0.5em;
padding-right: 2.5em;
}
.toggle-password {
position: absolute;
right: 0.5em;
background: none;
border: none;
cursor: pointer;
padding: 0;
font-size: 1em;
} }
} }
</style> </style>

View File

@@ -16,7 +16,7 @@ export default async () => {
} }
const testPlugin = async (pluginId, config = {}) => { const testPlugin = async (pluginId, config = {}) => {
await pluginManager.testPlugin(pluginId, { ...config }) return await pluginManager.testPlugin(pluginId, { ...config })
} }
return { return {

View File

@@ -1,4 +1,7 @@
// z-index // z-index
.menu { .menu {
z-index: 20;
}
.nav {
z-index: 10; z-index: 10;
} }

View File

@@ -3,6 +3,8 @@
<h1 class="title">Preferences</h1> <h1 class="title">Preferences</h1>
<div class="sections"> <div class="sections">
<preferences-general />
<preferences-encryption ref="encryption" /> <preferences-encryption ref="encryption" />
<suspense @resolve="ready = true"> <suspense @resolve="ready = true">
@@ -22,6 +24,7 @@
<script setup> <script setup>
import PreferencesEncryption from '@/components/preferences/Encryption.vue' import PreferencesEncryption from '@/components/preferences/Encryption.vue'
import PreferencesGeneral from '@/components/preferences/General.vue'
import PreferencesStorage from '@/components/preferences/Storage.vue' import PreferencesStorage from '@/components/preferences/Storage.vue'
import SvgSpinner from '@/components/svg/Spinner.vue' import SvgSpinner from '@/components/svg/Spinner.vue'
import { ref } from 'vue' import { ref } from 'vue'
@@ -61,6 +64,7 @@ const save = async () => {
.preferences { .preferences {
padding-top: var(--nav-height); padding-top: var(--nav-height);
padding-bottom: 60px; padding-bottom: 60px;
position: relative;
.title { .title {
margin-bottom: 25px; margin-bottom: 25px;
@@ -69,14 +73,20 @@ const save = async () => {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 30px; gap: 30px;
max-width: 500px;
} }
.section-title { .section-title {
margin-bottom: 20px; margin-bottom: 20px;
} }
.error { .error {
color: red; position: fixed;
margin-top: 16px; top: 0;
left: 0;
right: 0;
background: #ba3632;
padding: 5px var(--layout-margin);
text-align: center;
} }
.save-btn { .save-btn {