diff --git a/components/IdentityProvider.tsx b/components/IdentityProvider.tsx --- a/components/IdentityProvider.tsx +++ b/components/IdentityProvider.tsx @@ -1,8 +1,9 @@ "use client"; import { getIdentityData } from "actions/getIdentityData"; -import { createContext, useContext } from "react"; +import { createContext, useContext, useEffect } from "react"; import useSWR, { KeyedMutator, mutate } from "swr"; import { DashboardState } from "./PageLayouts/DashboardLayout"; +import { supabaseBrowserClient } from "supabase/browserClient"; export type InterfaceState = { dashboards: { [id: string]: DashboardState | undefined }; @@ -20,6 +21,18 @@ let { data: identity, mutate } = useSWR("identity", () => getIdentityData(), { fallbackData: props.initialValue, }); + useEffect(() => { + if (!identity?.atp_did) return; + let supabase = supabaseBrowserClient(); + let channel = supabase.channel(`identity.atp_did:${identity.atp_did}`); + channel.on("broadcast", { event: "notification" }, () => { + mutate(); + }); + channel.subscribe(); + return () => { + channel.unsubscribe(); + }; + }, [identity?.atp_did]); return ( {props.children} diff --git a/src/notifications.ts b/src/notifications.ts --- a/src/notifications.ts +++ b/src/notifications.ts @@ -127,3 +127,13 @@ ), })); } + +export async function pingIdentityToUpdateNotification(did: string) { + let channel = supabaseServerClient.channel(`identity.atp_did:${did}`); + await channel.send({ + type: "broadcast", + event: "notification", + payload: { message: "poke" }, + }); + await supabaseServerClient.removeChannel(channel); +} diff --git a/app/(home-pages)/notifications/NotificationList.tsx b/app/(home-pages)/notifications/NotificationList.tsx --- a/app/(home-pages)/notifications/NotificationList.tsx +++ b/app/(home-pages)/notifications/NotificationList.tsx @@ -5,6 +5,7 @@ import { useEffect, createContext } from "react"; import { markAsRead } from "./getNotifications"; import { ReplyNotification } from "./ReplyNotification"; +import { useIdentityData } from "components/IdentityProvider"; export function NotificationList({ notifications, @@ -13,9 +14,11 @@ notifications: HydratedNotification[]; compact?: boolean; }) { + let { mutate } = useIdentityData(); useEffect(() => { - setTimeout(() => { - markAsRead(); + setTimeout(async () => { + await markAsRead(); + mutate(); }, 500); }, []); diff --git a/app/lish/[did]/[publication]/[rkey]/Interactions/Comments/commentAction.ts b/app/lish/[did]/[publication]/[rkey]/Interactions/Comments/commentAction.ts --- a/app/lish/[did]/[publication]/[rkey]/Interactions/Comments/commentAction.ts +++ b/app/lish/[did]/[publication]/[rkey]/Interactions/Comments/commentAction.ts @@ -8,7 +8,10 @@ import { AtUri, lexToJson, Un$Typed } from "@atproto/api"; import { supabaseServerClient } from "supabase/serverClient"; import { Json } from "supabase/database.types"; -import { Notification } from "src/notifications"; +import { + Notification, + pingIdentityToUpdateNotification, +} from "src/notifications"; import { v7 } from "uuid"; export async function publishComment(args: { @@ -68,30 +71,23 @@ }) .select(); let notifications: Notification[] = []; - if ( - !args.comment.replyTo && - new AtUri(args.document).host !== credentialSession.did - ) + let recipient = args.comment.replyTo + ? new AtUri(args.comment.replyTo).host + : new AtUri(args.document).host; + if (recipient !== credentialSession.did) { notifications.push({ id: v7(), - recipient: new AtUri(args.document).host, - data: { type: "comment", comment_uri: uri.toString() }, - }); - if ( - args.comment.replyTo && - new AtUri(args.comment.replyTo).host !== credentialSession.did - ) - notifications.push({ - id: v7(), - recipient: new AtUri(args.comment.replyTo).host, + recipient, data: { type: "comment", comment_uri: uri.toString(), parent_uri: args.comment.replyTo, }, }); - // SOMEDAY: move this out the action with inngest or workflows - await supabaseServerClient.from("notifications").insert(notifications); + // SOMEDAY: move this out the action with inngest or workflows + await supabaseServerClient.from("notifications").insert(notifications); + await pingIdentityToUpdateNotification(recipient); + } return { record: data?.[0].record as Json,