diff --git a/frontend/src/components/FileExplorer.vue b/frontend/src/components/FileExplorer.vue index 6f75589..4647b6e 100644 --- a/frontend/src/components/FileExplorer.vue +++ b/frontend/src/components/FileExplorer.vue @@ -53,7 +53,7 @@ {{ doc.name }} - + @@ -84,6 +84,7 @@ import ContextMenu from '@imengyu/vue3-context-menu' import { computed, nextTick, + onActivated, onDeactivated, onMounted, onUnmounted, @@ -336,9 +337,13 @@ const focusBreadcrumb = () => { const keyboardFollowScroll = createKeyboardFollowScroll() const markKeyboardFollow = keyboardFollowScroll.markKeyboardFollow const keepCursorVisibleSmooth = keyboardFollowScroll.keepVisible +// Deactivated (KeepAlive-cached) instances stay alive with frozen, potentially +// stale props - their watchers must not react to global store changes. +let isActive = true watch( () => store.cursor, cursor => { + if (!isActive) return if (cursor && editing.value && cursor !== editing.value.key) { exitEditing() } @@ -347,6 +352,7 @@ watch( watch( () => store.cursor, cursor => { + if (!isActive) return if (cursor && !editing.value) { const a = document.querySelector( `#file-${cursor} .name a` @@ -359,6 +365,7 @@ watch( watch( () => [props.documents.length, store.cursor, store.query, editing.value] as const, ([len, cursor, query, editingDoc]) => { + if (!isActive) return if (!len && cursor && !query && !editingDoc) { store.cursor = '' focusBreadcrumb() @@ -378,7 +385,11 @@ onMounted(() => { active.focus({ preventScroll: true }) } }) +onActivated(() => { + isActive = true +}) onDeactivated(() => { + isActive = false if (editing.value) exitEditing() }) onUnmounted(() => { @@ -617,6 +628,12 @@ table td { .name .rename-button { position: absolute; right: 0; + opacity: 0; + visibility: hidden; +} +tbody tr:hover .name .rename-button { + opacity: 1; + visibility: visible; animation: appear calc(5 * var(--transition-time)) linear; } @keyframes appear { diff --git a/frontend/src/components/Gallery.vue b/frontend/src/components/Gallery.vue index a59aabd..1ab52cb 100644 --- a/frontend/src/components/Gallery.vue +++ b/frontend/src/components/Gallery.vue @@ -8,7 +8,7 @@ :editing="editing === doc ? {rename, exit} : null" :style="{ '--gallery-figure-height': rowHeightsByKey[doc.key] ?? '15em' }" @menu="contextMenu($event, doc)" - @rename="editing = doc; store.cursor = doc.key" + @rename="onFigureRename(doc)" :class="{ 'folder-start': showFolderBreadcrumb(index) }" /> @@ -64,6 +64,10 @@ const editing = shallowRef(null) const exit = () => { editing.value = null } +const onFigureRename = (doc: Doc) => { + editing.value = doc + store.cursor = doc.key +} const rename = async (doc: Doc, newName: string) => { const oldName = doc.name doc.name = newName // We should get an update from watch but this is quicker @@ -396,9 +400,13 @@ const focusBreadcrumb = () => { const keyboardFollowScroll = createKeyboardFollowScroll() const markKeyboardFollow = keyboardFollowScroll.markKeyboardFollow const keepCursorVisibleSmooth = keyboardFollowScroll.keepVisible +// Deactivated (KeepAlive-cached) instances stay alive with frozen, potentially +// stale props - their watchers must not react to global store changes. +let isActive = true watch( () => store.cursor, cursor => { + if (!isActive) return if (cursor && editing.value && cursor !== editing.value.key) { exit() } @@ -407,6 +415,7 @@ watch( watch( () => store.cursor, cursor => { + if (!isActive) return if (cursor && !editing.value) { const a = document.querySelector(`#file-${cursor}`) as HTMLAnchorElement | null if (a) { @@ -419,6 +428,7 @@ watch( watch( () => [props.documents.length, store.cursor, store.query, editing.value] as const, ([len, cursor, query, editingDoc]) => { + if (!isActive) return if (!len && cursor && !query && !editingDoc) { store.cursor = '' focusBreadcrumb() @@ -449,12 +459,14 @@ onMounted(() => { attachGalleryObservers() }) onActivated(() => { + isActive = true nextTick(() => { updateColumns() attachGalleryObservers() }) }) onDeactivated(() => { + isActive = false detachGalleryObservers() if (editing.value) exit() }) diff --git a/frontend/src/components/GalleryFigure.vue b/frontend/src/components/GalleryFigure.vue index 98abbf5..77e3953 100644 --- a/frontend/src/components/GalleryFigure.vue +++ b/frontend/src/components/GalleryFigure.vue @@ -29,7 +29,7 @@ {{ snap.displayName }} .{{ snap.ext }} - +
@@ -64,6 +64,10 @@ const props = defineProps<{ doc: Doc editing?: EditingProp }>() +const emit = defineEmits<{ + (e: 'rename'): void + (e: 'menu', ev: MouseEvent): void +}>() const m = ref(null) const tooltip = ref | null>(null)