update directory live
Some checks are pending
Build Electron App / build (macos-latest, build:mac) (push) Waiting to run
Build Electron App / build (ubuntu-latest, build:linux) (push) Waiting to run
Build Electron App / build (windows-latest, build:win) (push) Waiting to run

This commit is contained in:
nicwands
2026-03-03 17:21:14 -05:00
parent e9e0abe380
commit 73349444d6
16 changed files with 88339 additions and 39075 deletions

View File

@@ -333,11 +333,26 @@ app.whenReady().then(async () => {
"729a0d21d783654c68f1a0123e2a0e986350de536b5324f1f35876ea12ffeaf5" "729a0d21d783654c68f1a0123e2a0e986350de536b5324f1f35876ea12ffeaf5"
); );
await notesAPI.init(); await notesAPI.init();
ipcMain.handle("notesAPI:call", (_, method, args) => { const broadcastNoteChange = (event, data) => {
BrowserWindow.getAllWindows().forEach((win) => {
win.webContents.send(event, data);
});
};
ipcMain.handle("notesAPI:call", async (_, method, args) => {
if (!notesAPI[method]) { if (!notesAPI[method]) {
throw new Error("Invalid method"); throw new Error("Invalid method");
} }
return notesAPI[method](...args); const result = await notesAPI[method](...args);
if (method === "createNote") {
broadcastNoteChange("note-created", result);
} else if (method === "updateNote") {
broadcastNoteChange("note-updated", result);
} else if (method === "updateNoteMetadata") {
broadcastNoteChange("note-updated", result);
} else if (method === "deleteNote") {
broadcastNoteChange("note-deleted", { id: args[0] });
}
return result;
}); });
electronApp.setAppUserModelId("com.electron"); electronApp.setAppUserModelId("com.electron");
app.on("browser-window-created", (_, window) => { app.on("browser-window-created", (_, window) => {

View File

@@ -2,6 +2,15 @@ import { contextBridge, ipcRenderer } from "electron";
const api = { const api = {
openNoteWindow: (noteId) => { openNoteWindow: (noteId) => {
ipcRenderer.send("open-note-window", noteId); ipcRenderer.send("open-note-window", noteId);
},
onNoteCreated: (callback) => {
ipcRenderer.on("note-created", (_, data) => callback(data));
},
onNoteUpdated: (callback) => {
ipcRenderer.on("note-updated", (_, data) => callback(data));
},
onNoteDeleted: (callback) => {
ipcRenderer.on("note-deleted", (_, data) => callback(data));
} }
}; };
const notesAPI = { const notesAPI = {

View File

@@ -180,11 +180,7 @@ meter {
all: revert; all: revert;
} }
.lily-cursor { .menu {
z-index: 20;
}
.site-header {
z-index: 10; z-index: 10;
} }
@@ -304,13 +300,13 @@ html.has-scroll-smooth .hide-on-smooth-scroll {
grid-gap: var(--layout-column-gap); grid-gap: var(--layout-column-gap);
} }
html:not(.dev), html,
html:not(.dev) * { html * {
scrollbar-width: none !important; scrollbar-width: none !important;
-ms-overflow-style: none !important; -ms-overflow-style: none !important;
} }
html:not(.dev)::-webkit-scrollbar, html::-webkit-scrollbar,
html:not(.dev) *::-webkit-scrollbar { html *::-webkit-scrollbar {
width: 0 !important; width: 0 !important;
height: 0 !important; height: 0 !important;
} }
@@ -445,6 +441,10 @@ pre {
min-height: 100vh; min-height: 100vh;
} }
button {
cursor: pointer;
}
::selection { ::selection {
color: var(--theme-bg); color: var(--theme-bg);
background: var(--theme-accent); background: var(--theme-accent);
@@ -493,6 +493,223 @@ pre {
transform: translateY(100%); transform: translateY(100%);
opacity: 0; opacity: 0;
} }
}/* Breakpoints */
@keyframes flip-r {
50% {
transform: translateX(100%);
opacity: 0;
}
51% {
transform: translateX(-100%);
opacity: 0;
}
}
@keyframes flip-l {
50% {
transform: translateX(-100%);
opacity: 0;
}
51% {
transform: translateX(100%);
opacity: 0;
}
}
@keyframes flip-d {
50% {
transform: translateY(100%);
opacity: 0;
}
51% {
transform: translateY(-100%);
opacity: 0;
}
}
@keyframes flip-u {
50% {
transform: translateY(-100%);
opacity: 0;
}
51% {
transform: translateY(100%);
opacity: 0;
}
}
.nav {
padding-top: 2.5423728814vw;
color: var(--grey-100);
}/* Breakpoints */
@keyframes flip-r {
50% {
transform: translateX(100%);
opacity: 0;
}
51% {
transform: translateX(-100%);
opacity: 0;
}
}
@keyframes flip-l {
50% {
transform: translateX(-100%);
opacity: 0;
}
51% {
transform: translateX(100%);
opacity: 0;
}
}
@keyframes flip-d {
50% {
transform: translateY(100%);
opacity: 0;
}
51% {
transform: translateY(-100%);
opacity: 0;
}
}
@keyframes flip-u {
50% {
transform: translateY(-100%);
opacity: 0;
}
51% {
transform: translateY(100%);
opacity: 0;
}
}
.menu {
position: fixed;
top: 0;
left: 0;
right: 0;
background: var(--theme-bg);
border-bottom: 1px solid var(--grey-100);
}
.menu .menu-wrap {
display: flex;
flex-direction: column;
padding-top: 0.8474576271vw;
padding-bottom: 2.8248587571vw;
}
.menu .menu-wrap .menu-item {
display: block;
padding: 4.5197740113vw 0;
text-align: center;
}
.menu .menu-wrap .menu-item:not(:last-child) {
border-bottom: 1px dashed currentColor;
}
.menu .menu-wrap .menu-item:hover {
color: var(--theme-accent);
}
.menu.menu-enter-active, .menu.menu-leave-active {
transition: transform 300ms var(--ease-out-expo);
}
.menu.menu-enter-from, .menu.menu-leave-to {
transform: translateY(-100%);
}/* Breakpoints */
@keyframes flip-r {
50% {
transform: translateX(100%);
opacity: 0;
}
51% {
transform: translateX(-100%);
opacity: 0;
}
}
@keyframes flip-l {
50% {
transform: translateX(-100%);
opacity: 0;
}
51% {
transform: translateX(100%);
opacity: 0;
}
}
@keyframes flip-d {
50% {
transform: translateY(100%);
opacity: 0;
}
51% {
transform: translateY(-100%);
opacity: 0;
}
}
@keyframes flip-u {
50% {
transform: translateY(-100%);
opacity: 0;
}
51% {
transform: translateY(100%);
opacity: 0;
}
}
.scroll-bar {
position: fixed;
top: 0;
right: 0;
bottom: 0;
width: 2.2598870056vw;
will-change: transform;
border-left: 1px solid var(--grey-100);
}
.scroll-bar .inner {
height: 100%;
position: relative;
}
.scroll-bar .inner .handle {
width: 100%;
height: 109.604519774vw;
background: var(--grey-100);
border-radius: 20px;
position: absolute;
right: 0;
will-change: transform;
}/* Breakpoints */
@keyframes flip-r {
50% {
transform: translateX(100%);
opacity: 0;
}
51% {
transform: translateX(-100%);
opacity: 0;
}
}
@keyframes flip-l {
50% {
transform: translateX(-100%);
opacity: 0;
}
51% {
transform: translateX(100%);
opacity: 0;
}
}
@keyframes flip-d {
50% {
transform: translateY(100%);
opacity: 0;
}
51% {
transform: translateY(-100%);
opacity: 0;
}
}
@keyframes flip-u {
50% {
transform: translateY(-100%);
opacity: 0;
}
51% {
transform: translateY(100%);
opacity: 0;
}
} }
.container { .container {
min-height: calc(100 * var(--vh)); min-height: calc(100 * var(--vh));
@@ -547,7 +764,8 @@ pre {
} }
.category-row { .category-row {
display: grid; display: grid;
grid-template-columns: 7.3446327684vw 1fr; grid-template-columns: 7.3446327684vw 1fr auto;
align-items: flex-start;
width: 100%; width: 100%;
position: relative; position: relative;
padding: 1.4124293785vw 0 4.2372881356vw; padding: 1.4124293785vw 0 4.2372881356vw;
@@ -555,6 +773,10 @@ pre {
} }
.category-row .index { .category-row .index {
margin-top: 5.3672316384vw; margin-top: 5.3672316384vw;
font-family: var(--font-mono);
font-weight: 400;
line-height: 1;
font-size: 3.3898305085vw;
} }
.category-row .title { .category-row .title {
display: block; display: block;
@@ -570,16 +792,48 @@ pre {
-webkit-line-clamp: 2; -webkit-line-clamp: 2;
} }
} }
.category-row .category-input {
display: block;
width: 100%;
font-family: var(--font-display);
font-weight: 400;
letter-spacing: -0.02em;
line-height: 1.3;
font-size: 8.4745762712vw;
}
.category-row .category-input:focus {
outline: none;
}
.category-row .edit-button,
.category-row .save-button {
color: var(--grey-100);
cursor: pointer;
padding-right: 0.5em;
padding-left: 0.5em;
margin-top: 1.5em;
}
.category-row .edit-button {
opacity: 0;
pointer-events: none;
}
.category-row.editable:hover .edit-button {
opacity: 1;
pointer-events: auto;
}
.category-row::after { .category-row::after {
content: "----------------------------------------"; content: "----------------------------------------";
position: absolute; position: absolute;
bottom: 0; bottom: 0;
left: 0; left: 0;
font-family: var(--font-mono);
font-weight: 400;
line-height: 1;
font-size: 3.3898305085vw;
} }
.category-row.router-link-exact-active { .category-row.router-link-exact-active, .category-row.editable {
cursor: default; cursor: default;
} }
.category-row:hover:not(.router-link-exact-active) { .category-row:hover:not(.router-link-exact-active):not(.editable) {
color: var(--theme-accent); color: var(--theme-accent);
}/* Breakpoints */ }/* Breakpoints */
@keyframes flip-r { @keyframes flip-r {
@@ -687,10 +941,10 @@ pre {
opacity: 0; opacity: 0;
} }
} }
.directory { main.directory {
padding-top: 5.0847457627vw; padding-top: 5.0847457627vw;
} }
.directory .label { main.directory .label {
text-transform: uppercase; text-transform: uppercase;
margin: 4.802259887vw 0 6.7796610169vw; margin: 4.802259887vw 0 6.7796610169vw;
font-family: var(--font-mono); font-family: var(--font-mono);
@@ -698,7 +952,7 @@ pre {
line-height: 1; line-height: 1;
font-size: 3.3898305085vw; font-size: 3.3898305085vw;
} }
.directory .notes { main.directory .notes {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 3.9548022599vw; gap: 3.9548022599vw;
@@ -743,27 +997,27 @@ pre {
opacity: 0; opacity: 0;
} }
} }
.editor { main.editor {
padding-top: 2.2598870056vw; padding-top: 2.2598870056vw;
padding-bottom: 5.6497175141vw; padding-bottom: 5.6497175141vw;
} }
.editor h1 { main.editor h1 {
font-weight: 700 !important; font-weight: 700 !important;
font-family: var(--font-mono); font-family: var(--font-mono);
font-weight: 400; font-weight: 400;
line-height: 1; line-height: 1;
font-size: 3.3898305085vw; font-size: 3.3898305085vw;
} }
.editor h1:first-child { main.editor h1:first-child {
font-family: var(--font-mono); font-family: var(--font-mono);
font-size: 3.3898305085vw; font-size: 3.3898305085vw;
font-weight: 400 !important; font-weight: 400 !important;
} }
.editor h1:first-child:first-child::first-letter { main.editor h1:first-child:first-child::first-letter {
font-family: var(--font-display); font-family: var(--font-display);
font-size: 11.8644067797vw; font-size: 11.8644067797vw;
} }
.editor h1.is-editor-empty:first-child::before { main.editor h1.is-editor-empty:first-child::before {
color: var(--grey-100); color: var(--grey-100);
content: attr(data-placeholder); content: attr(data-placeholder);
pointer-events: none; pointer-events: none;
@@ -771,56 +1025,135 @@ pre {
font-size: 3.3898305085vw; font-size: 3.3898305085vw;
font-weight: 400 !important; font-weight: 400 !important;
} }
.editor h1.is-editor-empty:first-child::before:first-child::first-letter { main.editor h1.is-editor-empty:first-child::before:first-child::first-letter {
font-family: var(--font-display); font-family: var(--font-display);
font-size: 11.8644067797vw; font-size: 11.8644067797vw;
} }
.editor p strong { main.editor p strong {
font-weight: 700; font-weight: 700;
} }
.editor p em { main.editor p em {
font-style: italic; font-style: italic;
} }
.editor hr::before { main.editor hr::before {
content: "----------------------------------------"; content: "----------------------------------------";
font-family: var(--font-mono); font-family: var(--font-mono);
font-weight: 400; font-weight: 400;
line-height: 1; line-height: 1;
font-size: 3.3898305085vw; font-size: 3.3898305085vw;
} }
.editor ul { main.editor ul {
list-style-type: disc; list-style-type: disc;
} }
.editor ul li { main.editor ul li {
display: list-item; display: list-item;
margin-left: 1em; margin-left: 1em;
} }
.editor ol { main.editor ol {
list-style-type: decimal; list-style-type: decimal;
} }
.editor ol li { main.editor ol li {
display: list-item; display: list-item;
margin-left: 1.5em; margin-left: 1.5em;
} }
.editor ol li::marker { main.editor ol li::marker {
font-family: var(--font-mono); font-family: var(--font-mono);
font-weight: 400; font-weight: 400;
line-height: 1; line-height: 1;
font-size: 3.3898305085vw; font-size: 3.3898305085vw;
} }
.editor a { main.editor a {
color: var(--theme-link); color: var(--theme-link);
cursor: pointer; cursor: pointer;
} }
.editor .editor-wrap > div { main.editor code {
border: 1px solid var(--grey-100);
color: var(--theme-accent);
padding: 0.2em;
border-radius: 0.2em;
}
main.editor pre code {
display: block;
color: inherit;
padding: 1em;
/* Code styling */
}
main.editor pre code .hljs-comment,
main.editor pre code .hljs-quote {
color: #616161;
}
main.editor pre code .hljs-variable,
main.editor pre code .hljs-template-variable,
main.editor pre code .hljs-attribute,
main.editor pre code .hljs-tag,
main.editor pre code .hljs-name,
main.editor pre code .hljs-regexp,
main.editor pre code .hljs-link,
main.editor pre code .hljs-name,
main.editor pre code .hljs-selector-id,
main.editor pre code .hljs-selector-class {
color: #f98181;
}
main.editor pre code .hljs-number,
main.editor pre code .hljs-meta,
main.editor pre code .hljs-built_in,
main.editor pre code .hljs-builtin-name,
main.editor pre code .hljs-literal,
main.editor pre code .hljs-type,
main.editor pre code .hljs-params {
color: #fbbc88;
}
main.editor pre code .hljs-string,
main.editor pre code .hljs-symbol,
main.editor pre code .hljs-bullet {
color: #b9f18d;
}
main.editor pre code .hljs-title,
main.editor pre code .hljs-section {
color: #faf594;
}
main.editor pre code .hljs-keyword,
main.editor pre code .hljs-selector-tag {
color: #70cff8;
}
main.editor pre code .hljs-emphasis {
font-style: italic;
}
main.editor pre code .hljs-strong {
font-weight: 700;
}
main.editor blockquote {
border-left: 4px solid var(--grey-100);
padding-left: 0.5em;
}
main.editor s {
position: relative;
}
main.editor s::after {
content: " ";
display: block;
position: absolute;
top: 50%;
left: 0;
right: 0;
height: 0.2824858757vw;
background: currentColor;
}
main.editor mark {
background: var(--theme-accent);
color: var(--theme-bg);
padding: 0.2em;
border-radius: 0.2em;
}
main.editor .editor-wrap > div {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 5.6497175141vw; gap: 5.6497175141vw;
} }
.editor .editor-wrap > div:focus { main.editor .editor-wrap > div:focus {
outline: none; outline: none;
} }
.editor .bubble-menu { main.editor .bubble-menu {
display: flex; display: flex;
gap: 1.4124293785vw; gap: 1.4124293785vw;
border: 1px solid var(--grey-100); border: 1px solid var(--grey-100);
@@ -828,16 +1161,16 @@ pre {
border-radius: 0.2em; border-radius: 0.2em;
background: var(--theme-bg); background: var(--theme-bg);
} }
.editor .bubble-menu button { main.editor .bubble-menu button {
cursor: pointer; cursor: pointer;
padding: 0.2em; padding: 0.2em;
border-radius: 0.2em; border-radius: 0.2em;
} }
.editor .bubble-menu button:hover { main.editor .bubble-menu button:hover {
background: var(--grey-100); background: var(--grey-100);
color: var(--theme-bg); color: var(--theme-bg);
} }
.editor .bubble-menu button.active { main.editor .bubble-menu button.active {
background: var(--theme-fg); background: var(--theme-fg);
color: var(--theme-bg); color: var(--theme-bg);
}/* Breakpoints */ }/* Breakpoints */
@@ -881,17 +1214,67 @@ pre {
opacity: 0; opacity: 0;
} }
} }
.category .back { main.category .back {
display: block; display: block;
opacity: 0.25; opacity: 0.25;
margin-top: 2.5423728814vw; margin-top: 2.5423728814vw;
} }
.category .category-row { main.category .category-row {
margin-top: 1.1299435028vw; margin-top: 1.1299435028vw;
} }
.category .notes { main.category .notes {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 3.9548022599vw; gap: 3.9548022599vw;
margin-top: 2.5423728814vw; margin-top: 2.5423728814vw;
} }
main.category .new-note {
display: block;
margin: 14.1242937853vw auto 0;
}/* Breakpoints */
@keyframes flip-r {
50% {
transform: translateX(100%);
opacity: 0;
}
51% {
transform: translateX(-100%);
opacity: 0;
}
}
@keyframes flip-l {
50% {
transform: translateX(-100%);
opacity: 0;
}
51% {
transform: translateX(100%);
opacity: 0;
}
}
@keyframes flip-d {
50% {
transform: translateY(100%);
opacity: 0;
}
51% {
transform: translateY(-100%);
opacity: 0;
}
}
@keyframes flip-u {
50% {
transform: translateY(-100%);
opacity: 0;
}
51% {
transform: translateY(100%);
opacity: 0;
}
}
main.instructions .back-link {
opacity: 0.25;
display: block;
margin-top: 2.5423728814vw;
margin-bottom: 3.9548022599vw;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -8,8 +8,8 @@
http-equiv="Content-Security-Policy" http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:"
/> />
<script type="module" crossorigin src="./assets/index-Dv1qfmwr.js"></script> <script type="module" crossorigin src="./assets/index-GKstRZpo.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-CZWw79gc.css"> <link rel="stylesheet" crossorigin href="./assets/index-D9ZUihqb.css">
</head> </head>
<body> <body>

View File

@@ -97,12 +97,33 @@ app.whenReady().then(async () => {
) )
await notesAPI.init() await notesAPI.init()
// Broadcast note changes to all windows
const broadcastNoteChange = (event, data) => {
BrowserWindow.getAllWindows().forEach((win) => {
win.webContents.send(event, data)
})
}
// Handle Notes API // Handle Notes API
ipcMain.handle('notesAPI:call', (_, method, args) => { ipcMain.handle('notesAPI:call', async (_, method, args) => {
if (!notesAPI[method]) { if (!notesAPI[method]) {
throw new Error('Invalid method') throw new Error('Invalid method')
} }
return notesAPI[method](...args)
const result = await notesAPI[method](...args)
// Broadcast changes to all windows
if (method === 'createNote') {
broadcastNoteChange('note-created', result)
} else if (method === 'updateNote') {
broadcastNoteChange('note-updated', result)
} else if (method === 'updateNoteMetadata') {
broadcastNoteChange('note-updated', result)
} else if (method === 'deleteNote') {
broadcastNoteChange('note-deleted', { id: args[0] })
}
return result
}) })
electronApp.setAppUserModelId('com.electron') electronApp.setAppUserModelId('com.electron')

View File

@@ -5,6 +5,15 @@ const api = {
openNoteWindow: (noteId) => { openNoteWindow: (noteId) => {
ipcRenderer.send('open-note-window', noteId) ipcRenderer.send('open-note-window', noteId)
}, },
onNoteCreated: (callback) => {
ipcRenderer.on('note-created', (_, data) => callback(data))
},
onNoteUpdated: (callback) => {
ipcRenderer.on('note-updated', (_, data) => callback(data))
},
onNoteDeleted: (callback) => {
ipcRenderer.on('note-deleted', (_, data) => callback(data))
},
} }
// Implement notes API // Implement notes API

View File

@@ -4,11 +4,7 @@
<Nav /> <Nav />
<div class="menu-wrap layout-block-inner"> <div class="menu-wrap layout-block-inner">
<new-note <new-note class="menu-item" @noteOpened="closeMenu" />
class="menu-item"
category="Special Delivery"
@noteOpened="closeMenu"
/>
<router-link class="menu-item" to="/category" <router-link class="menu-item" to="/category"
>+ New Capitulum</router-link >+ New Capitulum</router-link
> >

View File

@@ -2,8 +2,30 @@ import { ref } from 'vue'
const categories = ref([]) const categories = ref([])
const searchResults = ref([]) const searchResults = ref([])
const notesChangeCount = ref(0)
let initialized = false
function setupListeners() {
if (initialized || typeof window === 'undefined') return
initialized = true
window.api.onNoteCreated(() => {
notesChangeCount.value++
})
window.api.onNoteUpdated(() => {
notesChangeCount.value++
})
window.api.onNoteDeleted(() => {
notesChangeCount.value++
})
}
export default () => { export default () => {
setupListeners()
/* ------------------------- /* -------------------------
Initialization Initialization
--------------------------*/ --------------------------*/
@@ -71,6 +93,7 @@ export default () => {
return { return {
categories, categories,
searchResults, searchResults,
notesChangeCount,
loadCategories, loadCategories,
loadCategoryNotes, loadCategoryNotes,

View File

@@ -18,7 +18,7 @@
</template> </template>
<script setup> <script setup>
import { computed, onMounted, ref } from 'vue' import { computed, onMounted, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import useNotes from '@/composables/useNotes' import useNotes from '@/composables/useNotes'
import NoteRow from '@/components/NoteRow.vue' import NoteRow from '@/components/NoteRow.vue'
@@ -29,14 +29,23 @@ const route = useRoute()
const id = route.params?.id const id = route.params?.id
const router = useRouter() const router = useRouter()
const { categories, loadCategoryNotes, updateCategory } = useNotes() const { categories, loadCategoryNotes, updateCategory, notesChangeCount } =
useNotes()
const notes = ref() const notes = ref()
onMounted(async () => { async function refreshNotes() {
if (id) { if (id) {
notes.value = await loadCategoryNotes(id) notes.value = await loadCategoryNotes(id)
} }
}
onMounted(async () => {
await refreshNotes()
})
watch(notesChangeCount, async () => {
await refreshNotes()
}) })
const onCategoryEdited = async (editedCategory) => { const onCategoryEdited = async (editedCategory) => {

View File

@@ -14,8 +14,3 @@ const onCategoryEdited = (name) => {
router.push({ name: 'category', params: { id: name } }) router.push({ name: 'category', params: { id: name } })
} }
</script> </script>
<style lang="scss">
main.create-category {
}
</style>

View File

@@ -17,17 +17,26 @@
<script setup> <script setup>
import useNotes from '@/composables/useNotes' import useNotes from '@/composables/useNotes'
import { onMounted, ref } from 'vue' import { onMounted, ref, watch } from 'vue'
import CategoryRow from '@/components/CategoryRow.vue' import CategoryRow from '@/components/CategoryRow.vue'
import NoteRow from '@/components/NoteRow.vue' import NoteRow from '@/components/NoteRow.vue'
const { categories, loadCategories, loadCategoryNotes } = useNotes() const { categories, loadCategories, loadCategoryNotes, notesChangeCount } =
useNotes()
const notes = ref() const notes = ref()
onMounted(async () => { async function refreshNotes() {
await loadCategories() await loadCategories()
notes.value = await loadCategoryNotes() notes.value = await loadCategoryNotes()
}
onMounted(async () => {
await refreshNotes()
})
watch(notesChangeCount, async () => {
await refreshNotes()
}) })
</script> </script>