- Core API: bind/unbind accept id (integer PK) when face_id is null - Tauri proxy: stream video responses instead of buffering for seek bar - VideoPlayer: remove muted attribute, unmute by default - LibraryView: call invalidateFiles() before ensureFiles() on register/unregister - PeopleView: close sort panel on click-outside, not just hamburger toggle - bind_face: prefer face_id, fallback to id when face_id is null
44 lines
966 B
TypeScript
44 lines
966 B
TypeScript
import { Directive } from 'vue'
|
|
|
|
const vObserve: Directive<HTMLElement> = {
|
|
mounted(el, binding) {
|
|
if (typeof binding.value !== 'function') return
|
|
|
|
const callback = binding.value
|
|
|
|
const observer = new IntersectionObserver(
|
|
(entries) => {
|
|
if (!entries.length) return
|
|
if (entries[0].isIntersecting) {
|
|
callback()
|
|
observer.disconnect()
|
|
}
|
|
},
|
|
{ rootMargin: '200px 0px' }
|
|
)
|
|
|
|
observer.observe(el)
|
|
;(el as any)._io = observer
|
|
|
|
requestAnimationFrame(() => {
|
|
const rect = el.getBoundingClientRect()
|
|
if (
|
|
rect.top < window.innerHeight + 200 &&
|
|
rect.bottom > -200 &&
|
|
rect.width > 0
|
|
) {
|
|
callback()
|
|
observer.disconnect()
|
|
;(el as any)._io = undefined
|
|
}
|
|
})
|
|
},
|
|
unmounted(el) {
|
|
if ((el as any)._io) {
|
|
;(el as any)._io.disconnect()
|
|
;(el as any)._io = undefined
|
|
}
|
|
},
|
|
}
|
|
|
|
export default vObserve |