diff --git a/app/(home-pages)/notifications/FollowNotification.tsx b/app/(home-pages)/notifications/FollowNotification.tsx index 9b5e4dc2..dd8b2b74 100644 --- a/app/(home-pages)/notifications/FollowNotification.tsx +++ b/app/(home-pages)/notifications/FollowNotification.tsx @@ -1,17 +1,33 @@ import { Avatar } from "components/Avatar"; import { Notification } from "./Notification"; +import { HydratedSubscribeNotification } from "src/notifications"; +import { blobRefToSrc } from "src/utils/blobRefToSrc"; +import { AppBskyActorProfile, PubLeafletPublication } from "lexicons/api"; + +export const FollowNotification = (props: HydratedSubscribeNotification) => { + const profileRecord = props.subscriptionData?.identities?.bsky_profiles + ?.record as AppBskyActorProfile.Record; + const displayName = + profileRecord?.displayName || + props.subscriptionData?.identities?.bsky_profiles?.handle || + "Someone"; + const pubRecord = props.subscriptionData?.publications + ?.record as PubLeafletPublication.Record; + const avatarSrc = + profileRecord?.avatar?.ref && + blobRefToSrc( + profileRecord.avatar.ref, + props.subscriptionData?.identity || "", + ); -export const DummyFollowNotification = (props: {}) => { - const identity = "celine"; - const pubName = "Pub Name Here"; return ( } + timestamp={props.created_at} + href={`https://${pubRecord?.base_path}`} + icon={} actionText={ <> - {identity} followed {pubName}! + {displayName} subscribed to {pubRecord?.name}! } /> diff --git a/app/(home-pages)/notifications/NotificationList.tsx b/app/(home-pages)/notifications/NotificationList.tsx index f3ab4eff..35a974ba 100644 --- a/app/(home-pages)/notifications/NotificationList.tsx +++ b/app/(home-pages)/notifications/NotificationList.tsx @@ -6,6 +6,7 @@ import { useEffect, createContext } from "react"; import { markAsRead } from "./getNotifications"; import { ReplyNotification } from "./ReplyNotification"; import { useIdentityData } from "components/IdentityProvider"; +import { FollowNotification } from "./FollowNotification"; export function NotificationList({ notifications, @@ -36,6 +37,9 @@ export function NotificationList({ if (n.parentData) return ; return ; } + if (n.type === "subscribe") { + return ; + } })} diff --git a/app/lish/subscribeToPublication.ts b/app/lish/subscribeToPublication.ts index db93ed76..c221800a 100644 --- a/app/lish/subscribeToPublication.ts +++ b/app/lish/subscribeToPublication.ts @@ -12,6 +12,11 @@ import { redirect } from "next/navigation"; import { encodeActionToSearchParam } from "app/api/oauth/[route]/afterSignInActions"; import { Json } from "supabase/database.types"; import { IdResolver } from "@atproto/identity"; +import { + Notification, + pingIdentityToUpdateNotification, +} from "src/notifications"; +import { v7 } from "uuid"; let leafletFeedURI = "at://did:plc:btxrwcaeyodrap5mnjw2fvmz/app.bsky.feed.generator/subscribedPublications"; @@ -46,6 +51,22 @@ export async function subscribeToPublication( publication, identity: credentialSession.did!, }); + + // Create notification for the publication owner + let publicationOwner = new AtUri(publication).host; + if (publicationOwner !== credentialSession.did) { + let notification: Notification = { + id: v7(), + recipient: publicationOwner, + data: { + type: "subscribe", + subscription_uri: record.uri, + }, + }; + await supabaseServerClient.from("notifications").insert(notification); + await pingIdentityToUpdateNotification(publicationOwner); + } + let bsky = new BskyAgent(credentialSession); let [prefs, profile, resolveDid] = await Promise.all([ bsky.app.bsky.actor.getPreferences(), diff --git a/src/notifications.ts b/src/notifications.ts index 450c9c8b..4b6301d6 100644 --- a/src/notifications.ts +++ b/src/notifications.ts @@ -85,17 +85,11 @@ async function hydrateCommentNotifications(notifications: NotificationRow[]) { })); } -export type HydratedSubscribeNotification = { - id: string; - recipient: string; - created_at: string; - type: "subscribe"; - subscription_uri: string; - subscriptionData?: Tables<"publication_subscriptions">; -}; -async function hydrateSubscribeNotifications( - notifications: NotificationRow[], -): Promise { +export type HydratedSubscribeNotification = Awaited< + ReturnType +>[0]; + +async function hydrateSubscribeNotifications(notifications: NotificationRow[]) { const subscribeNotifications = notifications.filter( ( n, @@ -107,13 +101,13 @@ async function hydrateSubscribeNotifications( return []; } - // Fetch subscription data from the database + // Fetch subscription data from the database with related data const subscriptionUris = subscribeNotifications.map( (n) => n.data.subscription_uri, ); const { data: subscriptions } = await supabaseServerClient .from("publication_subscriptions") - .select("*") + .select("*, identities(bsky_profiles(*)), publications(*)") .in("uri", subscriptionUris); return subscribeNotifications.map((notification) => ({ @@ -124,7 +118,7 @@ async function hydrateSubscribeNotifications( subscription_uri: notification.data.subscription_uri, subscriptionData: subscriptions?.find( (s) => s.uri === notification.data.subscription_uri, - ), + )!, })); }