diff --git a/gdn-app/src/components/CNote.vue b/gdn-app/src/components/CNote.vue index d1300ed..6a12f96 100644 --- a/gdn-app/src/components/CNote.vue +++ b/gdn-app/src/components/CNote.vue @@ -42,7 +42,7 @@ const hovering = ref(false); const mode = ref<"editing" | "creating">(); const mayOpen = computed(() => children.value.length > 0); -const open = computed(() => mayOpen.value && ui.openPaths.has(props.path)); +const open = computed(() => mayOpen.value && ui.isOpen(props.path)); const focused = computed(() => ui.focusPath === props.path); const hover = computed(() => hovering.value && mode.value !== "editing"); @@ -52,11 +52,7 @@ const editing = computed(() => mode.value === "editing"); // Ensure we're open if we need to be. watchEffect(() => { - if (props.forceOpen || creating.value) { - if (!ui.openPaths.has(props.path)) { - ui.openPaths.add(props.path); - } - } + if (props.forceOpen || creating.value) ui.setOpen(props.path, true); }); // Ensure only one editor is ever open. @@ -73,21 +69,13 @@ function focusOnThis() { ui.focusPath = props.path; } -function toggleOpen() { - if (open.value) { - ui.openPaths.delete(props.path); - } else { - ui.openPaths.add(props.path); - } -} - function onClick() { if (!focused.value) { focusOnThis(); return; } - toggleOpen(); + ui.toggleOpen(props.path); } function onEditButtonClick() { @@ -135,7 +123,7 @@ function onCreateEditorFinish(text: string) {
diff --git a/gdn-app/src/stores/ui.ts b/gdn-app/src/stores/ui.ts index 5f961dd..81f4764 100644 --- a/gdn-app/src/stores/ui.ts +++ b/gdn-app/src/stores/ui.ts @@ -1,6 +1,6 @@ import { pathAncestors, pathLiesOn } from "@/util"; import { defineStore } from "pinia"; -import { ref, watch, watchEffect } from "vue"; +import { ref, watchEffect } from "vue"; export const useUiStore = defineStore("ui", () => { const anchorId = ref(); @@ -15,18 +15,31 @@ export const useUiStore = defineStore("ui", () => { } }); - // Ensure the focusPath is updated when a node that lies on it is folded. - watch(openPaths, (now, old) => { - for (const folded of old.difference(now)) { - if (pathLiesOn(folded, focusPath.value)) { - focusPath.value = folded; - } + function isOpen(path: string): boolean { + return openPaths.value.has(path); + } + + function setOpen(path: string, open: boolean) { + // Move the focusPath if necessary + if (!open && isOpen(path) && pathLiesOn(path, focusPath.value)) { + focusPath.value = path; } - }); + + // Don't update openPaths unnecessarily. + // Just in case vue itself doesn't debounce Set operations. + if (open && !isOpen(path)) openPaths.value.add(path); + else if (!open && isOpen(path)) openPaths.value.delete(path); + } + + function toggleOpen(path: string) { + setOpen(path, !isOpen(path)); + } return { anchorId, focusPath, - openPaths, + isOpen, + setOpen, + toggleOpen, }; });