feat: timeline paginator
This commit is contained in:
parent
f3dd3fe8a5
commit
cf22ca25bf
|
@ -13,7 +13,7 @@ const createdAt = $computed(() => {
|
|||
|
||||
<template>
|
||||
<div flex flex-col>
|
||||
<div>
|
||||
<div border="b border">
|
||||
<img h-50 w-full object-cover :src="account.header">
|
||||
</div>
|
||||
<div p3 style="margin-top:-3.5rem;" flex flex-col gap-6>
|
||||
|
|
57
components/timeline/TimelinePaginator.client.vue
Normal file
57
components/timeline/TimelinePaginator.client.vue
Normal file
|
@ -0,0 +1,57 @@
|
|||
<script setup lang="ts">
|
||||
import type { Paginator, Status } from 'masto'
|
||||
|
||||
const { paginator } = defineProps<{
|
||||
paginator: Paginator<any, Status[]>
|
||||
}>()
|
||||
|
||||
let isLoading = $ref(false)
|
||||
let isDone = $ref(false)
|
||||
const statuses = $ref<Status[]>([])
|
||||
|
||||
const endAnchor = ref<HTMLDivElement>()
|
||||
const bound = reactive(useElementBounding(endAnchor))
|
||||
const isInScreen = $computed(() => bound.top < window.innerHeight * 2)
|
||||
|
||||
async function loadNext() {
|
||||
if (isLoading || isDone)
|
||||
return
|
||||
|
||||
// console.log('REQUEST')
|
||||
isLoading = true
|
||||
const result = await paginator.next()
|
||||
if (result.done)
|
||||
isDone = true
|
||||
if (result.value?.length)
|
||||
statuses.push(...result.value)
|
||||
isLoading = false
|
||||
await nextTick()
|
||||
bound.update()
|
||||
}
|
||||
|
||||
useIntervalFn(() => {
|
||||
bound.update()
|
||||
}, 1000)
|
||||
|
||||
watch(
|
||||
() => isInScreen,
|
||||
() => {
|
||||
if (isInScreen && !isLoading)
|
||||
loadNext()
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<template v-for="status of statuses" :key="status.id">
|
||||
<StatusCard :status="status" border="t border" pt-4 />
|
||||
</template>
|
||||
<div ref="endAnchor" />
|
||||
<div v-if="isLoading">
|
||||
Loading...
|
||||
</div>
|
||||
<div v-if="isDone">
|
||||
End of list
|
||||
</div>
|
||||
</template>
|
|
@ -7,12 +7,12 @@ const params = useRoute().params
|
|||
const user = $computed(() => params.user as string)
|
||||
const masto = await useMasto()
|
||||
const { data: account } = await useAsyncData(`${user}:info`, () => masto.accounts.lookup({ acct: user }))
|
||||
const { data: status } = await useAsyncData(`${user}:status`, () => masto.accounts.fetchStatuses(account.value!.id!))
|
||||
const paginator = masto.accounts.getStatusesIterable(account.value!.id!, {})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<AccountHeader :account="account" />
|
||||
</div>
|
||||
<TimelineList :timelines="status?.value" />
|
||||
<TimelinePaginator :paginator="paginator" />
|
||||
</template>
|
||||
|
|
|
@ -6,9 +6,9 @@ if (!token.value)
|
|||
router.replace('/public')
|
||||
|
||||
const masto = await useMasto()
|
||||
const { data: timelines } = await useAsyncData('timelines-home', () => masto.timelines.fetchHome().then(r => r.value))
|
||||
const paginator = masto.timelines.getHomeIterable()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TimelineList :timelines="timelines" />
|
||||
<TimelinePaginator :paginator="paginator" />
|
||||
</template>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<script setup lang="ts">
|
||||
const masto = await useMasto()
|
||||
const { data: timelines } = await useAsyncData('timelines-public', () => masto.timelines.fetchPublic().then(r => r.value))
|
||||
const paginator = masto.timelines.getPublicIterable()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TimelineList :timelines="timelines" />
|
||||
<TimelinePaginator :paginator="paginator" />
|
||||
</template>
|
||||
|
|
Loading…
Reference in a new issue