functionality updates for preferences
This commit is contained in:
@@ -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})`,
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ const getDefaultConfig = () => {
|
|||||||
return {
|
return {
|
||||||
activeAdapter: 'browser',
|
activeAdapter: 'browser',
|
||||||
theme: 'dark',
|
theme: 'dark',
|
||||||
|
enableBlackletter: 'true',
|
||||||
|
openNotesInNewWindow: 'true',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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') {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
67
src/renderer/src/components/preferences/BooleanInput.vue
Normal file
67
src/renderer/src/components/preferences/BooleanInput.vue
Normal 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>
|
||||||
@@ -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>
|
||||||
|
|||||||
48
src/renderer/src/components/preferences/General.vue
Normal file
48
src/renderer/src/components/preferences/General.vue
Normal 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>
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
// z-index
|
// z-index
|
||||||
.menu {
|
.menu {
|
||||||
|
z-index: 20;
|
||||||
|
}
|
||||||
|
.nav {
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user