a tool for shared writing and social publishing
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

add basic subscribers view

+64
+1
app/api/rpc/[command]/get_publication_data.ts
··· 20 20 .select( 21 21 `*, 22 22 documents_in_publications(documents(*)), 23 + publication_subscriptions(*, identities(bsky_profiles(*))), 23 24 publication_domains(*), 24 25 leaflets_in_publications(*, 25 26 permission_tokens(*,
+61
app/lish/[did]/[publication]/dashboard/PublicationSubscribers.tsx
··· 1 + "use client"; 2 + import { AppBskyActorProfile } from "lexicons/api"; 3 + import { usePublicationData } from "./PublicationSWRProvider"; 4 + import { blobRefToSrc } from "src/utils/blobRefToSrc"; 5 + 6 + export function PublicationSubscribers() { 7 + let { data: publication } = usePublicationData(); 8 + if (!publication) return <div>null</div>; 9 + if (publication.publication_subscriptions.length === 0) 10 + return <div>No subscribers yet!</div>; 11 + return ( 12 + <div> 13 + <h2>{publication.publication_subscriptions.length} Subscribers </h2> 14 + <div className="flex gap-2 flex-col"> 15 + {publication.publication_subscriptions 16 + .sort((a, b) => { 17 + return b.created_at.localeCompare(a.created_at); 18 + }) 19 + .map((subscriber, index) => { 20 + if (!subscriber.identities?.bsky_profiles) return null; 21 + let handle = subscriber.identities?.bsky_profiles.handle; 22 + let profile = subscriber.identities?.bsky_profiles 23 + ?.record as AppBskyActorProfile.Record | null; 24 + if (!profile) return null; 25 + return ( 26 + <div key={subscriber.identities.bsky_profiles?.did}> 27 + <a 28 + target="_blank" 29 + href={`https://bsky.app/profile/${subscriber.identities.bsky_profiles?.did}`} 30 + className="flex text-primary p-2 gap-1" 31 + > 32 + <div className="flex flex-row gap-2"> 33 + {profile.avatar && ( 34 + <img 35 + className="rounded-full w-8 h-8" 36 + src={ 37 + profile?.avatar && 38 + blobRefToSrc( 39 + profile.avatar.ref, 40 + subscriber.identities.bsky_profiles?.did, 41 + ) 42 + } 43 + alt={profile.displayName} 44 + /> 45 + )} 46 + <div className="flex flex-col gap-1"> 47 + <h3>{profile.displayName}</h3> 48 + <p>@{handle}</p> 49 + </div> 50 + </div> 51 + </a> 52 + {index !== publication.publication_subscriptions.length - 1 && ( 53 + <hr className="border-border" /> 54 + )} 55 + </div> 56 + ); 57 + })} 58 + </div> 59 + </div> 60 + ); 61 + }
+2
app/lish/[did]/[publication]/dashboard/page.tsx
··· 15 15 import { PublicationSWRDataProvider } from "./PublicationSWRProvider"; 16 16 import { PublishedPostsList } from "./PublishedPostsLists"; 17 17 import { PubLeafletPublication } from "lexicons/api"; 18 + import { PublicationSubscribers } from "./PublicationSubscribers"; 18 19 19 20 export async function generateMetadata(props: { 20 21 params: Promise<{ publication: string; did: string }>; ··· 88 89 tabs={{ 89 90 Drafts: <DraftList />, 90 91 Published: <PublishedPostsList />, 92 + Subscribers: <PublicationSubscribers />, 91 93 }} 92 94 defaultTab={"Drafts"} 93 95 />