src/Frontend/src/components/ClipFeed.vue
+11
-24
diff --git a/src/Frontend/src/components/ClipFeed.vue b/src/Frontend/src/components/ClipFeed.vue
index 5b955a3..25b7bea 100644
@@ -1,13 +1,20 @@
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from "vue";
import { ref, onMounted } from "vue";
import ClipItem from "./ClipItem.vue";
import type { Clip } from "../Clip";
const clips = ref<Array<Clip>>([]);
const sentinel = ref<HTMLDivElement | null>(null);
const loading = ref(false);
const exhausted = ref(false);
function onClipVisible(clip: Clip) {
const lastClip = clips.value.at(-1);
if (clip.id != lastClip?.id) {
return;
}
fetchClips(clip.id);
}
async function fetchClips(after?: string) {
if (loading.value || exhausted.value) {
return;
@@ -28,28 +35,12 @@ async function fetchClips(after?: string) {
}
}
let observer: IntersectionObserver | null = null;
onMounted(() => {
fetchClips();
observer = new IntersectionObserver(([entry]) => {
if (entry.isIntersecting) {
const last = clips.value.at(-1);
fetchClips(last?.id);
}
});
if (sentinel.value) {
observer.observe(sentinel.value);
}
});
onUnmounted(() => observer?.disconnect());
onMounted(() => fetchClips());
</script>
<template>
<div class="feed">
<ClipItem v-for="clip in clips" :key="clip.id" :clip="clip" />
<div ref="sentinel" class="sentinel"></div>
<ClipItem v-for="clip in clips" :key="clip.id" :clip="clip" @visible="onClipVisible(clip)" />
</div>
</template>
@@ -59,8 +50,4 @@ onUnmounted(() => observer?.disconnect());
overflow-y: scroll;
scroll-snap-type: y mandatory;
}
.sentinel {
height: 1px;
}
</style>
src/Frontend/src/components/ClipItem.vue
+2
-0
diff --git a/src/Frontend/src/components/ClipItem.vue b/src/Frontend/src/components/ClipItem.vue
index c4c06f7..bcf3922 100644
@@ -3,6 +3,7 @@ import { ref, onMounted, onUnmounted } from "vue";
import type { Clip } from "../Clip";
const { clip } = defineProps<{ clip: Clip }>();
const emit = defineEmits<{ visible: [] }>();
const videoEl = ref<HTMLVideoElement | null>(null);
@@ -13,6 +14,7 @@ onMounted(() => {
observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
emit("visible");
video.muted = false;
video.play().catch(() => {
video.muted = true;