mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-08 20:57:08 +08:00
feat(core): more notification type (#11209)
This commit is contained in:
@@ -18,6 +18,9 @@ import type {
|
|||||||
InvitationAcceptedNotificationBodyType,
|
InvitationAcceptedNotificationBodyType,
|
||||||
InvitationBlockedNotificationBodyType,
|
InvitationBlockedNotificationBodyType,
|
||||||
InvitationNotificationBodyType,
|
InvitationNotificationBodyType,
|
||||||
|
InvitationReviewApprovedNotificationBodyType,
|
||||||
|
InvitationReviewDeclinedNotificationBodyType,
|
||||||
|
InvitationReviewRequestNotificationBodyType,
|
||||||
MentionNotificationBodyType,
|
MentionNotificationBodyType,
|
||||||
} from '@affine/graphql';
|
} from '@affine/graphql';
|
||||||
import { i18nTime, Trans, useI18n } from '@affine/i18n';
|
import { i18nTime, Trans, useI18n } from '@affine/i18n';
|
||||||
@@ -118,6 +121,12 @@ const NotificationItem = ({ notification }: { notification: Notification }) => {
|
|||||||
<InvitationNotificationItem notification={notification} />
|
<InvitationNotificationItem notification={notification} />
|
||||||
) : type === NotificationType.InvitationBlocked ? (
|
) : type === NotificationType.InvitationBlocked ? (
|
||||||
<InvitationBlockedNotificationItem notification={notification} />
|
<InvitationBlockedNotificationItem notification={notification} />
|
||||||
|
) : type === NotificationType.InvitationReviewRequest ? (
|
||||||
|
<InvitationReviewRequestNotificationItem notification={notification} />
|
||||||
|
) : type === NotificationType.InvitationReviewDeclined ? (
|
||||||
|
<InvitationReviewDeclinedNotificationItem notification={notification} />
|
||||||
|
) : type === NotificationType.InvitationReviewApproved ? (
|
||||||
|
<InvitationReviewApprovedNotificationItem notification={notification} />
|
||||||
) : (
|
) : (
|
||||||
<div className={styles.itemContainer}>
|
<div className={styles.itemContainer}>
|
||||||
<Avatar size={22} />
|
<Avatar size={22} />
|
||||||
@@ -194,6 +203,189 @@ const MentionNotificationItem = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const InvitationReviewRequestNotificationItem = ({
|
||||||
|
notification,
|
||||||
|
}: {
|
||||||
|
notification: Notification;
|
||||||
|
}) => {
|
||||||
|
const notificationListService = useService(NotificationListService);
|
||||||
|
const { jumpToWorkspaceSettings } = useNavigateHelper();
|
||||||
|
const t = useI18n();
|
||||||
|
const body = notification.body as InvitationReviewRequestNotificationBodyType;
|
||||||
|
const memberInactived = !body.createdByUser;
|
||||||
|
const workspaceInactived = !body.workspace;
|
||||||
|
const handleClick = useCallback(() => {
|
||||||
|
notificationListService.readNotification(notification.id).catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
if (!body.workspace?.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
jumpToWorkspaceSettings(body.workspace.id, 'workspace:members');
|
||||||
|
}, [body, jumpToWorkspaceSettings, notification, notificationListService]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.itemContainer} onClick={handleClick}>
|
||||||
|
<Avatar
|
||||||
|
size={22}
|
||||||
|
name={body.createdByUser?.name}
|
||||||
|
url={body.createdByUser?.avatarUrl}
|
||||||
|
/>
|
||||||
|
<div className={styles.itemMain}>
|
||||||
|
<span>
|
||||||
|
<Trans
|
||||||
|
i18nKey={'com.affine.notification.invitation-review-request'}
|
||||||
|
components={{
|
||||||
|
1: (
|
||||||
|
<b
|
||||||
|
className={styles.itemNameLabel}
|
||||||
|
data-inactived={memberInactived}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
2: <WorkspaceNameWithIcon data-inactived={workspaceInactived} />,
|
||||||
|
}}
|
||||||
|
values={{
|
||||||
|
username:
|
||||||
|
body.createdByUser?.name ?? t['com.affine.inactive-member'](),
|
||||||
|
workspaceName:
|
||||||
|
body.workspace?.name ?? t['com.affine.inactive-workspace'](),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<div className={styles.itemDate}>
|
||||||
|
{i18nTime(notification.createdAt, {
|
||||||
|
relative: true,
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<DeleteButton notification={notification} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const InvitationReviewDeclinedNotificationItem = ({
|
||||||
|
notification,
|
||||||
|
}: {
|
||||||
|
notification: Notification;
|
||||||
|
}) => {
|
||||||
|
const t = useI18n();
|
||||||
|
const body =
|
||||||
|
notification.body as InvitationReviewDeclinedNotificationBodyType;
|
||||||
|
const memberInactived = !body.createdByUser;
|
||||||
|
const workspaceInactived = !body.workspace;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.itemContainer}>
|
||||||
|
<Avatar
|
||||||
|
size={22}
|
||||||
|
name={body.createdByUser?.name}
|
||||||
|
url={body.createdByUser?.avatarUrl}
|
||||||
|
/>
|
||||||
|
<div className={styles.itemMain}>
|
||||||
|
<span>
|
||||||
|
<Trans
|
||||||
|
i18nKey={'com.affine.notification.invitation-review-declined'}
|
||||||
|
components={{
|
||||||
|
1: (
|
||||||
|
<b
|
||||||
|
className={styles.itemNameLabel}
|
||||||
|
data-inactived={memberInactived}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
2: <WorkspaceNameWithIcon data-inactived={workspaceInactived} />,
|
||||||
|
}}
|
||||||
|
values={{
|
||||||
|
username:
|
||||||
|
body.createdByUser?.name ?? t['com.affine.inactive-member'](),
|
||||||
|
workspaceName:
|
||||||
|
body.workspace?.name ?? t['com.affine.inactive-workspace'](),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<div className={styles.itemDate}>
|
||||||
|
{i18nTime(notification.createdAt, {
|
||||||
|
relative: true,
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<DeleteButton notification={notification} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const InvitationReviewApprovedNotificationItem = ({
|
||||||
|
notification,
|
||||||
|
}: {
|
||||||
|
notification: Notification;
|
||||||
|
}) => {
|
||||||
|
const notificationListService = useService(NotificationListService);
|
||||||
|
const { jumpToPage } = useNavigateHelper();
|
||||||
|
const t = useI18n();
|
||||||
|
const body =
|
||||||
|
notification.body as InvitationReviewApprovedNotificationBodyType;
|
||||||
|
const memberInactived = !body.createdByUser;
|
||||||
|
const workspaceInactived = !body.workspace;
|
||||||
|
|
||||||
|
const handleClick = useCallback(() => {
|
||||||
|
notificationListService.readNotification(notification.id).catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
if (!body.workspace?.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
jumpToPage(body.workspace.id, 'all');
|
||||||
|
}, [body, jumpToPage, notification, notificationListService]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.itemContainer}>
|
||||||
|
<Avatar
|
||||||
|
size={22}
|
||||||
|
name={body.createdByUser?.name}
|
||||||
|
url={body.createdByUser?.avatarUrl}
|
||||||
|
/>
|
||||||
|
<div className={styles.itemMain}>
|
||||||
|
<span>
|
||||||
|
<Trans
|
||||||
|
i18nKey={'com.affine.notification.invitation-review-approved'}
|
||||||
|
components={{
|
||||||
|
1: (
|
||||||
|
<b
|
||||||
|
className={styles.itemNameLabel}
|
||||||
|
data-inactived={memberInactived}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
2: <WorkspaceNameWithIcon data-inactived={workspaceInactived} />,
|
||||||
|
}}
|
||||||
|
values={{
|
||||||
|
username:
|
||||||
|
body.createdByUser?.name ?? t['com.affine.inactive-member'](),
|
||||||
|
workspaceName:
|
||||||
|
body.workspace?.name ?? t['com.affine.inactive-workspace'](),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
{!workspaceInactived && (
|
||||||
|
<Button
|
||||||
|
variant="secondary"
|
||||||
|
className={styles.itemActionButton}
|
||||||
|
onClick={handleClick}
|
||||||
|
>
|
||||||
|
{t[
|
||||||
|
'com.affine.notification.invitation-review-approved.open-workspace'
|
||||||
|
]()}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
<div className={styles.itemDate}>
|
||||||
|
{i18nTime(notification.createdAt, {
|
||||||
|
relative: true,
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<DeleteButton notification={notification} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const InvitationAcceptedNotificationItem = ({
|
const InvitationAcceptedNotificationItem = ({
|
||||||
notification,
|
notification,
|
||||||
}: {
|
}: {
|
||||||
@@ -320,21 +512,6 @@ const InvitationNotificationItem = ({
|
|||||||
const [isAccepting, setIsAccepting] = useState(false);
|
const [isAccepting, setIsAccepting] = useState(false);
|
||||||
const { jumpToPage } = useNavigateHelper();
|
const { jumpToPage } = useNavigateHelper();
|
||||||
|
|
||||||
const WorkspaceNameWithIcon = useCallback(
|
|
||||||
({
|
|
||||||
children,
|
|
||||||
...props
|
|
||||||
}: React.PropsWithChildren<React.HTMLAttributes<HTMLSpanElement>>) => {
|
|
||||||
return (
|
|
||||||
<b className={styles.itemNameLabel} {...props}>
|
|
||||||
<CollaborationIcon width={20} height={20} />
|
|
||||||
{children}
|
|
||||||
</b>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleReadAndOpenWorkspace = useCallback(() => {
|
const handleReadAndOpenWorkspace = useCallback(() => {
|
||||||
notificationListService.readNotification(notification.id).catch(err => {
|
notificationListService.readNotification(notification.id).catch(err => {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
@@ -473,3 +650,15 @@ const DeleteButton = ({
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const WorkspaceNameWithIcon = ({
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}: React.PropsWithChildren<React.HTMLAttributes<HTMLSpanElement>>) => {
|
||||||
|
return (
|
||||||
|
<b className={styles.itemNameLabel} {...props}>
|
||||||
|
<CollaborationIcon width={20} height={20} />
|
||||||
|
{children}
|
||||||
|
</b>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
{
|
{
|
||||||
"ar": 94,
|
"ar": 93,
|
||||||
"ca": 4,
|
"ca": 4,
|
||||||
"da": 4,
|
"da": 4,
|
||||||
"de": 94,
|
"de": 93,
|
||||||
"el-GR": 94,
|
"el-GR": 93,
|
||||||
"en": 100,
|
"en": 100,
|
||||||
"es-AR": 94,
|
"es-AR": 93,
|
||||||
"es-CL": 95,
|
"es-CL": 95,
|
||||||
"es": 94,
|
"es": 93,
|
||||||
"fa": 94,
|
"fa": 93,
|
||||||
"fr": 94,
|
"fr": 93,
|
||||||
"hi": 2,
|
"hi": 2,
|
||||||
"it-IT": 94,
|
"it-IT": 93,
|
||||||
"it": 1,
|
"it": 1,
|
||||||
"ja": 94,
|
"ja": 93,
|
||||||
"ko": 59,
|
"ko": 59,
|
||||||
"pl": 94,
|
"pl": 93,
|
||||||
"pt-BR": 94,
|
"pt-BR": 93,
|
||||||
"ru": 94,
|
"ru": 93,
|
||||||
"sv-SE": 94,
|
"sv-SE": 93,
|
||||||
"uk": 94,
|
"uk": 93,
|
||||||
"ur": 2,
|
"ur": 2,
|
||||||
"zh-Hans": 94,
|
"zh-Hans": 93,
|
||||||
"zh-Hant": 94
|
"zh-Hant": 93
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7107,6 +7107,14 @@ export function useAFFiNEI18N(): {
|
|||||||
* `No new notifications`
|
* `No new notifications`
|
||||||
*/
|
*/
|
||||||
["com.affine.notification.empty"](): string;
|
["com.affine.notification.empty"](): string;
|
||||||
|
/**
|
||||||
|
* `Open workspace`
|
||||||
|
*/
|
||||||
|
["com.affine.notification.invitation-review-approved.open-workspace"](): string;
|
||||||
|
/**
|
||||||
|
* `Accept & Join`
|
||||||
|
*/
|
||||||
|
["com.affine.notification.invitation.accept"](): string;
|
||||||
/**
|
/**
|
||||||
* `Tips`
|
* `Tips`
|
||||||
*/
|
*/
|
||||||
@@ -8474,6 +8482,62 @@ export const TypedTrans: {
|
|||||||
["1"]: JSX.Element;
|
["1"]: JSX.Element;
|
||||||
["2"]: JSX.Element;
|
["2"]: JSX.Element;
|
||||||
}>>;
|
}>>;
|
||||||
|
/**
|
||||||
|
* `<1>{{username}}</1> has accept your invitation`
|
||||||
|
*/
|
||||||
|
["com.affine.notification.invitation-accepted"]: ComponentType<TypedTransProps<{
|
||||||
|
readonly username: string;
|
||||||
|
}, {
|
||||||
|
["1"]: JSX.Element;
|
||||||
|
}>>;
|
||||||
|
/**
|
||||||
|
* `<1>{{username}}</1> has requested to join <2>{{workspaceName}}</2>`
|
||||||
|
*/
|
||||||
|
["com.affine.notification.invitation-review-request"]: ComponentType<TypedTransProps<Readonly<{
|
||||||
|
username: string;
|
||||||
|
workspaceName: string;
|
||||||
|
}>, {
|
||||||
|
["1"]: JSX.Element;
|
||||||
|
["2"]: JSX.Element;
|
||||||
|
}>>;
|
||||||
|
/**
|
||||||
|
* `<1>{{username}}</1> has declined your request to join <2>{{workspaceName}}</2>`
|
||||||
|
*/
|
||||||
|
["com.affine.notification.invitation-review-declined"]: ComponentType<TypedTransProps<Readonly<{
|
||||||
|
username: string;
|
||||||
|
workspaceName: string;
|
||||||
|
}>, {
|
||||||
|
["1"]: JSX.Element;
|
||||||
|
["2"]: JSX.Element;
|
||||||
|
}>>;
|
||||||
|
/**
|
||||||
|
* `<1>{{username}}</1> has approved your request to join <2>{{workspaceName}}</2>`
|
||||||
|
*/
|
||||||
|
["com.affine.notification.invitation-review-approved"]: ComponentType<TypedTransProps<Readonly<{
|
||||||
|
username: string;
|
||||||
|
workspaceName: string;
|
||||||
|
}>, {
|
||||||
|
["1"]: JSX.Element;
|
||||||
|
["2"]: JSX.Element;
|
||||||
|
}>>;
|
||||||
|
/**
|
||||||
|
* `There is an issue regarding your invitation to <1>{{workspaceName}}</1> `
|
||||||
|
*/
|
||||||
|
["com.affine.notification.invitation-blocked"]: ComponentType<TypedTransProps<{
|
||||||
|
readonly workspaceName: string;
|
||||||
|
}, {
|
||||||
|
["1"]: JSX.Element;
|
||||||
|
}>>;
|
||||||
|
/**
|
||||||
|
* `<1>{{username}}</1> invited you to join <2>{{workspaceName}}</2>`
|
||||||
|
*/
|
||||||
|
["com.affine.notification.invitation"]: ComponentType<TypedTransProps<Readonly<{
|
||||||
|
username: string;
|
||||||
|
workspaceName: string;
|
||||||
|
}>, {
|
||||||
|
["1"]: JSX.Element;
|
||||||
|
["2"]: JSX.Element;
|
||||||
|
}>>;
|
||||||
/**
|
/**
|
||||||
* `Unable to join <1/> <2>{{workspaceName}}</2> due to insufficient seats available.`
|
* `Unable to join <1/> <2>{{workspaceName}}</2> due to insufficient seats available.`
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1767,6 +1767,14 @@
|
|||||||
"com.affine.notification.unsupported": "Unsupported message",
|
"com.affine.notification.unsupported": "Unsupported message",
|
||||||
"com.affine.notification.mention": "<1>{{username}}</1> mentioned you in <2>{{docTitle}}</2>",
|
"com.affine.notification.mention": "<1>{{username}}</1> mentioned you in <2>{{docTitle}}</2>",
|
||||||
"com.affine.notification.empty": "No new notifications",
|
"com.affine.notification.empty": "No new notifications",
|
||||||
|
"com.affine.notification.invitation-accepted": "<1>{{username}}</1> has accept your invitation",
|
||||||
|
"com.affine.notification.invitation-review-request": "<1>{{username}}</1> has requested to join <2>{{workspaceName}}</2>",
|
||||||
|
"com.affine.notification.invitation-review-declined": "<1>{{username}}</1> has declined your request to join <2>{{workspaceName}}</2>",
|
||||||
|
"com.affine.notification.invitation-review-approved": "<1>{{username}}</1> has approved your request to join <2>{{workspaceName}}</2>",
|
||||||
|
"com.affine.notification.invitation-review-approved.open-workspace": "Open workspace",
|
||||||
|
"com.affine.notification.invitation-blocked": "There is an issue regarding your invitation to <1>{{workspaceName}}</1> ",
|
||||||
|
"com.affine.notification.invitation": "<1>{{username}}</1> invited you to join <2>{{workspaceName}}</2>",
|
||||||
|
"com.affine.notification.invitation.accept": "Accept & Join",
|
||||||
"tips": "Tips",
|
"tips": "Tips",
|
||||||
"Template": "Template",
|
"Template": "Template",
|
||||||
"com.affine.template-list.delete": "Delete Template",
|
"com.affine.template-list.delete": "Delete Template",
|
||||||
|
|||||||
Reference in New Issue
Block a user