Show more replies in Following (different heuristic) (#4880)

zio/stable
dan 2024-08-06 16:42:42 +01:00 committed by GitHub
parent 686d5ebb53
commit b291a1ed8a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 79 additions and 15 deletions

View File

@ -25,6 +25,13 @@ type FeedSliceItem = {
isParentBlocked: boolean isParentBlocked: boolean
} }
type AuthorContext = {
author: AppBskyActorDefs.ProfileViewBasic
parentAuthor: AppBskyActorDefs.ProfileViewBasic | undefined
grandparentAuthor: AppBskyActorDefs.ProfileViewBasic | undefined
rootAuthor: AppBskyActorDefs.ProfileViewBasic | undefined
}
export class FeedViewPostsSlice { export class FeedViewPostsSlice {
_reactKey: string _reactKey: string
_feedPost: FeedViewPost _feedPost: FeedViewPost
@ -159,21 +166,29 @@ export class FeedViewPostsSlice {
return !!this.items.find(item => item.post.uri === uri) return !!this.items.find(item => item.post.uri === uri)
} }
getAllAuthors(): AppBskyActorDefs.ProfileViewBasic[] { getAuthors(): AuthorContext {
const feedPost = this._feedPost const feedPost = this._feedPost
const authors = [feedPost.post.author] let author: AppBskyActorDefs.ProfileViewBasic = feedPost.post.author
let parentAuthor: AppBskyActorDefs.ProfileViewBasic | undefined
let grandparentAuthor: AppBskyActorDefs.ProfileViewBasic | undefined
let rootAuthor: AppBskyActorDefs.ProfileViewBasic | undefined
if (feedPost.reply) { if (feedPost.reply) {
if (AppBskyFeedDefs.isPostView(feedPost.reply.parent)) { if (AppBskyFeedDefs.isPostView(feedPost.reply.parent)) {
authors.push(feedPost.reply.parent.author) parentAuthor = feedPost.reply.parent.author
} }
if (feedPost.reply.grandparentAuthor) { if (feedPost.reply.grandparentAuthor) {
authors.push(feedPost.reply.grandparentAuthor) grandparentAuthor = feedPost.reply.grandparentAuthor
} }
if (AppBskyFeedDefs.isPostView(feedPost.reply.root)) { if (AppBskyFeedDefs.isPostView(feedPost.reply.root)) {
authors.push(feedPost.reply.root.author) rootAuthor = feedPost.reply.root.author
} }
} }
return authors return {
author,
parentAuthor,
grandparentAuthor,
rootAuthor,
}
} }
} }
@ -252,7 +267,7 @@ export class FeedTuner {
!slice.isRepost && !slice.isRepost &&
// This is not perfect but it's close as we can get to // This is not perfect but it's close as we can get to
// detecting threads without having to peek ahead. // detecting threads without having to peek ahead.
!areSameAuthor(slice.getAllAuthors()) !areSameAuthor(slice.getAuthors())
) { ) {
slices.splice(i, 1) slices.splice(i, 1)
i-- i--
@ -333,7 +348,7 @@ export class FeedTuner {
if ( if (
slice.isReply && slice.isReply &&
!slice.isRepost && !slice.isRepost &&
!isFollowingAll(slice.getAllAuthors(), userDid) !shouldDisplayReplyInFollowing(slice.getAuthors(), userDid)
) { ) {
slices.splice(i, 1) slices.splice(i, 1)
i-- i--
@ -389,15 +404,64 @@ export class FeedTuner {
} }
} }
function areSameAuthor(authors: AppBskyActorDefs.ProfileViewBasic[]): boolean { function areSameAuthor(authors: AuthorContext): boolean {
const dids = authors.map(a => a.did) const {author, parentAuthor, grandparentAuthor, rootAuthor} = authors
const set = new Set(dids) const authorDid = author.did
return set.size === 1 if (parentAuthor && parentAuthor.did !== authorDid) {
return false
}
if (grandparentAuthor && grandparentAuthor.did !== authorDid) {
return false
}
if (rootAuthor && rootAuthor.did !== authorDid) {
return false
}
return true
} }
function isFollowingAll( function shouldDisplayReplyInFollowing(
authors: AppBskyActorDefs.ProfileViewBasic[], authors: AuthorContext,
userDid: string, userDid: string,
): boolean { ): boolean {
return authors.every(a => a.did === userDid || a.viewer?.following) const {author, parentAuthor, grandparentAuthor, rootAuthor} = authors
if (!isSelfOrFollowing(author, userDid)) {
// Only show replies from self or people you follow.
return false
}
if (!parentAuthor || !grandparentAuthor || !rootAuthor) {
// Don't surface orphaned reply subthreads.
return false
}
if (
parentAuthor.did === author.did &&
grandparentAuthor.did === author.did &&
rootAuthor.did === author.did
) {
// Always show self-threads.
return true
}
// From this point on we need at least one more reason to show it.
if (
parentAuthor.did !== author.did &&
isSelfOrFollowing(parentAuthor, userDid)
) {
return true
}
if (
grandparentAuthor.did !== author.did &&
isSelfOrFollowing(grandparentAuthor, userDid)
) {
return true
}
if (rootAuthor.did !== author.did && isSelfOrFollowing(rootAuthor, userDid)) {
return true
}
return false
}
function isSelfOrFollowing(
profile: AppBskyActorDefs.ProfileViewBasic,
userDid: string,
) {
return Boolean(profile.did === userDid || profile.viewer?.following)
} }