Preferences WIP
This commit is contained in:
@@ -143,6 +143,11 @@ app.whenReady().then(async () => {
|
||||
ipcMain.on("open-note-window", (_, noteId) => {
|
||||
createNoteWindow(noteId);
|
||||
});
|
||||
const broadcastNoteChange = (event, data) => {
|
||||
BrowserWindow.getAllWindows().forEach((win) => {
|
||||
win.webContents.send(event, data);
|
||||
});
|
||||
};
|
||||
const registry = new PluginRegistry();
|
||||
registry.register(filesystemPlugin);
|
||||
registry.register(supabasePlugin);
|
||||
@@ -162,6 +167,8 @@ app.whenReady().then(async () => {
|
||||
}
|
||||
return await adapter[method](...args);
|
||||
});
|
||||
broadcastNoteChange("plugin-changed", pluginId);
|
||||
console.log("activePlugin: ", pluginId);
|
||||
return true;
|
||||
};
|
||||
await setActivePlugin(initialConfig.activeAdapter);
|
||||
@@ -177,11 +184,6 @@ app.whenReady().then(async () => {
|
||||
ipcMain.handle("setActivePlugin", async (_, pluginId) => {
|
||||
return await setActivePlugin(pluginId);
|
||||
});
|
||||
const broadcastNoteChange = (event, data) => {
|
||||
BrowserWindow.getAllWindows().forEach((win) => {
|
||||
win.webContents.send(event, data);
|
||||
});
|
||||
};
|
||||
ipcMain.on("note-changed", (_, event, data) => {
|
||||
broadcastNoteChange(event, data);
|
||||
});
|
||||
|
||||
@@ -16,6 +16,9 @@ const api = {
|
||||
onNoteDeleted: (callback) => {
|
||||
ipcRenderer.on("note-deleted", (_, data) => callback(data));
|
||||
},
|
||||
onPluginChanged: (callback) => {
|
||||
ipcRenderer.on("plugin-changed", (_, data) => callback(data));
|
||||
},
|
||||
notifyNoteChanged: (event, data) => {
|
||||
ipcRenderer.send("note-changed", event, data);
|
||||
}
|
||||
|
||||
@@ -70,6 +70,13 @@ app.whenReady().then(async () => {
|
||||
createNoteWindow(noteId)
|
||||
})
|
||||
|
||||
// Broadcast note changes to all windows
|
||||
const broadcastNoteChange = (event, data) => {
|
||||
BrowserWindow.getAllWindows().forEach((win) => {
|
||||
win.webContents.send(event, data)
|
||||
})
|
||||
}
|
||||
|
||||
// Create plugin registry
|
||||
const registry = new PluginRegistry()
|
||||
|
||||
@@ -102,6 +109,8 @@ app.whenReady().then(async () => {
|
||||
return await adapter[method](...args)
|
||||
})
|
||||
|
||||
broadcastNoteChange('plugin-changed', pluginId)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -124,13 +133,6 @@ app.whenReady().then(async () => {
|
||||
return await setActivePlugin(pluginId)
|
||||
})
|
||||
|
||||
// Broadcast note changes to all windows
|
||||
const broadcastNoteChange = (event, data) => {
|
||||
BrowserWindow.getAllWindows().forEach((win) => {
|
||||
win.webContents.send(event, data)
|
||||
})
|
||||
}
|
||||
|
||||
// Handle note change events from renderer
|
||||
ipcMain.on('note-changed', (_, event, data) => {
|
||||
broadcastNoteChange(event, data)
|
||||
|
||||
@@ -19,6 +19,9 @@ const api = {
|
||||
onNoteDeleted: (callback) => {
|
||||
ipcRenderer.on('note-deleted', (_, data) => callback(data))
|
||||
},
|
||||
onPluginChanged: (callback) => {
|
||||
ipcRenderer.on('plugin-changed', (_, data) => callback(data))
|
||||
},
|
||||
notifyNoteChanged: (event, data) => {
|
||||
ipcRenderer.send('note-changed', event, data)
|
||||
},
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
<div :class="classes" :style="styles">
|
||||
<Nav />
|
||||
|
||||
<router-view :key="$route.fullPath" />
|
||||
<Suspense>
|
||||
<router-view :key="$route.fullPath" />
|
||||
</Suspense>
|
||||
|
||||
<Menu />
|
||||
|
||||
|
||||
@@ -5,15 +5,18 @@
|
||||
|
||||
<div class="menu-wrap layout-block">
|
||||
<new-note class="menu-item" @noteOpened="closeMenu" />
|
||||
<router-link class="menu-item" to="/category"
|
||||
>+ New Capitulum</router-link
|
||||
>
|
||||
<router-link class="menu-item" to="/category">
|
||||
+ New Capitulum
|
||||
</router-link>
|
||||
<theme-switcher class="menu-item" />
|
||||
<router-link class="menu-item" to="/instructions"
|
||||
>Instructio</router-link
|
||||
>
|
||||
<router-link class="menu-item" to="/instructions">
|
||||
Instructio
|
||||
</router-link>
|
||||
<button class="menu-item">Import</button>
|
||||
<button class="menu-item">Export</button>
|
||||
<router-link class="menu-item" to="/preferences">
|
||||
Preferences
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
@@ -29,8 +29,14 @@ export default () => {
|
||||
return configPromise
|
||||
}
|
||||
|
||||
const refreshConfig = async () => {
|
||||
config.value = await window.api.getConfig()
|
||||
configResolve()
|
||||
}
|
||||
|
||||
return {
|
||||
config,
|
||||
ensureConfig,
|
||||
refreshConfig,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,12 @@ const setupListeners = () => {
|
||||
|
||||
window.api.onNoteCreated(updateCacheCount)
|
||||
window.api.onNoteUpdated(updateCacheCount)
|
||||
window.api.onPluginChanged(async () => {
|
||||
const api = await getNotesAPI()
|
||||
await api.init()
|
||||
|
||||
notesChangeCount.value++
|
||||
})
|
||||
|
||||
// Todo update cache
|
||||
window.api.onNoteDeleted(() => {
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { ref } from 'vue'
|
||||
import useConfig from './useConfig'
|
||||
|
||||
export default async () => {
|
||||
const { refreshConfig } = useConfig()
|
||||
|
||||
export default () => {
|
||||
const plugins = ref([])
|
||||
|
||||
onMounted(async () => {
|
||||
plugins.value = await window.api.listPlugins()
|
||||
})
|
||||
plugins.value = await window.api.listPlugins()
|
||||
|
||||
const setActivePlugin = async (pluginId) => {
|
||||
await window.api.setActivePlugin(pluginId)
|
||||
await refreshConfig()
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -110,6 +110,7 @@ export default class NotesAPI {
|
||||
async init() {
|
||||
await this._initSodium()
|
||||
await this.adapter.init()
|
||||
this.notesCache.clear()
|
||||
|
||||
const encryptedNotes = await this.adapter.getAll()
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ import IpcAdapter from '@/libs/core/IpcAdapter.js'
|
||||
import useConfig from '@/composables/useConfig.js'
|
||||
|
||||
// Singleton pattern to make sure only one instance of NotesAPI exists
|
||||
|
||||
let notesAPI = null
|
||||
let initPromise = null
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import CreateCategory from '@/views/CreateCategory.vue'
|
||||
import Category from '@/views/Category.vue'
|
||||
import Instructions from '@/views/Instructions.vue'
|
||||
import Search from '@/views/Search.vue'
|
||||
import Preferences from '@/views/Preferences.vue'
|
||||
|
||||
const routes = [
|
||||
{ path: '/', name: 'directory', component: Directory },
|
||||
@@ -14,6 +15,7 @@ const routes = [
|
||||
{ path: '/category/:id', name: 'category', component: Category },
|
||||
{ path: '/instructions', name: 'instructions', component: Instructions },
|
||||
{ path: '/search', name: 'search', component: Search },
|
||||
{ path: '/preferences', name: 'preferences', component: Preferences },
|
||||
]
|
||||
|
||||
export const router = createRouter({
|
||||
|
||||
@@ -47,7 +47,9 @@ a,
|
||||
button,
|
||||
input,
|
||||
pre,
|
||||
span {
|
||||
span,
|
||||
label,
|
||||
li {
|
||||
@include p;
|
||||
}
|
||||
.bold {
|
||||
|
||||
@@ -12,17 +12,6 @@
|
||||
<div class="notes">
|
||||
<note-row v-for="note in notes" :note="note" :key="note.id" />
|
||||
</div>
|
||||
|
||||
<div v-for="plugin in plugins" :key="plugin.id">
|
||||
<input
|
||||
v-model="activePlugin"
|
||||
type="radio"
|
||||
name="plugins"
|
||||
:value="plugin.id"
|
||||
:id="plugin.id"
|
||||
/>
|
||||
<label :for="plugin.id">{{ plugin.name }}</label>
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
@@ -38,9 +27,6 @@ const { categories, loadCategories, loadCategoryNotes, notesChangeCount } =
|
||||
useNotes()
|
||||
|
||||
const { config } = useConfig()
|
||||
const { plugins, setActivePlugin } = usePlugins()
|
||||
|
||||
const activePlugin = ref(config.value?.activeAdapter)
|
||||
|
||||
const notes = ref()
|
||||
|
||||
@@ -56,10 +42,6 @@ onMounted(async () => {
|
||||
watch(notesChangeCount, async () => {
|
||||
await refreshNotes()
|
||||
})
|
||||
watch(activePlugin, async (pluginId) => {
|
||||
await setActivePlugin(pluginId)
|
||||
await refreshNotes()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@@ -67,18 +49,6 @@ main.directory {
|
||||
padding-top: 18px;
|
||||
padding-bottom: 30px;
|
||||
|
||||
input[type='radio'] {
|
||||
display: block;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin-right: 10px;
|
||||
border: 1px solid white;
|
||||
|
||||
&:checked {
|
||||
background-color: white;
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
text-transform: uppercase;
|
||||
margin: 17px 0 24px;
|
||||
|
||||
86
src/renderer/src/views/Preferences.vue
Normal file
86
src/renderer/src/views/Preferences.vue
Normal file
@@ -0,0 +1,86 @@
|
||||
<template>
|
||||
<main class="preferences layout-block">
|
||||
<router-link to="/" class="back"><- Back</router-link>
|
||||
|
||||
<h1 class="mono">Storage Plugin</h1>
|
||||
|
||||
<div v-for="plugin in plugins" class="plugin" :key="plugin.id">
|
||||
<input
|
||||
v-model="activePluginId"
|
||||
name="plugins"
|
||||
type="radio"
|
||||
:id="plugin.id"
|
||||
:value="plugin.id"
|
||||
/>
|
||||
<label :for="plugin.id">
|
||||
<p class="name bold">{{ plugin.name }}</p>
|
||||
<p class="description">{{ plugin.description }}</p>
|
||||
</label>
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import usePlugins from '@/composables/usePlugins'
|
||||
import useConfig from '@/composables/useConfig'
|
||||
import { ref, onMounted, watch } from 'vue'
|
||||
|
||||
const { plugins, setActivePlugin } = await usePlugins()
|
||||
const { config, ensureConfig } = useConfig()
|
||||
|
||||
const activePluginId = ref(plugins.value[0].id)
|
||||
|
||||
onMounted(async () => {
|
||||
await ensureConfig()
|
||||
activePluginId.value = config.value.activeAdapter
|
||||
|
||||
watch(activePluginId, async (id) => {
|
||||
await setActivePlugin(id)
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.preferences {
|
||||
padding-top: 8px;
|
||||
|
||||
.back {
|
||||
opacity: 0.25;
|
||||
display: block;
|
||||
margin-top: 9px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.plugin {
|
||||
display: flex;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
input[type='radio'] {
|
||||
display: block;
|
||||
flex-shrink: 0;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin-right: 10px;
|
||||
border: 1px solid white;
|
||||
cursor: pointer;
|
||||
|
||||
&:checked {
|
||||
background-color: white;
|
||||
}
|
||||
}
|
||||
|
||||
label {
|
||||
cursor: pointer;
|
||||
|
||||
.description {
|
||||
color: var(--grey-100);
|
||||
margin-top: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -25,7 +25,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { ref, onMounted, onBeforeUnmount } from 'vue'
|
||||
import useNotes from '@/composables/useNotes'
|
||||
import NoteRow from '@/components/NoteRow.vue'
|
||||
import _debounce from 'lodash/debounce'
|
||||
@@ -39,6 +39,10 @@ onMounted(async () => {
|
||||
await new Promise((resolve) => setTimeout(resolve, 100))
|
||||
searchInput.value?.focus()
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
query.value = ''
|
||||
searchResults.value = []
|
||||
})
|
||||
|
||||
const onSearch = async () => {
|
||||
await search(query.value)
|
||||
|
||||
Reference in New Issue
Block a user