Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

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

Fix orphaned feed slices, handle blocks (#4944)

* Fix orphaned feed slices, handle blocks

* Revert to filerting out orphan threads

* Support NotFoundPost views too

* Just kidding, use ReplyRef.root as source of grandparent data

* Fixes

authored by

Eric Bailey and committed by
GitHub
3976d673 2939ee7d

+48 -8
+26 -5
src/lib/api/feed-manip.ts
··· 23 23 record: AppBskyFeedPost.Record 24 24 parentAuthor: AppBskyActorDefs.ProfileViewBasic | undefined 25 25 isParentBlocked: boolean 26 + isParentNotFound: boolean 26 27 } 27 28 28 29 type AuthorContext = { ··· 68 69 } 69 70 const parent = reply?.parent 70 71 const isParentBlocked = AppBskyFeedDefs.isBlockedPost(parent) 72 + const isParentNotFound = AppBskyFeedDefs.isNotFoundPost(parent) 71 73 let parentAuthor: AppBskyActorDefs.ProfileViewBasic | undefined 72 74 if (AppBskyFeedDefs.isPostView(parent)) { 73 75 parentAuthor = parent.author ··· 77 79 record: post.record, 78 80 parentAuthor, 79 81 isParentBlocked, 82 + isParentNotFound, 80 83 }) 81 84 if (!reply || reason) { 82 85 return ··· 89 92 this.isOrphan = true 90 93 return 91 94 } 95 + const root = reply.root 96 + const rootIsView = 97 + AppBskyFeedDefs.isPostView(root) || 98 + AppBskyFeedDefs.isBlockedPost(root) || 99 + AppBskyFeedDefs.isNotFoundPost(root) 100 + /* 101 + * If the parent is also the root, we just so happen to have the data we 102 + * need to compute if the parent's parent (grandparent) is blocked. This 103 + * doesn't always happen, of course, but we can take advantage of it when 104 + * it does. 105 + */ 106 + const grandparent = 107 + rootIsView && parent.record.reply?.parent.uri === root.uri 108 + ? root 109 + : undefined 92 110 const grandparentAuthor = reply.grandparentAuthor 93 111 const isGrandparentBlocked = Boolean( 94 - grandparentAuthor?.viewer?.blockedBy || 95 - grandparentAuthor?.viewer?.blocking || 96 - grandparentAuthor?.viewer?.blockingByList, 112 + grandparent && AppBskyFeedDefs.isBlockedPost(grandparent), 113 + ) 114 + const isGrandparentNotFound = Boolean( 115 + grandparent && AppBskyFeedDefs.isNotFoundPost(grandparent), 97 116 ) 98 117 this.items.unshift({ 99 118 post: parent, 100 119 record: parent.record, 101 120 parentAuthor: grandparentAuthor, 102 121 isParentBlocked: isGrandparentBlocked, 122 + isParentNotFound: isGrandparentNotFound, 103 123 }) 104 124 if (isGrandparentBlocked) { 105 125 this.isOrphan = true 106 - // Keep going, it might still have a root. 126 + // Keep going, it might still have a root, and we need this for thread 127 + // de-deduping 107 128 } 108 - const root = reply.root 109 129 if ( 110 130 !AppBskyFeedDefs.isPostView(root) || 111 131 !AppBskyFeedPost.isRecord(root.record) || ··· 121 141 post: root, 122 142 record: root.record, 123 143 isParentBlocked: false, 144 + isParentNotFound: false, 124 145 parentAuthor: undefined, 125 146 }) 126 147 if (parent.record.reply?.parent.uri !== root.uri) {
+2
src/state/queries/post-feed.ts
··· 80 80 moderation: ModerationDecision 81 81 parentAuthor?: AppBskyActorDefs.ProfileViewBasic 82 82 isParentBlocked?: boolean 83 + isParentNotFound?: boolean 83 84 } 84 85 85 86 export interface FeedPostSlice { ··· 326 327 moderation: moderations[i], 327 328 parentAuthor: item.parentAuthor, 328 329 isParentBlocked: item.isParentBlocked, 330 + isParentNotFound: item.isParentNotFound, 329 331 } 330 332 return feedPostSliceItem 331 333 }),
+16 -3
src/view/com/posts/FeedItem.tsx
··· 63 63 feedContext: string | undefined 64 64 hideTopBorder?: boolean 65 65 isParentBlocked?: boolean 66 + isParentNotFound?: boolean 66 67 } 67 68 68 69 export function FeedItem({ ··· 78 79 isThreadParent, 79 80 hideTopBorder, 80 81 isParentBlocked, 82 + isParentNotFound, 81 83 }: FeedItemProps & {post: AppBskyFeedDefs.PostView}): React.ReactNode { 82 84 const postShadowed = usePostShadow(post) 83 85 const richText = useMemo( ··· 109 111 isThreadParent={isThreadParent} 110 112 hideTopBorder={hideTopBorder} 111 113 isParentBlocked={isParentBlocked} 114 + isParentNotFound={isParentNotFound} 112 115 /> 113 116 ) 114 117 } ··· 129 132 isThreadParent, 130 133 hideTopBorder, 131 134 isParentBlocked, 135 + isParentNotFound, 132 136 }: FeedItemProps & { 133 137 richText: RichTextAPI 134 138 post: Shadow<AppBskyFeedDefs.PostView> ··· 344 348 postHref={href} 345 349 onOpenAuthor={onOpenAuthor} 346 350 /> 347 - {showReplyTo && (parentAuthor || isParentBlocked) && ( 348 - <ReplyToLabel blocked={isParentBlocked} profile={parentAuthor} /> 349 - )} 351 + {showReplyTo && 352 + (parentAuthor || isParentBlocked || isParentNotFound) && ( 353 + <ReplyToLabel 354 + blocked={isParentBlocked} 355 + notFound={isParentNotFound} 356 + profile={parentAuthor} 357 + /> 358 + )} 350 359 <LabelsOnMyPost post={post} /> 351 360 <PostContent 352 361 moderation={moderation} ··· 438 447 function ReplyToLabel({ 439 448 profile, 440 449 blocked, 450 + notFound, 441 451 }: { 442 452 profile: AppBskyActorDefs.ProfileViewBasic | undefined 443 453 blocked?: boolean 454 + notFound?: boolean 444 455 }) { 445 456 const pal = usePalette('default') 446 457 const {currentAccount} = useSession() ··· 448 459 let label 449 460 if (blocked) { 450 461 label = <Trans context="description">Reply to a blocked post</Trans> 462 + } else if (notFound) { 463 + label = <Trans context="description">Reply to an unknown post</Trans> 451 464 } else if (profile != null) { 452 465 const isMe = profile.did === currentAccount?.did 453 466 if (isMe) {
+4
src/view/com/posts/FeedSlice.tsx
··· 36 36 isThreadChild={isThreadChildAt(slice.items, 0)} 37 37 hideTopBorder={hideTopBorder} 38 38 isParentBlocked={slice.items[0].isParentBlocked} 39 + isParentNotFound={slice.items[0].isParentNotFound} 39 40 /> 40 41 <ViewFullThread uri={slice.items[0].uri} /> 41 42 <FeedItem ··· 53 54 isThreadParent={isThreadParentAt(slice.items, beforeLast)} 54 55 isThreadChild={isThreadChildAt(slice.items, beforeLast)} 55 56 isParentBlocked={slice.items[beforeLast].isParentBlocked} 57 + isParentNotFound={slice.items[beforeLast].isParentNotFound} 56 58 /> 57 59 <FeedItem 58 60 key={slice.items[last]._reactKey} ··· 66 68 isThreadParent={isThreadParentAt(slice.items, last)} 67 69 isThreadChild={isThreadChildAt(slice.items, last)} 68 70 isParentBlocked={slice.items[last].isParentBlocked} 71 + isParentNotFound={slice.items[last].isParentNotFound} 69 72 isThreadLastChild 70 73 /> 71 74 </> ··· 90 93 isThreadChildAt(slice.items, i) && slice.items.length === i + 1 91 94 } 92 95 isParentBlocked={slice.items[i].isParentBlocked} 96 + isParentNotFound={slice.items[i].isParentNotFound} 93 97 hideTopBorder={hideTopBorder && i === 0} 94 98 /> 95 99 ))}