From 8afc0e8f3e5648b59c1b10dc6522b02a6ea5dc9f Mon Sep 17 00:00:00 2001 From: Jared Pereira Date: Mon, 10 Nov 2025 14:02:11 -0500 Subject: [PATCH] wire up notifications --- actions/getIdentityData.ts | 2 + .../notifications/CommentNotication.tsx | 27 +++++----- .../notifications/MentionNotification.tsx | 10 +++- .../notifications/Notification.tsx | 10 ++-- .../notifications/NotificationList.tsx | 36 +++++++++++++ .../notifications/ReplyNotification.tsx | 5 +- .../notifications/getNotifications.ts | 28 ++++++++++ app/(home-pages)/notifications/page.tsx | 14 +---- components/ActionBar/Navigation.tsx | 54 +++++++++++++++---- src/notifications.ts | 11 +++- 10 files changed, 153 insertions(+), 44 deletions(-) create mode 100644 app/(home-pages)/notifications/NotificationList.tsx create mode 100644 app/(home-pages)/notifications/getNotifications.ts diff --git a/actions/getIdentityData.ts b/actions/getIdentityData.ts index c9c407b5..7224413b 100644 --- a/actions/getIdentityData.ts +++ b/actions/getIdentityData.ts @@ -17,6 +17,7 @@ export async function uncachedGetIdentityData() { identities( *, bsky_profiles(*), + notifications(count), publication_subscriptions(*), custom_domains!custom_domains_identity_id_fkey(publication_domains(*), *), home_leaflet:permission_tokens!identities_home_page_fkey(*, permission_token_rights(*, @@ -33,6 +34,7 @@ export async function uncachedGetIdentityData() { ) )`, ) + .eq("identities.notifications.read", false) .eq("id", auth_token) .eq("confirmed", true) .single() diff --git a/app/(home-pages)/notifications/CommentNotication.tsx b/app/(home-pages)/notifications/CommentNotication.tsx index eace88c3..3b95e394 100644 --- a/app/(home-pages)/notifications/CommentNotication.tsx +++ b/app/(home-pages)/notifications/CommentNotication.tsx @@ -3,6 +3,7 @@ import { AppBskyActorProfile, PubLeafletComment, PubLeafletDocument, + PubLeafletPublication, } from "lexicons/api"; import { HydratedCommentNotification } from "src/notifications"; import { blobRefToSrc } from "src/utils/blobRefToSrc"; @@ -20,17 +21,18 @@ export const CommentNotification = (props: HydratedCommentNotification) => { let commentRecord = props.commentData.record as PubLeafletComment.Record; let profileRecord = props.commentData.bsky_profiles ?.record as AppBskyActorProfile.Record; - const displayName = profileRecord.displayName || "Someone"; + const displayName = + profileRecord.displayName || + props.commentData.bsky_profiles?.handle || + "Someone"; + const publication = props.commentData.documents?.documents_in_publications[0] + ?.publications?.record as PubLeafletPublication.Record; return ( } - actionText={ - <> - {displayName} commented on your post - - } + actionText={<>{displayName} commented on your post} content={ - + { props.commentData.bsky_profiles?.did || "", ) } - displayName={ - profileRecord?.displayName || - props.commentData.bsky_profiles?.handle || - "Someone" - } + displayName={displayName} index={[]} plaintext={commentRecord.plaintext} facets={commentRecord.facets} @@ -61,7 +59,10 @@ export const DummyCommentNotification = () => { icon={} actionText={<>celine commented on your post} content={ - + { icon={} actionText={<>celine mentioned your post} content={ - + I'm just gonna put the description here. The surrounding context is just sort of a pain to figure out
@@ -28,7 +31,10 @@ export const DummyUserMentionNotification = () => { icon={} actionText={<>celine mentioned you} content={ - +
...llo this is the content of a post or whatever here it comes{" "} @celine and here it diff --git a/app/(home-pages)/notifications/Notification.tsx b/app/(home-pages)/notifications/Notification.tsx index 5ca9d9ef..a20f27bb 100644 --- a/app/(home-pages)/notifications/Notification.tsx +++ b/app/(home-pages)/notifications/Notification.tsx @@ -1,6 +1,10 @@ import { Avatar } from "components/Avatar"; import { BaseTextBlock } from "app/lish/[did]/[publication]/[rkey]/BaseTextBlock"; -import { PubLeafletRichtextFacet } from "lexicons/api"; +import { + PubLeafletDocument, + PubLeafletPublication, + PubLeafletRichtextFacet, +} from "lexicons/api"; export const Notification = (props: { icon: React.ReactNode; @@ -26,6 +30,7 @@ export const Notification = (props: { export const ContentLayout = (props: { children: React.ReactNode; postTitle: string; + publication: PubLeafletPublication.Record; }) => { return (
@@ -36,8 +41,7 @@ export const ContentLayout = (props: {
-
- Pub Name Here + {props.publication.name}
); diff --git a/app/(home-pages)/notifications/NotificationList.tsx b/app/(home-pages)/notifications/NotificationList.tsx new file mode 100644 index 00000000..8c22f80a --- /dev/null +++ b/app/(home-pages)/notifications/NotificationList.tsx @@ -0,0 +1,36 @@ +"use client"; + +import { HydratedNotification } from "src/notifications"; +import { CommentNotification } from "./CommentNotication"; +import { useEntity, useReplicache } from "src/replicache"; +import { useEffect } from "react"; +import { markAsRead } from "./getNotifications"; + +export function NotificationList({ + notifications, +}: { + notifications: HydratedNotification[]; +}) { + useEffect(() => { + setTimeout(() => { + markAsRead(); + }, 500); + }, []); + let { rootEntity } = useReplicache(); + + let showPageBackground = !useEntity(rootEntity, "theme/card-border-hidden") + ?.data.value; + + return ( +
+
+ {notifications.map((n) => { + if (n.type === "comment") { + n; + return ; + } + })} +
+
+ ); +} diff --git a/app/(home-pages)/notifications/ReplyNotification.tsx b/app/(home-pages)/notifications/ReplyNotification.tsx index f272905e..dd806220 100644 --- a/app/(home-pages)/notifications/ReplyNotification.tsx +++ b/app/(home-pages)/notifications/ReplyNotification.tsx @@ -13,7 +13,10 @@ export const DummyReplyNotification = () => { icon={} actionText={<>jared replied to your comment} content={ - + { .select("*") .eq("recipient", identity.atp_did); let notifications = await hydrateNotifications(data || []); - return ( -
-
- {notifications.map((n) => { - if (n.type === "comment") { - n; - return ; - } - })} -
-
- ); + return ; }; diff --git a/components/ActionBar/Navigation.tsx b/components/ActionBar/Navigation.tsx index b1c0b245..5f8b8a50 100644 --- a/components/ActionBar/Navigation.tsx +++ b/components/ActionBar/Navigation.tsx @@ -33,6 +33,12 @@ import { DummyPostMentionNotification, DummyUserMentionNotification, } from "app/(home-pages)/notifications/MentionNotification"; +import useSWR from "swr"; +import { + getNotifications, + markAsRead, +} from "app/(home-pages)/notifications/getNotifications"; +import { DotLoader } from "components/utils/DotLoader"; export type navPages = "home" | "reader" | "pub" | "discover" | "notifications"; @@ -40,11 +46,14 @@ export const DesktopNavigation = (props: { currentPage: navPages; publication?: string; }) => { + let { identity } = useIdentityData(); return (
- - - + {identity?.atp_did && ( + + + + )} - - + {identity?.atp_did && ( + <> + + + + )}
); }; @@ -161,8 +174,12 @@ const DiscoverButton = (props: { current?: boolean }) => { }; export function NotificationButton(props: { current?: boolean }) { - let unreads = true; + let { identity, mutate } = useIdentityData(); + let unreads = identity?.notifications[0]?.count; let isMobile = useIsMobile(); + let { data: notifications, isLoading } = useSWR("notifications", () => + getNotifications(3), + ); // let identity = await getIdentityData(); // if (!identity?.atp_did) return; // let { data } = await supabaseServerClient @@ -173,6 +190,13 @@ export function NotificationButton(props: { current?: boolean }) { return ( { + if (open) { + console.log(open); + await markAsRead(); + mutate(); + } + }} asChild side={isMobile ? "top" : "right"} align={isMobile ? "center" : "start"} @@ -194,11 +218,19 @@ export function NotificationButton(props: { current?: boolean }) { } >
- - - - - + {isLoading ? ( +
+ loading + +
+ ) : ( + notifications?.map((n) => { + if (n.type === "comment") { + n; + return ; + } + }) + )}
> { // Call all hydrators in parallel const [commentNotifications, subscribeNotifications] = await Promise.all([ hydrateCommentNotifications(notifications), @@ -56,7 +61,9 @@ async function hydrateCommentNotifications(notifications: NotificationRow[]) { const commentUris = commentNotifications.map((n) => n.data.comment_uri); const { data: comments } = await supabaseServerClient .from("comments_on_documents") - .select("*,bsky_profiles(*), documents(*)") + .select( + "*,bsky_profiles(*), documents(*, documents_in_publications(publications(*)))", + ) .in("uri", commentUris); return commentNotifications.map((notification) => ({ -- 2.51.2