feat(core): track for notifications (#11298)

This commit is contained in:
EYHN
2025-03-31 08:38:29 +00:00
parent 73c7815a6d
commit 231956fd39
3 changed files with 60 additions and 6 deletions
@@ -25,6 +25,7 @@ import type {
MentionNotificationBodyType, MentionNotificationBodyType,
} from '@affine/graphql'; } from '@affine/graphql';
import { i18nTime, Trans, useI18n } from '@affine/i18n'; import { i18nTime, Trans, useI18n } from '@affine/i18n';
import track from '@affine/track';
import { import {
CollaborationIcon, CollaborationIcon,
DeleteIcon, DeleteIcon,
@@ -176,6 +177,10 @@ const MentionNotificationItem = ({
const memberInactived = !body.createdByUser; const memberInactived = !body.createdByUser;
const handleClick = useCallback(() => { const handleClick = useCallback(() => {
track.$.sidebar.notifications.clickNotification({
type: notification.type,
item: 'read',
});
if (!body.workspace?.id) { if (!body.workspace?.id) {
return; return;
} }
@@ -189,7 +194,7 @@ const MentionNotificationItem = ({
body.doc.blockId ? [body.doc.blockId] : undefined, body.doc.blockId ? [body.doc.blockId] : undefined,
body.doc.elementId ? [body.doc.elementId] : undefined body.doc.elementId ? [body.doc.elementId] : undefined
); );
}, [body, jumpToPageBlock, notificationListService, notification.id]); }, [body, jumpToPageBlock, notificationListService, notification]);
return ( return (
<div className={styles.itemContainer} onClick={handleClick}> <div className={styles.itemContainer} onClick={handleClick}>
@@ -241,6 +246,10 @@ const InvitationReviewRequestNotificationItem = ({
const memberInactived = !body.createdByUser; const memberInactived = !body.createdByUser;
const workspaceInactived = !body.workspace; const workspaceInactived = !body.workspace;
const handleClick = useCallback(() => { const handleClick = useCallback(() => {
track.$.sidebar.notifications.clickNotification({
type: notification.type,
item: 'read',
});
notificationListService.readNotification(notification.id).catch(err => { notificationListService.readNotification(notification.id).catch(err => {
console.error(err); console.error(err);
}); });
@@ -353,6 +362,11 @@ const InvitationReviewApprovedNotificationItem = ({
const workspaceInactived = !body.workspace; const workspaceInactived = !body.workspace;
const handleClick = useCallback(() => { const handleClick = useCallback(() => {
track.$.sidebar.notifications.clickNotification({
type: notification.type,
item: 'button',
button: 'open',
});
notificationListService.readNotification(notification.id).catch(err => { notificationListService.readNotification(notification.id).catch(err => {
console.error(err); console.error(err);
}); });
@@ -424,6 +438,10 @@ const InvitationAcceptedNotificationItem = ({
const memberInactived = !body.createdByUser; const memberInactived = !body.createdByUser;
const handleClick = useCallback(() => { const handleClick = useCallback(() => {
track.$.sidebar.notifications.clickNotification({
type: notification.type,
item: 'read',
});
notificationListService.readNotification(notification.id).catch(err => { notificationListService.readNotification(notification.id).catch(err => {
console.error(err); console.error(err);
}); });
@@ -476,6 +494,10 @@ const InvitationBlockedNotificationItem = ({
const workspaceInactived = !body.workspace; const workspaceInactived = !body.workspace;
const handleClick = useCallback(() => { const handleClick = useCallback(() => {
track.$.sidebar.notifications.clickNotification({
type: notification.type,
item: 'read',
});
notificationListService.readNotification(notification.id).catch(err => { notificationListService.readNotification(notification.id).catch(err => {
console.error(err); console.error(err);
}); });
@@ -544,6 +566,11 @@ const InvitationNotificationItem = ({
}, [body, jumpToPage, notification.id, notificationListService]); }, [body, jumpToPage, notification.id, notificationListService]);
const handleAcceptInvite = useCallback(() => { const handleAcceptInvite = useCallback(() => {
track.$.sidebar.notifications.clickNotification({
type: notification.type,
item: 'button',
button: 'accept',
});
setIsAccepting(true); setIsAccepting(true);
invitationService invitationService
.acceptInvite(inviteId) .acceptInvite(inviteId)
@@ -654,12 +681,17 @@ const DeleteButton = ({
(e: React.MouseEvent<HTMLButtonElement>) => { (e: React.MouseEvent<HTMLButtonElement>) => {
e.stopPropagation(); // prevent trigger the click event of the parent element e.stopPropagation(); // prevent trigger the click event of the parent element
track.$.sidebar.notifications.clickNotification({
type: notification.type,
item: 'dismiss',
});
notificationListService.readNotification(notification.id).catch(err => { notificationListService.readNotification(notification.id).catch(err => {
console.error(err); console.error(err);
}); });
onClick?.(); onClick?.();
}, },
[notificationListService, notification.id, onClick] [notificationListService, notification, onClick]
); );
return ( return (
@@ -2,6 +2,7 @@ import { Menu } from '@affine/component';
import { MenuItem } from '@affine/core/modules/app-sidebar/views'; import { MenuItem } from '@affine/core/modules/app-sidebar/views';
import { NotificationCountService } from '@affine/core/modules/notification'; import { NotificationCountService } from '@affine/core/modules/notification';
import { useI18n } from '@affine/i18n'; import { useI18n } from '@affine/i18n';
import { track } from '@affine/track';
import { NotificationIcon } from '@blocksuite/icons/rc'; import { NotificationIcon } from '@blocksuite/icons/rc';
import { useLiveData, useService } from '@toeverything/infra'; import { useLiveData, useService } from '@toeverything/infra';
import { useCallback, useState } from 'react'; import { useCallback, useState } from 'react';
@@ -28,9 +29,17 @@ export const NotificationButton = () => {
const [notificationListOpen, setNotificationListOpen] = useState(false); const [notificationListOpen, setNotificationListOpen] = useState(false);
const handleNotificationListOpenChange = useCallback((open: boolean) => { const handleNotificationListOpenChange = useCallback(
setNotificationListOpen(open); (open: boolean) => {
}, []); if (open) {
track.$.sidebar.notifications.openInbox({
unreadCount: notificationCountService.count$.value,
});
}
setNotificationListOpen(open);
},
[notificationCountService.count$.value]
);
return ( return (
<Menu <Menu
+14 -1
View File
@@ -145,6 +145,10 @@ type AttachmentEvents =
type TemplateEvents = 'openTemplateListMenu'; type TemplateEvents = 'openTemplateListMenu';
// END SECTION // END SECTION
// SECTION: notification
type NotificationEvents = 'openInbox' | 'clickNotification';
// END SECTION
type UserEvents = type UserEvents =
| GeneralEvents | GeneralEvents
| AppEvents | AppEvents
@@ -162,7 +166,9 @@ type UserEvents =
| PaymentEvents | PaymentEvents
| DNDEvents | DNDEvents
| AttachmentEvents | AttachmentEvents
| TemplateEvents; | TemplateEvents
| NotificationEvents;
interface PageDivision { interface PageDivision {
[page: string]: { [page: string]: {
[segment: string]: { [segment: string]: {
@@ -346,6 +352,7 @@ const PageEvents = {
sidebar: { sidebar: {
newDoc: ['quickStart'], newDoc: ['quickStart'],
template: ['openTemplateListMenu', 'quickStart'], template: ['openTemplateListMenu', 'quickStart'],
notifications: ['openInbox', 'clickNotification'],
}, },
splitViewIndicator: { splitViewIndicator: {
$: ['splitViewAction', 'openInSplitView', 'openInPeekView'], $: ['splitViewAction', 'openInSplitView', 'openInPeekView'],
@@ -543,6 +550,12 @@ export type EventArgs = {
inviteUserDocRole: { inviteUserDocRole: {
control: 'member list'; control: 'member list';
}; };
openInbox: { unreadCount: number };
clickNotification: {
type: string;
item: 'read' | 'button' | 'dismiss';
button?: string;
};
}; };
// for type checking // for type checking