fix: group follow notification

append current group before push a single item
zio/stable
三咲智子 2023-01-09 20:23:15 +08:00
parent efe7d639c1
commit 83db9f0c38
No known key found for this signature in database
GPG Key ID: 69992F2250DFD93E
4 changed files with 37 additions and 52 deletions

View File

@ -1,4 +1,4 @@
<script setup lang="ts" generic="T, O"> <script setup lang="ts" generic="T, O, U = T">
// @ts-expect-error missing types // @ts-expect-error missing types
import { DynamicScroller } from 'vue-virtual-scroller' import { DynamicScroller } from 'vue-virtual-scroller'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css' import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
@ -22,20 +22,20 @@ const {
// until the next pagination to avoid border effect between pages when reordering // until the next pagination to avoid border effect between pages when reordering
// and grouping items // and grouping items
buffer?: number buffer?: number
preprocess?: (items: T[]) => any[] preprocess?: (items: T[]) => U[]
}>() }>()
defineSlots<{ defineSlots<{
default: { default: {
items: T[] items: U[]
item: T item: U
index: number index: number
active?: boolean active?: boolean
older?: T older?: U
newer?: T // newer is undefined when index === 0 newer?: U // newer is undefined when index === 0
} }
items: { items: {
items: T[] items: U[]
} }
updater: { updater: {
number: number number: number

View File

@ -1,12 +1,9 @@
<script setup lang="ts"> <script setup lang="ts">
import { mastodon } from 'masto' import type { Paginator, WsEvents, mastodon } from 'masto'
import type { Paginator, WsEvents } from 'masto' import type { GroupedAccountLike, NotificationSlot } from '~/types'
// type used in <template>
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
import type { GroupedAccountLike, GroupedLikeNotifications, GroupedNotifications, NotificationSlot } from '~/types'
const { paginator, stream } = defineProps<{ const { paginator, stream } = defineProps<{
paginator: Paginator<NotificationSlot[], mastodon.v1.ListNotificationsParams> paginator: Paginator<mastodon.v1.Notification[], mastodon.v1.ListNotificationsParams>
stream?: Promise<WsEvents> stream?: Promise<WsEvents>
}>() }>()
@ -26,7 +23,7 @@ const groupId = (item: mastodon.v1.Notification): string => {
return JSON.stringify(id) return JSON.stringify(id)
} }
function groupItems(items: mastodon.v1.Notification[]): NotificationSlot[] { function preprocess(items: mastodon.v1.Notification[]): NotificationSlot[] {
const results: NotificationSlot[] = [] const results: NotificationSlot[] = []
let id = 0 let id = 0
@ -43,21 +40,31 @@ function groupItems(items: mastodon.v1.Notification[]): NotificationSlot[] {
// This normally happens when you transfer an account, if not, show // This normally happens when you transfer an account, if not, show
// a big profile card for each follow // a big profile card for each follow
if (group[0].type === 'follow') { if (group[0].type === 'follow') {
const toGroup = [] let groups: mastodon.v1.Notification[] = []
for (const item of group) {
const hasHeader = !item.account.header.endsWith('/original/missing.png') function newGroup() {
if (hasHeader && (item.account.followersCount > 250 || (group.length === 1 && item.account.followersCount > 25))) if (groups.length > 0) {
results.push(item)
else
toGroup.push(item)
}
if (toGroup.length > 0) {
results.push({ results.push({
id: `grouped-${id++}`, id: `grouped-${id++}`,
type: `grouped-${group[0].type}`, type: 'grouped-follow',
items: toGroup, items: groups,
}) })
groups = []
} }
}
for (const item of group) {
const hasHeader = !item.account.header.endsWith('/original/missing.png')
if (hasHeader && (item.account.followersCount > 250 || (group.length === 1 && item.account.followersCount > 25))) {
newGroup()
results.push(item)
}
else {
groups.push(item)
}
}
newGroup()
return return
} }
@ -101,28 +108,6 @@ function groupItems(items: mastodon.v1.Notification[]): NotificationSlot[] {
return results return results
} }
function preprocess(items: NotificationSlot[]): NotificationSlot[] {
const flattenedNotifications: mastodon.v1.Notification[] = []
for (const item of items) {
if (item.type === 'grouped-reblogs-and-favourites') {
const group = item as GroupedLikeNotifications
for (const like of group.likes) {
if (like.reblog)
flattenedNotifications.push(like.reblog)
if (like.favourite)
flattenedNotifications.push(like.favourite)
}
}
else if (item.type.startsWith('grouped-')) {
flattenedNotifications.push(...(item as GroupedNotifications).items)
}
else {
flattenedNotifications.push(item as mastodon.v1.Notification)
}
}
return groupItems(flattenedNotifications)
}
const { clearNotifications } = useNotifications() const { clearNotifications } = useNotifications()
const { formatNumber } = useHumanReadableNumber() const { formatNumber } = useHumanReadableNumber()
</script> </script>
@ -143,12 +128,12 @@ const { formatNumber } = useHumanReadableNumber()
/> />
<NotificationGroupedLikes <NotificationGroupedLikes
v-else-if="item.type === 'grouped-reblogs-and-favourites'" v-else-if="item.type === 'grouped-reblogs-and-favourites'"
:group="item as GroupedLikeNotifications" :group="item"
border="b base" border="b base"
/> />
<NotificationCard <NotificationCard
v-else v-else
:notification="item as mastodon.v1.Notification" :notification="item"
hover:bg-active hover:bg-active
border="b base" border="b base"
/> />

View File

@ -1,11 +1,11 @@
import type { Paginator, WsEvents } from 'masto' import type { Paginator, WsEvents } from 'masto'
import type { PaginatorState } from '~/types' import type { PaginatorState } from '~/types'
export function usePaginator<T, P>( export function usePaginator<T, P, U = T>(
paginator: Paginator<T[], P>, paginator: Paginator<T[], P>,
stream?: Promise<WsEvents>, stream?: Promise<WsEvents>,
eventType: 'notification' | 'update' = 'update', eventType: 'notification' | 'update' = 'update',
preprocess: (items: T[]) => T[] = (items: T[]) => items, preprocess: (items: T[]) => U[] = (items: T[]) => items as unknown as U[],
buffer = 10, buffer = 10,
) { ) {
const state = ref<PaginatorState>(isMastoInitialised.value ? 'idle' : 'loading') const state = ref<PaginatorState>(isMastoInitialised.value ? 'idle' : 'loading')

View File

@ -29,7 +29,7 @@ export type PaginatorState = 'idle' | 'loading' | 'done' | 'error'
export interface GroupedNotifications { export interface GroupedNotifications {
id: string id: string
type: Exclude<string, 'grouped-reblogs-and-favourites'> type: 'grouped-follow'
items: mastodon.v1.Notification[] items: mastodon.v1.Notification[]
} }