diff --git a/src/lib/api/feed-manip.ts b/src/lib/api/feed-manip.ts index c2b80ca042..6e78283ea0 100644 --- a/src/lib/api/feed-manip.ts +++ b/src/lib/api/feed-manip.ts @@ -41,6 +41,8 @@ export class FeedViewPostsSlice { isFallbackMarker: boolean isOrphan: boolean rootUri: string + participantDids: Set = new Set() + additionalParticipantProfiles: AppBskyActorDefs.ProfileViewBasic[] = [] constructor(feedPost: FeedViewPost) { const {post, reply, reason} = feedPost @@ -211,12 +213,19 @@ export class FeedViewPostsSlice { rootAuthor, } } + + getAuthorDids(): string[] { + return Object.values(this.getAuthors()) + .map(p => (p ? p.did : undefined)) + .filter(Boolean) as string[] + } } export class FeedTuner { seenKeys: Set = new Set() seenUris: Set = new Set() - seenRootUris: Set = new Set() + seenRootUris: Map}> = new Map() + profileMap: Map = new Map() constructor(public tunerFns: FeedTunerFn[]) {} @@ -345,13 +354,36 @@ export class FeedTuner { dryRun: boolean, ): FeedViewPostsSlice[] { for (let i = 0; i < slices.length; i++) { - const rootUri = slices[i].rootUri - if (!slices[i].isRepost && tuner.seenRootUris.has(rootUri)) { + const slice = slices[i] + const rootUri = slice.rootUri + const authorsDids = slice.getAuthorDids() + if (!slice.isRepost && tuner.seenRootUris.has(rootUri)) { + const seen = tuner.seenRootUris.get(rootUri)! + for (const did of authorsDids) { + seen.participantDids.add(did) + } slices.splice(i, 1) i-- } else { if (!dryRun) { - tuner.seenRootUris.add(rootUri) + const participantDids = new Set(authorsDids) + slice.participantDids = participantDids + tuner.seenRootUris.set(rootUri, {participantDids}) + } + } + for (const profile of Object.values(slice.getAuthors())) { + if (profile) { + tuner.profileMap.set(profile.did, profile) + } + } + } + for (const slice of slices) { + const visibleAuthors = new Set(slice.getAuthorDids()) + for (const userDid of slice.participantDids) { + if (visibleAuthors.has(userDid)) continue + const profile = tuner.profileMap.get(userDid) + if (profile) { + slice.additionalParticipantProfiles.push(profile) } } } diff --git a/src/state/queries/post-feed.ts b/src/state/queries/post-feed.ts index ee3e2c14d2..b31c18583a 100644 --- a/src/state/queries/post-feed.ts +++ b/src/state/queries/post-feed.ts @@ -94,6 +94,7 @@ export interface FeedPostSlice { | AppBskyFeedDefs.ReasonRepost | ReasonFeedSource | {[k: string]: unknown; $type: string} + additionalParticipantProfiles?: AppBskyActorDefs.ProfileViewBasic[] } export interface FeedPageUnselected { @@ -318,6 +319,8 @@ export function usePostFeedQuery( isFallbackMarker: slice.isFallbackMarker, feedContext: slice.feedContext, reason: slice.reason, + additionalParticipantProfiles: + slice.additionalParticipantProfiles, items: slice.items.map((item, i) => { const feedPostSliceItem: FeedPostSliceItem = { _reactKey: `${slice._reactKey}-${i}-${item.post.uri}`, diff --git a/src/view/com/posts/FeedItem.tsx b/src/view/com/posts/FeedItem.tsx index e90e8b885c..3359d7c637 100644 --- a/src/view/com/posts/FeedItem.tsx +++ b/src/view/com/posts/FeedItem.tsx @@ -84,9 +84,11 @@ export function FeedItem({ isParentBlocked, isParentNotFound, rootPost, + additionalParticipantProfiles, }: FeedItemProps & { post: AppBskyFeedDefs.PostView rootPost: AppBskyFeedDefs.PostView + additionalParticipantProfiles?: AppBskyActorDefs.ProfileViewBasic[] }): React.ReactNode { const postShadowed = usePostShadow(post) const richText = useMemo( @@ -120,6 +122,7 @@ export function FeedItem({ isParentBlocked={isParentBlocked} isParentNotFound={isParentNotFound} rootPost={rootPost} + additionalParticipantProfiles={additionalParticipantProfiles} /> ) } @@ -142,10 +145,12 @@ let FeedItemInner = ({ isParentBlocked, isParentNotFound, rootPost, + additionalParticipantProfiles, }: FeedItemProps & { richText: RichTextAPI post: Shadow rootPost: AppBskyFeedDefs.PostView + additionalParticipantProfiles?: AppBskyActorDefs.ProfileViewBasic[] }): React.ReactNode => { const queryClient = useQueryClient() const {openComposer} = useComposerControls() @@ -392,6 +397,16 @@ let FeedItemInner = ({ feedContext={feedContext} threadgateRecord={threadgateRecord} /> + + {additionalParticipantProfiles?.length && ( + + + {additionalParticipantProfiles + .map(p => p.displayName) + .join(', ')} + + + )} diff --git a/src/view/com/posts/FeedSlice.tsx b/src/view/com/posts/FeedSlice.tsx index 0920026f60..c9e0d0558e 100644 --- a/src/view/com/posts/FeedSlice.tsx +++ b/src/view/com/posts/FeedSlice.tsx @@ -38,6 +38,7 @@ let FeedSlice = ({ isParentBlocked={slice.items[0].isParentBlocked} isParentNotFound={slice.items[0].isParentNotFound} rootPost={slice.items[0].post} + additionalParticipantProfiles={slice.additionalParticipantProfiles} /> ))}