feat: grouped follow notification

zio/stable
Anthony Fu 2022-11-30 08:47:54 +08:00
parent 07209a7d29
commit a6406abc52
6 changed files with 118 additions and 25 deletions

View File

@ -29,6 +29,7 @@ const { items, prevItems, update, state, endAnchor, error } = usePaginator(pagin
<template>
<div>
<slot v-if="prevItems.length" name="updater" v-bind="{ number: prevItems.length, update }" />
<slot name="items" :items="items">
<template v-if="virtualScroller">
<DynamicScroller
v-slot="{ item, active }"
@ -47,6 +48,7 @@ const { items, prevItems, update, state, endAnchor, error } = usePaginator(pagin
:item="item"
/>
</template>
</slot>
<div ref="endAnchor" />
<slot v-if="state === 'loading'" name="loading">
<div p5 text-center flex="~ col" items-center animate-pulse>

View File

@ -0,0 +1,38 @@
<script setup lang="ts">
import type { GroupedNotifications } from '~/types'
const { items } = defineProps<{
items: GroupedNotifications
}>()
const count = computed(() => items.items.length)
const isExpanded = ref(false)
</script>
<template>
<article flex flex-col>
<div flex ml-4 items-center>
<div i-ri:user-follow-fill mr-3 color-primary />
{{ $t('notification.followed_you_count', [`${count}`]) }}
</div>
<div v-if="isExpanded">
<AccountCard
v-for="item in items.items"
:key="item.id"
:account="item.account"
p3
/>
</div>
<div v-else flex="~ wrap gap-1" p4>
<AccountHoverWrapper
v-for="item in items.items"
:key="item.id"
:account="item.account"
>
<NuxtLink :to="getAccountPath(item.account)">
<AccountAvatar :account="item.account" w-8 h-8 />
</NuxtLink>
</AccountHoverWrapper>
</div>
</article>
</template>

View File

@ -1,19 +1,64 @@
<script setup lang="ts">
import type { Notification, Paginator } from 'masto'
import type { GroupedNotifications } from '~/types'
const { paginator } = defineProps<{
paginator: Paginator<any, Notification[]>
}>()
function groupItems(items: Notification[]): (Notification | GroupedNotifications)[] {
const results: (Notification | GroupedNotifications)[] = []
let id = 0
let followGroup: Notification[] = []
const bump = () => {
if (followGroup.length === 1) {
results.push(followGroup[0])
followGroup = []
}
else if (followGroup.length > 0) {
results.push({
id: `grouped-${id++}`,
type: 'grouped-follow',
items: followGroup,
})
followGroup = []
}
}
for (const item of items) {
if (item.type === 'follow') {
followGroup.push(item)
}
else {
bump()
results.push(item)
}
}
bump()
return results
}
</script>
<template>
<CommonPaginator :paginator="paginator">
<template #default="{ item }">
<template #items="{ items }">
<template v-for="item of groupItems(items)" :key="item.id">
<NotificationGroupedFollow
v-if="item.type === 'grouped-follow'"
:items="item"
border="b base" pt-4
/>
<NotificationCard
v-else
:notification="item"
hover:bg-active
border="b base" pt-4
/>
</template>
</template>
</CommonPaginator>
</template>

View File

@ -84,6 +84,7 @@
"notification": {
"favourited_post": "favourited your post",
"followed_you": "followed you",
"followed_you_count": "{0} persons followed you",
"missing_type": "MISSING notification.type:",
"reblogged_post": "reblogged your post",
"request_to_follow": "requested to follow you",

View File

@ -84,6 +84,7 @@
"notification": {
"favourited_post": "点赞了你的帖文",
"followed_you": "关注了你",
"followed_you_count": "{0} 人关注了你",
"missing_type": "未知的通知类型:",
"reblogged_post": "转发了你的帖文",
"request_to_follow": "请求关注你",

View File

@ -1,4 +1,4 @@
import type { AccountCredentials, Emoji, Instance } from 'masto'
import type { AccountCredentials, Emoji, Instance, Notification } from 'masto'
export interface AppInfo {
id: string
@ -23,3 +23,9 @@ export interface ServerInfo extends Instance {
timeUpdated: number
customEmojis?: Record<string, Emoji>
}
export interface GroupedNotifications {
id: string
type: string
items: Notification[]
}