feat: avoid reordering pagination border effects (#877)

This commit is contained in:
patak 2023-01-08 17:04:26 +01:00 committed by GitHub
parent f8692ed480
commit efe406df5b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 19 additions and 10 deletions

View file

@ -10,6 +10,7 @@ const {
keyProp = 'id',
virtualScroller = false,
eventType = 'update',
buffer = 10,
preprocess,
} = defineProps<{
paginator: Paginator<T[], O>
@ -17,6 +18,10 @@ const {
virtualScroller?: boolean
stream?: Promise<WsEvents>
eventType?: 'notification' | 'update'
// When preprocess is used, buffer is the number of items that will be hidden
// until the next pagination to avoid border effect between pages when reordering
// and grouping items
buffer?: number
preprocess?: (items: T[]) => any[]
}>()

View file

@ -13,12 +13,13 @@ const showHistory = (edit: mastodon.v1.StatusEdit) => {
}
const timeAgoOptions = useTimeAgoOptions()
// TODO: rework, this is only reversing the first page of edits
const reverseHistory = (items: mastodon.v1.StatusEdit[]) =>
[...items].reverse()
</script>
<template>
<CommonPaginator :paginator="paginator" key-prop="createdAt" :preprocess="reverseHistory">
<CommonPaginator :paginator="paginator" key-prop="createdAt" :preprocess="reverseHistory" :buffer="0">
<template #default="{ items, item, index }">
<CommonDropdownItem
px="0.5"

View file

@ -1,5 +1,5 @@
<script setup lang="ts">
const paginator = useMasto().v1.timelines.listHome()
const paginator = useMasto().v1.timelines.listHome({ limit: 30 })
const stream = useMasto().v1.stream.streamUser()
onBeforeUnmount(() => stream?.then(s => s.disconnect()))
</script>

View file

@ -4,12 +4,13 @@ import { DynamicScrollerItem } from 'vue-virtual-scroller'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
import type { Paginator, WsEvents, mastodon } from 'masto'
const { paginator, stream, account } = defineProps<{
const { paginator, stream, account, buffer = 10 } = defineProps<{
paginator: Paginator<mastodon.v1.Status[], mastodon.v1.ListAccountStatusesParams>
stream?: Promise<WsEvents>
context?: mastodon.v2.FilterContext
account?: mastodon.v1.Account
preprocess?: (items: mastodon.v1.Status[]) => mastodon.v1.Status[]
buffer?: number
}>()
const { formatNumber } = useHumanReadableNumber()
@ -21,7 +22,7 @@ const showOriginSite = $computed(() =>
</script>
<template>
<CommonPaginator v-bind="{ paginator, stream, preprocess }" :virtual-scroller="virtualScroller">
<CommonPaginator v-bind="{ paginator, stream, preprocess, buffer }" :virtual-scroller="virtualScroller">
<template #updater="{ number, update }">
<button py-4 border="b base" flex="~ col" p-3 w-full text-primary font-bold @click="update">
{{ $t('timeline.show_new_items', number, { named: { v: formatNumber(number) } }) }}

View file

@ -1,5 +1,5 @@
<script setup lang="ts">
const paginator = useMasto().v1.timelines.listPublic()
const paginator = useMasto().v1.timelines.listPublic({ limit: 30 })
const stream = useMasto().v1.stream.streamPublicTimeline()
onBeforeUnmount(() => stream.then(s => s.disconnect()))
</script>

View file

@ -1,5 +1,5 @@
<script setup lang="ts">
const paginator = useMasto().v1.timelines.listPublic({ local: true })
const paginator = useMasto().v1.timelines.listPublic({ limit: 30, local: true })
const stream = useMasto().v1.stream.streamCommunityTimeline()
onBeforeUnmount(() => stream.then(s => s.disconnect()))
</script>

View file

@ -6,6 +6,7 @@ export function usePaginator<T, P>(
stream?: Promise<WsEvents>,
eventType: 'notification' | 'update' = 'update',
preprocess: (items: T[]) => T[] = (items: T[]) => items,
buffer = 10,
) {
const state = ref<PaginatorState>(isMastoInitialised.value ? 'idle' : 'loading')
const items = ref<T[]>([])
@ -62,8 +63,10 @@ export function usePaginator<T, P>(
const result = await paginator.next()
if (result.value?.length) {
nextItems.value = preprocess(result.value) as any
items.value.push(...nextItems.value)
const preprocessedItems = preprocess([...nextItems.value, ...result.value]) as any
const itemsToShowCount = preprocessedItems.length - buffer
nextItems.value = preprocessedItems.slice(itemsToShowCount)
items.value.push(...preprocessedItems.slice(0, itemsToShowCount))
state.value = 'idle'
}
else {
@ -108,7 +111,6 @@ export function usePaginator<T, P>(
return {
items,
prevItems,
nextItems,
update,
state,
error,

View file

@ -8,7 +8,7 @@ const { t } = useI18n()
const account = await fetchAccountByHandle(handle)
const paginator = useMasto().v1.accounts.listStatuses(account.id, { excludeReplies: true })
const paginator = useMasto().v1.accounts.listStatuses(account.id, { limit: 30, excludeReplies: true })
if (account) {
useHeadFixed({