feat: admin notifications
This commit is contained in:
@@ -115,7 +115,11 @@ function NotificationRow({
|
|||||||
n: AppNotification;
|
n: AppNotification;
|
||||||
selfHandle: string;
|
selfHandle: string;
|
||||||
}) {
|
}) {
|
||||||
const display = n.actor_name || (n.actor_handle ? `@${n.actor_handle}` : "Someone");
|
// admin_message rows have no actor — they're a direct message from the team.
|
||||||
|
const isAdmin = n.kind === "admin_message";
|
||||||
|
const display = isAdmin
|
||||||
|
? "Prabhupāda Says"
|
||||||
|
: n.actor_name || (n.actor_handle ? `@${n.actor_handle}` : "Someone");
|
||||||
const message = messageFor(n);
|
const message = messageFor(n);
|
||||||
const unread = !n.read_at;
|
const unread = !n.read_at;
|
||||||
|
|
||||||
@@ -123,11 +127,18 @@ function NotificationRow({
|
|||||||
<div
|
<div
|
||||||
className={cnRow(unread)}
|
className={cnRow(unread)}
|
||||||
>
|
>
|
||||||
<UserAvatar src={n.actor_avatar_url} name={display} />
|
<UserAvatar src={isAdmin ? null : n.actor_avatar_url} name={display} />
|
||||||
<div className="min-w-0 flex-1">
|
<div className="min-w-0 flex-1">
|
||||||
|
{isAdmin ? (
|
||||||
|
<p className="text-sm text-foreground leading-snug whitespace-pre-line">
|
||||||
|
<span className="font-semibold">{display}</span>
|
||||||
|
{n.body ? <span className="block mt-0.5">{n.body}</span> : null}
|
||||||
|
</p>
|
||||||
|
) : (
|
||||||
<p className="text-sm text-foreground leading-snug">
|
<p className="text-sm text-foreground leading-snug">
|
||||||
<span className="font-semibold">{display}</span> {message}
|
<span className="font-semibold">{display}</span> {message}
|
||||||
</p>
|
</p>
|
||||||
|
)}
|
||||||
<p className="text-xs text-muted-foreground mt-0.5">
|
<p className="text-xs text-muted-foreground mt-0.5">
|
||||||
{timeAgo(n.created_at)}
|
{timeAgo(n.created_at)}
|
||||||
</p>
|
</p>
|
||||||
@@ -194,6 +205,8 @@ function messageFor(n: AppNotification): string {
|
|||||||
return "replied to your comment.";
|
return "replied to your comment.";
|
||||||
case "comment_mention":
|
case "comment_mention":
|
||||||
return "mentioned you in a comment.";
|
return "mentioned you in a comment.";
|
||||||
|
case "admin_message":
|
||||||
|
return n.body ?? "sent you a message.";
|
||||||
default:
|
default:
|
||||||
return "sent you a notification.";
|
return "sent you a notification.";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ type IncomingEvent = {
|
|||||||
actor_name?: string;
|
actor_name?: string;
|
||||||
actor_handle?: string;
|
actor_handle?: string;
|
||||||
actor_avatar_url?: string | null;
|
actor_avatar_url?: string | null;
|
||||||
|
body?: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
function messageFor(e: IncomingEvent): string {
|
function messageFor(e: IncomingEvent): string {
|
||||||
@@ -69,6 +70,8 @@ function messageFor(e: IncomingEvent): string {
|
|||||||
return `${who} replied to your comment`;
|
return `${who} replied to your comment`;
|
||||||
case "comment_mention":
|
case "comment_mention":
|
||||||
return `${who} mentioned you in a comment`;
|
return `${who} mentioned you in a comment`;
|
||||||
|
case "admin_message":
|
||||||
|
return e.body || "A message from Prabhupāda Says";
|
||||||
default:
|
default:
|
||||||
return "You have a new notification";
|
return "You have a new notification";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -627,6 +627,9 @@ export type AppNotification = {
|
|||||||
* / reply notifications can deep-link to the post even though the actor
|
* / reply notifications can deep-link to the post even though the actor
|
||||||
* isn't its owner. */
|
* isn't its owner. */
|
||||||
post_author_handle?: string | null;
|
post_author_handle?: string | null;
|
||||||
|
/** Free text for the `admin_message` kind (an admin → user direct message).
|
||||||
|
* Absent on every event-driven kind. */
|
||||||
|
body?: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const notifications = {
|
export const notifications = {
|
||||||
|
|||||||
Reference in New Issue
Block a user