Fix up traversal metadata
This commit is contained in:
@@ -4,7 +4,7 @@ import {useLingui} from '@lingui/react'
|
|||||||
|
|
||||||
import {makeProfileLink} from '#/lib/routes/links'
|
import {makeProfileLink} from '#/lib/routes/links'
|
||||||
import {type PostThreadParams, type Slice} from '#/state/queries/usePostThread'
|
import {type PostThreadParams, type Slice} from '#/state/queries/usePostThread'
|
||||||
import {TREE_AVI_WIDTH,TREE_INDENT} from '#/screens/PostThread/const'
|
import {TREE_AVI_WIDTH, TREE_INDENT} from '#/screens/PostThread/const'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
import {CirclePlus_Stroke2_Corner0_Rounded as CirclePlus} from '#/components/icons/CirclePlus'
|
import {CirclePlus_Stroke2_Corner0_Rounded as CirclePlus} from '#/components/icons/CirclePlus'
|
||||||
import {Link} from '#/components/Link'
|
import {Link} from '#/components/Link'
|
||||||
@@ -20,7 +20,7 @@ export function ReadMore({
|
|||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const isTreeView = view === 'tree'
|
const isTreeView = view === 'tree'
|
||||||
const indentCount = item.indent - 1
|
const indentCount = Math.max(0, item.indent - 1)
|
||||||
|
|
||||||
const treeIndents = isTreeView ? (
|
const treeIndents = isTreeView ? (
|
||||||
Array.from(Array(indentCount)).map((_, n: number) => (
|
Array.from(Array(indentCount)).map((_, n: number) => (
|
||||||
|
|||||||
@@ -8,7 +8,12 @@ import {
|
|||||||
HiddenReplyKind,
|
HiddenReplyKind,
|
||||||
type PostThreadParams,
|
type PostThreadParams,
|
||||||
type Slice,
|
type Slice,
|
||||||
|
type TraversalMetadata,
|
||||||
} from '#/state/queries/usePostThread/types'
|
} from '#/state/queries/usePostThread/types'
|
||||||
|
import {
|
||||||
|
getPostRecord,
|
||||||
|
getPostTraversalMetadata,
|
||||||
|
} from '#/state/queries/usePostThread/utils'
|
||||||
import * as views from '#/state/queries/usePostThread/views'
|
import * as views from '#/state/queries/usePostThread/views'
|
||||||
|
|
||||||
export function flatten(
|
export function flatten(
|
||||||
@@ -168,6 +173,7 @@ export function sort(
|
|||||||
const items: Slice[] = []
|
const items: Slice[] = []
|
||||||
const hidden: Slice[] = []
|
const hidden: Slice[] = []
|
||||||
const muted: Slice[] = []
|
const muted: Slice[] = []
|
||||||
|
const postDataMap = new Map<string, TraversalMetadata | undefined>()
|
||||||
|
|
||||||
traversal: for (let i = 0; i < thread.length; i++) {
|
traversal: for (let i = 0; i < thread.length; i++) {
|
||||||
const item = thread[i]
|
const item = thread[i]
|
||||||
@@ -193,6 +199,8 @@ export function sort(
|
|||||||
) {
|
) {
|
||||||
items.push(views.threadPostBlocked(item))
|
items.push(views.threadPostBlocked(item))
|
||||||
} else if (AppBskyUnspeccedGetPostThreadV2.isThreadItemPost(item.value)) {
|
} else if (AppBskyUnspeccedGetPostThreadV2.isThreadItemPost(item.value)) {
|
||||||
|
postDataMap.set(item.uri, getPostTraversalMetadata(item))
|
||||||
|
|
||||||
items.push(
|
items.push(
|
||||||
views.threadPost({
|
views.threadPost({
|
||||||
uri: item.uri,
|
uri: item.uri,
|
||||||
@@ -261,14 +269,16 @@ export function sort(
|
|||||||
i = branch.end
|
i = branch.end
|
||||||
continue traversal
|
continue traversal
|
||||||
} else if (AppBskyUnspeccedGetPostThreadV2.isThreadItemPost(item.value)) {
|
} else if (AppBskyUnspeccedGetPostThreadV2.isThreadItemPost(item.value)) {
|
||||||
|
postDataMap.set(item.uri, getPostTraversalMetadata(item))
|
||||||
|
|
||||||
const oneUp = thread.at(i - 1)
|
const oneUp = thread.at(i - 1)
|
||||||
const oneDown = thread.at(i + 1)
|
const oneDown = thread.at(i + 1)
|
||||||
const post = views.threadPost({
|
const post = views.threadPost({
|
||||||
uri: item.uri,
|
uri: item.uri,
|
||||||
depth: item.depth,
|
depth: item.depth,
|
||||||
value: item.value,
|
value: item.value,
|
||||||
parent: thread.find(
|
traversalMetadata: postDataMap.get(
|
||||||
p => p.uri === item.value.post.record.reply.parent.uri,
|
getPostRecord(item.value.post)?.reply?.parent?.uri || '',
|
||||||
),
|
),
|
||||||
oneUp,
|
oneUp,
|
||||||
oneDown,
|
oneDown,
|
||||||
@@ -308,12 +318,14 @@ export function sort(
|
|||||||
if (
|
if (
|
||||||
AppBskyUnspeccedGetPostThreadV2.isThreadItemPost(child.value)
|
AppBskyUnspeccedGetPostThreadV2.isThreadItemPost(child.value)
|
||||||
) {
|
) {
|
||||||
|
postDataMap.set(child.uri, getPostTraversalMetadata(child))
|
||||||
|
|
||||||
const childPost = views.threadPost({
|
const childPost = views.threadPost({
|
||||||
uri: child.uri,
|
uri: child.uri,
|
||||||
depth: child.depth,
|
depth: child.depth,
|
||||||
value: child.value,
|
value: child.value,
|
||||||
parent: thread.find(
|
traversalMetadata: postDataMap.get(
|
||||||
p => p.uri === child.value.post.record.reply.parent.uri,
|
getPostRecord(child.value.post)?.reply?.parent?.uri || '',
|
||||||
),
|
),
|
||||||
oneUp: thread[ci - 1],
|
oneUp: thread[ci - 1],
|
||||||
oneDown: thread[ci + 1],
|
oneDown: thread[ci + 1],
|
||||||
|
|||||||
@@ -91,3 +91,8 @@ export type Slice =
|
|||||||
nextAnchor: Extract<Slice, {type: 'threadPost'}>
|
nextAnchor: Extract<Slice, {type: 'threadPost'}>
|
||||||
nextAnchorUri: AtUri
|
nextAnchorUri: AtUri
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type TraversalMetadata = {
|
||||||
|
depth: number
|
||||||
|
hasBranchingReplies: boolean
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,10 +2,11 @@ import {
|
|||||||
type AppBskyFeedDefs,
|
type AppBskyFeedDefs,
|
||||||
AppBskyFeedPost,
|
AppBskyFeedPost,
|
||||||
AppBskyFeedThreadgate,
|
AppBskyFeedThreadgate,
|
||||||
type AppBskyUnspeccedGetPostThreadV2,
|
AppBskyUnspeccedGetPostThreadV2,
|
||||||
AtUri,
|
AtUri,
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
|
|
||||||
|
import {type TraversalMetadata} from '#/state/queries/usePostThread/types'
|
||||||
import * as bsky from '#/types/bsky'
|
import * as bsky from '#/types/bsky'
|
||||||
|
|
||||||
export function getThreadgateRecord(
|
export function getThreadgateRecord(
|
||||||
@@ -31,3 +32,25 @@ export function getRootPostAtUri(post: AppBskyFeedDefs.PostView) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getPostRecord(post: AppBskyFeedDefs.PostView) {
|
||||||
|
return post.record as AppBskyFeedPost.Record
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPostTraversalMetadata(
|
||||||
|
item: AppBskyUnspeccedGetPostThreadV2.ThreadItem,
|
||||||
|
): TraversalMetadata | undefined {
|
||||||
|
if (!AppBskyUnspeccedGetPostThreadV2.isThreadItemPost(item.value)) return
|
||||||
|
const replyCount = item.value.post.replyCount || 0
|
||||||
|
const unhydratedReplies = item.value.moreReplies || 0
|
||||||
|
return {
|
||||||
|
depth: item.depth,
|
||||||
|
/**
|
||||||
|
* If the post has more than a single reply, and the total reply count
|
||||||
|
* minus the number of replies not present in the response is greater than
|
||||||
|
* 1, then we must have more than a single branch of replies present in the
|
||||||
|
* response, which can affect how we render tree view.
|
||||||
|
*/
|
||||||
|
hasBranchingReplies: replyCount > 1 && replyCount - unhydratedReplies > 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,7 +8,10 @@ import {
|
|||||||
type ModerationOpts,
|
type ModerationOpts,
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
|
|
||||||
import {type Slice} from '#/state/queries/usePostThread/types'
|
import {
|
||||||
|
type Slice,
|
||||||
|
type TraversalMetadata,
|
||||||
|
} from '#/state/queries/usePostThread/types'
|
||||||
|
|
||||||
export function threadPostNoUnauthenticated({
|
export function threadPostNoUnauthenticated({
|
||||||
uri,
|
uri,
|
||||||
@@ -65,32 +68,18 @@ export function threadPost({
|
|||||||
uri,
|
uri,
|
||||||
depth,
|
depth,
|
||||||
value,
|
value,
|
||||||
parent: up,
|
|
||||||
oneUp,
|
oneUp,
|
||||||
moderationOpts,
|
moderationOpts,
|
||||||
|
traversalMetadata,
|
||||||
}: {
|
}: {
|
||||||
uri: string
|
uri: string
|
||||||
depth: number
|
depth: number
|
||||||
value: $Typed<AppBskyUnspeccedGetPostThreadV2.ThreadItemPost>
|
value: $Typed<AppBskyUnspeccedGetPostThreadV2.ThreadItemPost>
|
||||||
parent?: AppBskyUnspeccedGetPostThreadV2.OutputSchema['thread'][number]
|
|
||||||
oneUp?: AppBskyUnspeccedGetPostThreadV2.OutputSchema['thread'][number]
|
oneUp?: AppBskyUnspeccedGetPostThreadV2.OutputSchema['thread'][number]
|
||||||
oneDown?: AppBskyUnspeccedGetPostThreadV2.OutputSchema['thread'][number]
|
oneDown?: AppBskyUnspeccedGetPostThreadV2.OutputSchema['thread'][number]
|
||||||
moderationOpts: ModerationOpts
|
moderationOpts: ModerationOpts
|
||||||
|
traversalMetadata?: TraversalMetadata
|
||||||
}): Extract<Slice, {type: 'threadPost'}> {
|
}): Extract<Slice, {type: 'threadPost'}> {
|
||||||
const parent = (up && 'post' in up?.value
|
|
||||||
? up.value
|
|
||||||
: undefined) as unknown as AppBskyUnspeccedGetPostThreadV2.ThreadItemPost
|
|
||||||
const parentReplyCount = parent?.post?.replyCount || 0
|
|
||||||
const parentAdditionalReplies = parent?.moreReplies || 0
|
|
||||||
const parentHasBranchingReplies =
|
|
||||||
parentReplyCount > 1 && parentReplyCount - parentAdditionalReplies > 1
|
|
||||||
// if (!parentHasBranchingReplies) {
|
|
||||||
// console.log(value.post.record.text, {
|
|
||||||
// parentReplyCount,
|
|
||||||
// parentAdditionalReplies,
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'threadPost',
|
type: 'threadPost',
|
||||||
key: uri,
|
key: uri,
|
||||||
@@ -111,8 +100,10 @@ export function threadPost({
|
|||||||
isAnchor: depth === 0,
|
isAnchor: depth === 0,
|
||||||
showParentReplyLine: !!oneUp && oneUp.depth !== 0 && oneUp.depth < depth,
|
showParentReplyLine: !!oneUp && oneUp.depth !== 0 && oneUp.depth < depth,
|
||||||
showChildReplyLine: (value.post.replyCount || 0) > 0,
|
showChildReplyLine: (value.post.replyCount || 0) > 0,
|
||||||
indent: parentHasBranchingReplies ? depth : up?.depth || depth,
|
indent: traversalMetadata?.hasBranchingReplies
|
||||||
parentHasBranchingReplies,
|
? depth
|
||||||
|
: traversalMetadata?.depth || depth,
|
||||||
|
parentHasBranchingReplies: !!traversalMetadata?.hasBranchingReplies,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -127,7 +118,7 @@ export function readMore({
|
|||||||
key: `readMore:${parent.uri}`,
|
key: `readMore:${parent.uri}`,
|
||||||
indent: parent.ui.parentHasBranchingReplies
|
indent: parent.ui.parentHasBranchingReplies
|
||||||
? parent.depth
|
? parent.depth
|
||||||
: parent.depth - 1,
|
: Math.max(0, parent.depth - 1),
|
||||||
replyCount: parent.value.moreReplies,
|
replyCount: parent.value.moreReplies,
|
||||||
nextAnchor: parent,
|
nextAnchor: parent,
|
||||||
nextAnchorUri: new AtUri(parent.uri),
|
nextAnchorUri: new AtUri(parent.uri),
|
||||||
|
|||||||
Reference in New Issue
Block a user