fix: connected replies for virtual scrolling

This commit is contained in:
patak 2022-12-28 00:25:41 +01:00
parent ba91e0421e
commit 7305a01d5b
4 changed files with 24 additions and 28 deletions

View file

@ -25,8 +25,7 @@ defineSlots<{
item: any item: any
active?: boolean active?: boolean
older?: any older?: any
newer?: any newer?: any // newer is undefined when index === 0
index?: number
} }
updater: { updater: {
number: number number: number
@ -53,18 +52,18 @@ const { items, prevItems, update, state, endAnchor, error } = usePaginator(pagin
<slot <slot
:item="item" :item="item"
:active="active" :active="active"
:index="index" :older="items[index + 1]"
:newer="items[index - 1]"
/> />
</DynamicScroller> </DynamicScroller>
</template> </template>
<template v-else> <template v-else>
<slot <slot
v-for="item, i of items" v-for="item, index of items"
:key="item[keyProp]" :key="item[keyProp]"
:item="item" :item="item"
:older="items[i + 1]" :older="items[index + 1]"
:newer="items[i - 1]" :newer="items[index - 1]"
:index="i"
/> />
</template> </template>
</slot> </slot>

View file

@ -8,8 +8,13 @@ const props = withDefaults(
context?: FilterContext context?: FilterContext
hover?: boolean hover?: boolean
faded?: boolean faded?: boolean
showReplyTo?: boolean
connectReply?: boolean // If we know the prev and next status in the timeline, we can simplify the card
older?: Status
newer?: Status
// Manual overrides
hasOlder?: boolean
hasNewer?: boolean
}>(), }>(),
{ actions: true, showReplyTo: true }, { actions: true, showReplyTo: true },
) )
@ -20,6 +25,10 @@ const status = $computed(() => {
return props.status return props.status
}) })
// Use original status, avoid connecting a reblog (review if we should relax this)
const directReply = $computed(() => props.hasNewer || (!!props.status.inReplyToId && props.status.inReplyToId === props.newer?.id))
const connectReply = $computed(() => props.hasOlder || props.status.id === props.older?.inReplyToId)
const rebloggedBy = $computed(() => props.status.reblog ? props.status.account : null) const rebloggedBy = $computed(() => props.status.reblog ? props.status.account : null)
const el = ref<HTMLElement>() const el = ref<HTMLElement>()
@ -72,7 +81,7 @@ const isSelf = $computed(() => status.account.id === currentUser.value?.account.
relative flex flex-col gap-1 px-4 pt-1 relative flex flex-col gap-1 px-4 pt-1
class="pb-1.5" class="pb-1.5"
transition-100 transition-100
:class="{ 'hover:bg-active': hover }" :class="{ 'hover:bg-active': hover, 'border-t border-base': newer && !directReply }"
tabindex="0" tabindex="0"
focus:outline-none focus-visible:ring="2 primary" focus:outline-none focus-visible:ring="2 primary"
:lang="status.language ?? undefined" :lang="status.language ?? undefined"
@ -88,7 +97,7 @@ const isSelf = $computed(() => status.account.id === currentUser.value?.account.
</div> </div>
<div v-else /> <div v-else />
</slot> </slot>
<StatusReplyingTo v-if="showReplyTo" :status="status" :class="faded ? 'text-secondary-light' : ''" py1 /> <StatusReplyingTo v-if="!directReply" :status="status" :class="faded ? 'text-secondary-light' : ''" py1 />
</div> </div>
<div flex gap-3 :class="{ 'text-secondary': faded }"> <div flex gap-3 :class="{ 'text-secondary': faded }">
<div relative> <div relative>

View file

@ -21,24 +21,14 @@ const virtualScroller = $(computedEager(() => useFeatureFlags().experimentalVirt
{{ $t('timeline.show_new_items', number) }} {{ $t('timeline.show_new_items', number) }}
</button> </button>
</template> </template>
<template #default="{ item, older, newer, active, index }"> <template #default="{ item, older, newer, active }">
<template v-if="virtualScroller"> <template v-if="virtualScroller">
<DynamicScrollerItem :item="item" :active="active" tag="article"> <DynamicScrollerItem :item="item" :active="active" tag="article">
<StatusCard <StatusCard :status="item" :context="context" :older="older" :newer="newer" />
:status="item" :context="context"
:connect-reply="item.id === older?.inReplyToId"
:show-reply-to="!(item.inReplyToId && item.inReplyToId === newer?.id)"
:class="{ 'border-t border-base': index !== 0 && !(item.inReplyToId && item.inReplyToId === newer?.id) }"
/>
</DynamicScrollerItem> </DynamicScrollerItem>
</template> </template>
<template v-else> <template v-else>
<StatusCard <StatusCard :status="item" :context="context" :older="older" :newer="newer" />
:status="item" :context="context"
:connect-reply="item.id === older?.inReplyToId"
:show-reply-to="!(item.inReplyToId && item.inReplyToId === newer?.id)"
:class="{ 'border-t border-base': !(item.inReplyToId && item.inReplyToId === newer?.id) }"
/>
</template> </template>
</template> </template>
<template #loading> <template #loading>

View file

@ -63,7 +63,7 @@ onReactivated(() => {
<template v-for="comment of context?.ancestors" :key="comment.id"> <template v-for="comment of context?.ancestors" :key="comment.id">
<StatusCard <StatusCard
:status="comment" :actions="comment.visibility !== 'direct'" context="account" :status="comment" :actions="comment.visibility !== 'direct'" context="account"
:show-reply-to="false" :connect-reply="true" :has-older="true" :has-newer="true"
/> />
</template> </template>
@ -86,9 +86,7 @@ onReactivated(() => {
<template v-for="(comment, di) of context?.descendants" :key="comment.id"> <template v-for="(comment, di) of context?.descendants" :key="comment.id">
<StatusCard <StatusCard
:status="comment" :actions="comment.visibility !== 'direct'" context="account" :status="comment" :actions="comment.visibility !== 'direct'" context="account"
:connect-reply="comment.id === context?.descendants[di + 1]?.inReplyToId" :older="context?.descendants[di + 1]" :newer="context?.descendants[di - 1]" :has-newer="di === 0"
:show-reply-to="di !== 0 && comment.inReplyToId !== context?.descendants[di - 1]?.id"
:class="{ 'border-t border-base': di !== 0 && comment.inReplyToId !== context?.descendants[di - 1]?.id }"
/> />
</template> </template>