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
}
type AuthorContext = {
author: AppBskyActorDefs.ProfileViewBasic
parentAuthor: AppBskyActorDefs.ProfileViewBasic | undefined
grandparentAuthor: AppBskyActorDefs.ProfileViewBasic | undefined
rootAuthor: AppBskyActorDefs.ProfileViewBasic | undefined
}
export class FeedViewPostsSlice {
_reactKey: string
_feedPost: FeedViewPost
@ -159,21 +166,29 @@ export class FeedViewPostsSlice {
return !!this.items.find(item => item.post.uri === uri)
}
getAllAuthors(): AppBskyActorDefs.ProfileViewBasic[] {
getAuthors(): AuthorContext {
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 (AppBskyFeedDefs.isPostView(feedPost.reply.parent)) {
authors.push(feedPost.reply.parent.author)
parentAuthor = feedPost.reply.parent.author
}
if (feedPost.reply.grandparentAuthor) {
authors.push(feedPost.reply.grandparentAuthor)
grandparentAuthor = feedPost.reply.grandparentAuthor
}
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 &&
// This is not perfect but it's close as we can get to
// detecting threads without having to peek ahead.
!areSameAuthor(slice.getAllAuthors())
!areSameAuthor(slice.getAuthors())
) {
slices.splice(i, 1)
i--
@ -333,7 +348,7 @@ export class FeedTuner {
if (
slice.isReply &&
!slice.isRepost &&
!isFollowingAll(slice.getAllAuthors(), userDid)
!shouldDisplayReplyInFollowing(slice.getAuthors(), userDid)
) {
slices.splice(i, 1)
i--
@ -389,15 +404,64 @@ export class FeedTuner {
}
}
function areSameAuthor(authors: AppBskyActorDefs.ProfileViewBasic[]): boolean {
const dids = authors.map(a => a.did)
const set = new Set(dids)
return set.size === 1
function areSameAuthor(authors: AuthorContext): boolean {
const {author, parentAuthor, grandparentAuthor, rootAuthor} = authors
const authorDid = author.did
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(
authors: AppBskyActorDefs.ProfileViewBasic[],
function shouldDisplayReplyInFollowing(
authors: AuthorContext,
userDid: string,
): 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)
}