Checkpoint cleanup
This commit is contained in:
@@ -6,14 +6,12 @@ import {
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
HiddenReplyKind,
|
HiddenReplyKind,
|
||||||
type NTraversalMetadata,
|
|
||||||
type PostThreadParams,
|
type PostThreadParams,
|
||||||
type Slice,
|
type Slice,
|
||||||
type TraversalMetadata,
|
type TraversalMetadata,
|
||||||
} from '#/state/queries/usePostThread/types'
|
} from '#/state/queries/usePostThread/types'
|
||||||
import {
|
import {
|
||||||
getPostRecord,
|
getPostRecord,
|
||||||
getPostTraversalMetadata,
|
|
||||||
getThreadPostUI,
|
getThreadPostUI,
|
||||||
getTraversalMetadata,
|
getTraversalMetadata,
|
||||||
} from '#/state/queries/usePostThread/utils'
|
} from '#/state/queries/usePostThread/utils'
|
||||||
@@ -205,15 +203,29 @@ 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>()
|
const metadatas = new Map<string, TraversalMetadata>()
|
||||||
|
|
||||||
const metadatas = new Map<string, NTraversalMetadata>()
|
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
window.__data = metadatas // for debugging
|
window.__data = metadatas // for debugging
|
||||||
|
|
||||||
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]
|
||||||
|
let parentMetadata: TraversalMetadata | undefined
|
||||||
|
let metadata: TraversalMetadata | undefined
|
||||||
|
|
||||||
|
if (AppBskyUnspeccedGetPostThreadV2.isThreadItemPost(item.value)) {
|
||||||
|
parentMetadata = metadatas.get(
|
||||||
|
getPostRecord(item.value.post).reply?.parent?.uri || '',
|
||||||
|
)
|
||||||
|
metadata = getTraversalMetadata({
|
||||||
|
item,
|
||||||
|
parentMetadata,
|
||||||
|
prevItem: thread.at(i - 1),
|
||||||
|
nextItem: thread.at(i + 1),
|
||||||
|
})
|
||||||
|
metadatas.set(item.uri, metadata)
|
||||||
|
metadatas.set(metadata.text, metadata) // TODO debugging
|
||||||
|
}
|
||||||
|
|
||||||
if (item.depth < 0) {
|
if (item.depth < 0) {
|
||||||
/*
|
/*
|
||||||
@@ -240,17 +252,12 @@ export function sort(
|
|||||||
uri: item.uri,
|
uri: item.uri,
|
||||||
depth: item.depth,
|
depth: item.depth,
|
||||||
value: item.value,
|
value: item.value,
|
||||||
oneUp: thread[i - 1],
|
|
||||||
oneDown: thread[i + 1],
|
|
||||||
moderationOpts,
|
moderationOpts,
|
||||||
})
|
})
|
||||||
postDataMap.set(item.uri, getPostTraversalMetadata(post))
|
|
||||||
items.push(post)
|
items.push(post)
|
||||||
|
|
||||||
parentTraversal: for (let pi = i - 1; pi >= 0; pi--) {
|
parentTraversal: for (let pi = i - 1; pi >= 0; pi--) {
|
||||||
const parentOneDown = thread[pi + 1]
|
|
||||||
const parent = thread[pi]
|
const parent = thread[pi]
|
||||||
const parentOneUp = thread[pi - 1]
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
AppBskyUnspeccedGetPostThreadV2.isThreadItemNoUnauthenticated(
|
AppBskyUnspeccedGetPostThreadV2.isThreadItemNoUnauthenticated(
|
||||||
@@ -277,8 +284,6 @@ export function sort(
|
|||||||
uri: parent.uri,
|
uri: parent.uri,
|
||||||
depth: parent.depth,
|
depth: parent.depth,
|
||||||
value: parent.value,
|
value: parent.value,
|
||||||
oneUp: parentOneUp,
|
|
||||||
oneDown: parentOneDown,
|
|
||||||
moderationOpts,
|
moderationOpts,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
@@ -304,37 +309,20 @@ 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)) {
|
||||||
const parentMetadata = metadatas.get(
|
|
||||||
getPostRecord(item.value.post).reply?.parent?.uri || '',
|
|
||||||
)
|
|
||||||
const oneUp = thread.at(i - 1)
|
|
||||||
const oneDown = thread.at(i + 1)
|
|
||||||
const metadata = getTraversalMetadata({
|
|
||||||
item,
|
|
||||||
parentMetadata,
|
|
||||||
prevItem: oneUp,
|
|
||||||
nextItem: oneDown,
|
|
||||||
})
|
|
||||||
if (parentMetadata) {
|
if (parentMetadata) {
|
||||||
parentMetadata.seenReplies += 1
|
parentMetadata.seenReplies += 1
|
||||||
metadata.isLastSibling =
|
if (metadata) {
|
||||||
parentMetadata.replies === parentMetadata.seenReplies
|
metadata.isLastSibling =
|
||||||
|
parentMetadata.replies === parentMetadata.seenReplies
|
||||||
|
}
|
||||||
}
|
}
|
||||||
metadatas.set(item.uri, metadata)
|
|
||||||
metadatas.set(metadata.text, metadata) // TODO debugging
|
|
||||||
|
|
||||||
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,
|
||||||
traversalMetadata: postDataMap.get(
|
|
||||||
getPostRecord(item.value.post)?.reply?.parent?.uri || '',
|
|
||||||
),
|
|
||||||
oneUp,
|
|
||||||
oneDown,
|
|
||||||
moderationOpts,
|
moderationOpts,
|
||||||
})
|
})
|
||||||
postDataMap.set(item.uri, getPostTraversalMetadata(post))
|
|
||||||
const postMod = getModerationState(post.moderation)
|
const postMod = getModerationState(post.moderation)
|
||||||
const postIsHiddenByThreadgate = threadgateHiddenReplies.has(item.uri)
|
const postIsHiddenByThreadgate = threadgateHiddenReplies.has(item.uri)
|
||||||
const postIsModerated =
|
const postIsModerated =
|
||||||
@@ -372,12 +360,10 @@ export function sort(
|
|||||||
const childParentMetadata = metadatas.get(
|
const childParentMetadata = metadatas.get(
|
||||||
getPostRecord(child.value.post).reply?.parent?.uri || '',
|
getPostRecord(child.value.post).reply?.parent?.uri || '',
|
||||||
)
|
)
|
||||||
const prevItem = thread[ci - 1]
|
|
||||||
const nextItem = thread[ci + 1]
|
|
||||||
const childMetadata = getTraversalMetadata({
|
const childMetadata = getTraversalMetadata({
|
||||||
item: child,
|
item: child,
|
||||||
prevItem,
|
prevItem: thread[ci - 1],
|
||||||
nextItem,
|
nextItem: thread[ci + 1],
|
||||||
parentMetadata: childParentMetadata,
|
parentMetadata: childParentMetadata,
|
||||||
})
|
})
|
||||||
if (childParentMetadata) {
|
if (childParentMetadata) {
|
||||||
@@ -393,14 +379,8 @@ export function sort(
|
|||||||
uri: child.uri,
|
uri: child.uri,
|
||||||
depth: child.depth,
|
depth: child.depth,
|
||||||
value: child.value,
|
value: child.value,
|
||||||
traversalMetadata: postDataMap.get(
|
|
||||||
getPostRecord(child.value.post)?.reply?.parent?.uri || '',
|
|
||||||
),
|
|
||||||
oneUp: prevItem,
|
|
||||||
oneDown: nextItem,
|
|
||||||
moderationOpts,
|
moderationOpts,
|
||||||
})
|
})
|
||||||
postDataMap.set(child.uri, getPostTraversalMetadata(childPost))
|
|
||||||
const childPostMod = getModerationState(childPost.moderation)
|
const childPostMod = getModerationState(childPost.moderation)
|
||||||
const childPostIsHiddenByThreadgate =
|
const childPostIsHiddenByThreadgate =
|
||||||
threadgateHiddenReplies.has(child.uri)
|
threadgateHiddenReplies.has(child.uri)
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ export type Slice =
|
|||||||
indent: number
|
indent: number
|
||||||
parentHasBranchingReplies: boolean
|
parentHasBranchingReplies: boolean
|
||||||
isDeadEnd: boolean
|
isDeadEnd: boolean
|
||||||
|
skippedIndents: Set<number>
|
||||||
/**
|
/**
|
||||||
* Populated during the final traversal of the thread. Denotes whether
|
* Populated during the final traversal of the thread. Denotes whether
|
||||||
* there is a "Read more" link for the parent immediately following
|
* there is a "Read more" link for the parent immediately following
|
||||||
@@ -64,8 +65,6 @@ export type Slice =
|
|||||||
* this item.
|
* this item.
|
||||||
*/
|
*/
|
||||||
precedesChildReadMore?: boolean
|
precedesChildReadMore?: boolean
|
||||||
skippedIndents: Set<number>
|
|
||||||
[key: string]: any
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
@@ -108,11 +107,6 @@ export type Slice =
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type TraversalMetadata = {
|
export type TraversalMetadata = {
|
||||||
indent: number
|
|
||||||
hasBranchingReplies: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export type NTraversalMetadata = {
|
|
||||||
depth: number
|
depth: number
|
||||||
indent: number
|
indent: number
|
||||||
replies: number
|
replies: number
|
||||||
@@ -120,7 +114,7 @@ export type NTraversalMetadata = {
|
|||||||
seenReplies: number
|
seenReplies: number
|
||||||
hasBranchingReplies: boolean
|
hasBranchingReplies: boolean
|
||||||
isLastSibling: boolean
|
isLastSibling: boolean
|
||||||
parentMetadata?: NTraversalMetadata
|
parentMetadata?: TraversalMetadata
|
||||||
prevItemDepth?: number
|
prevItemDepth?: number
|
||||||
nextItemDepth?: number
|
nextItemDepth?: number
|
||||||
skippedIndents: Set<number>
|
skippedIndents: Set<number>
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import {
|
|||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
type NTraversalMetadata,
|
|
||||||
type Slice,
|
type Slice,
|
||||||
type TraversalMetadata,
|
type TraversalMetadata,
|
||||||
} from '#/state/queries/usePostThread/types'
|
} from '#/state/queries/usePostThread/types'
|
||||||
@@ -41,24 +40,6 @@ export function getPostRecord(post: AppBskyFeedDefs.PostView) {
|
|||||||
return post.record as AppBskyFeedPost.Record
|
return post.record as AppBskyFeedPost.Record
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getPostTraversalMetadata(
|
|
||||||
item: Extract<Slice, {type: 'threadPost'}>,
|
|
||||||
): TraversalMetadata | undefined {
|
|
||||||
if (!AppBskyUnspeccedGetPostThreadV2.isThreadItemPost(item.value)) return
|
|
||||||
const replyCount = item.value.post.replyCount || 0
|
|
||||||
const unhydratedReplies = item.value.moreReplies || 0
|
|
||||||
return {
|
|
||||||
indent: item.ui.indent,
|
|
||||||
/**
|
|
||||||
* 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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getTraversalMetadata({
|
export function getTraversalMetadata({
|
||||||
item,
|
item,
|
||||||
prevItem,
|
prevItem,
|
||||||
@@ -68,13 +49,19 @@ export function getTraversalMetadata({
|
|||||||
item: AppBskyUnspeccedGetPostThreadV2.ThreadItem
|
item: AppBskyUnspeccedGetPostThreadV2.ThreadItem
|
||||||
prevItem?: AppBskyUnspeccedGetPostThreadV2.ThreadItem
|
prevItem?: AppBskyUnspeccedGetPostThreadV2.ThreadItem
|
||||||
nextItem?: AppBskyUnspeccedGetPostThreadV2.ThreadItem
|
nextItem?: AppBskyUnspeccedGetPostThreadV2.ThreadItem
|
||||||
parentMetadata?: NTraversalMetadata
|
parentMetadata?: TraversalMetadata
|
||||||
}): NTraversalMetadata {
|
}): TraversalMetadata {
|
||||||
if (!AppBskyUnspeccedGetPostThreadV2.isThreadItemPost(item.value)) {
|
if (!AppBskyUnspeccedGetPostThreadV2.isThreadItemPost(item.value)) {
|
||||||
throw new Error(`Expected thread item to be a post`)
|
throw new Error(`Expected thread item to be a post`)
|
||||||
}
|
}
|
||||||
const replies = item.value.post.replyCount || 0
|
const replies = item.value.post.replyCount || 0
|
||||||
const unhydratedReplies = item.value.moreReplies || 0
|
const unhydratedReplies = item.value.moreReplies || 0
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
const hasBranchingReplies = replies > 1 && replies - unhydratedReplies > 1
|
const hasBranchingReplies = replies > 1 && replies - unhydratedReplies > 1
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -106,7 +93,7 @@ export function getThreadPostUI({
|
|||||||
prevItemDepth,
|
prevItemDepth,
|
||||||
nextItemDepth,
|
nextItemDepth,
|
||||||
skippedIndents,
|
skippedIndents,
|
||||||
}: NTraversalMetadata) {
|
}: TraversalMetadata): Extract<Slice, {type: 'threadPost'}>['ui'] {
|
||||||
return {
|
return {
|
||||||
isAnchor: depth === 0,
|
isAnchor: depth === 0,
|
||||||
showParentReplyLine:
|
showParentReplyLine:
|
||||||
|
|||||||
@@ -8,10 +8,7 @@ import {
|
|||||||
type ModerationOpts,
|
type ModerationOpts,
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
|
|
||||||
import {
|
import {type Slice} from '#/state/queries/usePostThread/types'
|
||||||
type Slice,
|
|
||||||
type TraversalMetadata,
|
|
||||||
} from '#/state/queries/usePostThread/types'
|
|
||||||
|
|
||||||
export function threadPostNoUnauthenticated({
|
export function threadPostNoUnauthenticated({
|
||||||
uri,
|
uri,
|
||||||
@@ -68,28 +65,13 @@ export function threadPost({
|
|||||||
uri,
|
uri,
|
||||||
depth,
|
depth,
|
||||||
value,
|
value,
|
||||||
oneUp,
|
|
||||||
oneDown,
|
|
||||||
moderationOpts,
|
moderationOpts,
|
||||||
traversalMetadata,
|
|
||||||
}: {
|
}: {
|
||||||
uri: string
|
uri: string
|
||||||
depth: number
|
depth: number
|
||||||
value: $Typed<AppBskyUnspeccedGetPostThreadV2.ThreadItemPost>
|
value: $Typed<AppBskyUnspeccedGetPostThreadV2.ThreadItemPost>
|
||||||
oneUp?: AppBskyUnspeccedGetPostThreadV2.OutputSchema['thread'][number]
|
|
||||||
oneDown?: AppBskyUnspeccedGetPostThreadV2.OutputSchema['thread'][number]
|
|
||||||
moderationOpts: ModerationOpts
|
moderationOpts: ModerationOpts
|
||||||
traversalMetadata?: TraversalMetadata
|
|
||||||
}): Extract<Slice, {type: 'threadPost'}> {
|
}): Extract<Slice, {type: 'threadPost'}> {
|
||||||
const parentHasBranchingReplies = !!traversalMetadata?.hasBranchingReplies
|
|
||||||
/*
|
|
||||||
* Indent differs from depth in cases where the tree has no branches, and so
|
|
||||||
* we can maintain the more shallow depth of the parent.
|
|
||||||
*/
|
|
||||||
const indent = parentHasBranchingReplies
|
|
||||||
? depth
|
|
||||||
: traversalMetadata?.indent || depth
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'threadPost',
|
type: 'threadPost',
|
||||||
key: uri,
|
key: uri,
|
||||||
@@ -106,19 +88,8 @@ export function threadPost({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
moderation: moderatePost(value.post, moderationOpts),
|
moderation: moderatePost(value.post, moderationOpts),
|
||||||
ui: {
|
// @ts-ignore populated by the traversal
|
||||||
isAnchor: depth === 0,
|
ui: {},
|
||||||
showParentReplyLine: !!oneUp && oneUp.depth !== 0 && oneUp.depth < depth,
|
|
||||||
showChildReplyLine: (value.post.replyCount || 0) > 0,
|
|
||||||
indent,
|
|
||||||
parentHasBranchingReplies,
|
|
||||||
/*
|
|
||||||
* If there are no slices below this one, or the next slice is less
|
|
||||||
* indented than the computed indent for this post.
|
|
||||||
*/
|
|
||||||
isDeadEnd: !oneDown || oneDown?.depth < indent,
|
|
||||||
skippedIndents: new Set(),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user