fix: Library thumbnail loading + People right-click context menu
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
</div>
|
||||
<div v-else-if="filteredPeople.length === 0" class="empty">No results</div>
|
||||
<div v-else class="ms-ppl-face-grid">
|
||||
<div v-for="p in filteredPeople" :key="p.identity_uuid" class="ms-ppl-face-card" @click="selectPerson(p)">
|
||||
<div v-for="p in filteredPeople" :key="p.identity_uuid" class="ms-ppl-face-card" @click="selectPerson(p)" @contextmenu.prevent="showContextMenu($event, p)">
|
||||
<div class="ms-ppl-face-img-wrap">
|
||||
<img v-if="profiles[p.identity_uuid]" :src="profiles[p.identity_uuid]" alt="" @vue:mounted="loadProfile(p.identity_uuid)">
|
||||
<svg v-else class="ms-silhouette" @vue:mounted="loadProfile(p.identity_uuid)" viewBox="0 0 120 120" fill="none">
|
||||
@@ -104,12 +104,19 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="ctxMenu.show" class="ctx-menu" :style="{ left: ctxMenu.x + 'px', top: ctxMenu.y + 'px' }">
|
||||
<div class="ctx-item" @click="ctxAction('rename')">✎ Rename</div>
|
||||
<div class="ctx-item" @click="ctxAction('merge')">⇄ Merge</div>
|
||||
<div class="ctx-divider"></div>
|
||||
<div class="ctx-item danger" @click="ctxAction('delete')">✕ Delete</div>
|
||||
</div>
|
||||
|
||||
<VideoPlayer v-if="playing" :file-uuid="currentVideo.fileUuid" :start-time="currentVideo.startTime" :end-time="currentVideo.endTime" :title="currentVideo.title" @close="playing = false" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, watch } from 'vue'
|
||||
import { ref, computed, onMounted, onUnmounted, watch } from 'vue'
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import VideoPlayer from '../components/VideoPlayer.vue'
|
||||
|
||||
@@ -133,6 +140,7 @@ const showMerge = ref(false)
|
||||
const mergeTarget = ref('')
|
||||
const candidates = ref<any[]>([])
|
||||
const candidateThumbs = ref<Record<string, string>>({})
|
||||
const ctxMenu = ref({ show: false, x: 0, y: 0, person: null as any })
|
||||
|
||||
const filteredPeople = computed(() => {
|
||||
if (isSearching.value && searchResults.value.length) return searchResults.value
|
||||
@@ -244,6 +252,37 @@ function playTrace(t: any) {
|
||||
playing.value = true
|
||||
}
|
||||
|
||||
function showContextMenu(e: MouseEvent, p: any) {
|
||||
ctxMenu.value = { show: true, x: e.clientX, y: e.clientY, person: p }
|
||||
}
|
||||
|
||||
function ctxAction(action: string) {
|
||||
const p = ctxMenu.value.person
|
||||
if (!p) return
|
||||
ctxMenu.value.show = false
|
||||
if (action === 'rename') {
|
||||
selectPerson(p)
|
||||
setTimeout(() => startEditName(), 100)
|
||||
} else if (action === 'merge') {
|
||||
selectPerson(p)
|
||||
setTimeout(() => { showMerge.value = true }, 100)
|
||||
} else if (action === 'delete') {
|
||||
if (confirm(`Delete "${p.name}"?`)) {
|
||||
invoke('delete_identity', { uuid: p.identity_uuid }).then(() => {
|
||||
people.value = people.value.filter((x: any) => x.identity_uuid !== p.identity_uuid)
|
||||
}).catch(e => console.error('Delete failed:', e))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function closeCtxMenu() { ctxMenu.value.show = false }
|
||||
onMounted(() => {
|
||||
document.addEventListener('click', closeCtxMenu)
|
||||
})
|
||||
onUnmounted(() => {
|
||||
document.removeEventListener('click', closeCtxMenu)
|
||||
})
|
||||
|
||||
watch(showCandidates, (v) => { if (v) loadCandidates() })
|
||||
</script>
|
||||
|
||||
@@ -278,4 +317,9 @@ h1 { margin: 0; }
|
||||
.ms-modal-actions { display: flex; justify-content: flex-end; }
|
||||
h2 { margin: 0 0 16px; font-size: 1rem; }
|
||||
.ms-merge-grid { display: flex; flex-wrap: wrap; gap: 16px; max-height: 50vh; overflow-y: auto; }
|
||||
.ctx-menu { position: fixed; z-index: 9999; background: #fff; border-radius: 12px; box-shadow: 0 8px 30px rgba(0,0,0,.15); padding: 6px; min-width: 140px; }
|
||||
.ctx-item { display: flex; align-items: center; gap: 8px; padding: 8px 12px; cursor: pointer; border-radius: 8px; font-size: 0.85rem; color: #222; }
|
||||
.ctx-item:hover { background: #f3f4f6; }
|
||||
.ctx-item.danger { color: #d93025; }
|
||||
.ctx-divider { height: 1px; background: #eee; margin: 4px 8px; }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user