fix: group follow notification
append current group before push a single itemzio/stable
parent
efe7d639c1
commit
83db9f0c38
|
@ -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
|
||||||
|
|
|
@ -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"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -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')
|
||||||
|
|
|
@ -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[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue