Checkpoint new traversal
This commit is contained in:
@@ -193,19 +193,14 @@ let PostThreadItemLoaded = ({
|
|||||||
],
|
],
|
||||||
]}>
|
]}>
|
||||||
{Array.from(Array(indents)).map((_, n: number) => {
|
{Array.from(Array(indents)).map((_, n: number) => {
|
||||||
const isLastIteration = n === indents - 1
|
const isSkipped = item.ui.skippedIndents.has(n)
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
key={`${post.uri}-padding-${n}`}
|
key={`${post.uri}-padding-${n}`}
|
||||||
style={[
|
style={[
|
||||||
t.atoms.border_contrast_low,
|
t.atoms.border_contrast_low,
|
||||||
{
|
{
|
||||||
borderRightWidth:
|
borderRightWidth: isSkipped ? 0 : REPLY_LINE_WIDTH,
|
||||||
isLastIteration &&
|
|
||||||
item.ui.isDeadEnd &&
|
|
||||||
!item.ui.precedesParentReadMore
|
|
||||||
? 0
|
|
||||||
: REPLY_LINE_WIDTH,
|
|
||||||
width: TREE_INDENT + TREE_AVI_WIDTH / 2,
|
width: TREE_INDENT + TREE_AVI_WIDTH / 2,
|
||||||
left: 1,
|
left: 1,
|
||||||
},
|
},
|
||||||
@@ -229,7 +224,7 @@ let PostThreadItemLoaded = ({
|
|||||||
!item.ui.precedesParentReadMore &&
|
!item.ui.precedesParentReadMore &&
|
||||||
!item.ui.precedesChildReadMore && [a.pb_sm],
|
!item.ui.precedesChildReadMore && [a.pb_sm],
|
||||||
]}>
|
]}>
|
||||||
{item.ui.indent > 1 && item.ui.parentHasBranchingReplies && (
|
{item.ui.indent > 1 && (
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
a.absolute,
|
a.absolute,
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ export function usePostThread({
|
|||||||
const {data} = await agent.app.bsky.unspecced.getPostThreadV2({
|
const {data} = await agent.app.bsky.unspecced.getPostThreadV2({
|
||||||
anchor: params.anchor!,
|
anchor: params.anchor!,
|
||||||
branchingFactor: params.view === 'linear' ? 1 : 3, // 100 TODO
|
branchingFactor: params.view === 'linear' ? 1 : 3, // 100 TODO
|
||||||
below: 3,
|
below: 6,
|
||||||
sort: params.sort,
|
sort: params.sort,
|
||||||
prioritizeFollowedUsers: params.prioritizeFollowedUsers,
|
prioritizeFollowedUsers: params.prioritizeFollowedUsers,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
HiddenReplyKind,
|
HiddenReplyKind,
|
||||||
|
type NTraversalMetadata,
|
||||||
type PostThreadParams,
|
type PostThreadParams,
|
||||||
type Slice,
|
type Slice,
|
||||||
type TraversalMetadata,
|
type TraversalMetadata,
|
||||||
@@ -13,6 +14,8 @@ import {
|
|||||||
import {
|
import {
|
||||||
getPostRecord,
|
getPostRecord,
|
||||||
getPostTraversalMetadata,
|
getPostTraversalMetadata,
|
||||||
|
getThreadPostUI,
|
||||||
|
getTraversalMetadata,
|
||||||
} from '#/state/queries/usePostThread/utils'
|
} from '#/state/queries/usePostThread/utils'
|
||||||
import * as views from '#/state/queries/usePostThread/views'
|
import * as views from '#/state/queries/usePostThread/views'
|
||||||
|
|
||||||
@@ -147,7 +150,6 @@ export function flatten(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log(flattened)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Insert hidden items and buttons to show them
|
* Insert hidden items and buttons to show them
|
||||||
@@ -205,6 +207,11 @@ export function sort(
|
|||||||
const muted: Slice[] = []
|
const muted: Slice[] = []
|
||||||
const postDataMap = new Map<string, TraversalMetadata | undefined>()
|
const postDataMap = new Map<string, TraversalMetadata | undefined>()
|
||||||
|
|
||||||
|
const metadatas = new Map<string, NTraversalMetadata>()
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
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]
|
||||||
|
|
||||||
@@ -297,8 +304,25 @@ 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 oneUp = thread.at(i - 1)
|
||||||
const oneDown = thread.at(i + 1)
|
const oneDown = thread.at(i + 1)
|
||||||
|
const metadata = getTraversalMetadata({
|
||||||
|
item,
|
||||||
|
parentMetadata,
|
||||||
|
prevItem: oneUp,
|
||||||
|
nextItem: oneDown,
|
||||||
|
})
|
||||||
|
if (parentMetadata) {
|
||||||
|
parentMetadata.seenReplies += 1
|
||||||
|
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,
|
||||||
@@ -345,6 +369,26 @@ export function sort(
|
|||||||
if (
|
if (
|
||||||
AppBskyUnspeccedGetPostThreadV2.isThreadItemPost(child.value)
|
AppBskyUnspeccedGetPostThreadV2.isThreadItemPost(child.value)
|
||||||
) {
|
) {
|
||||||
|
const childParentMetadata = metadatas.get(
|
||||||
|
getPostRecord(child.value.post).reply?.parent?.uri || '',
|
||||||
|
)
|
||||||
|
const prevItem = thread[ci - 1]
|
||||||
|
const nextItem = thread[ci + 1]
|
||||||
|
const childMetadata = getTraversalMetadata({
|
||||||
|
item: child,
|
||||||
|
prevItem,
|
||||||
|
nextItem,
|
||||||
|
parentMetadata: childParentMetadata,
|
||||||
|
})
|
||||||
|
if (childParentMetadata) {
|
||||||
|
childParentMetadata.seenReplies += 1
|
||||||
|
childMetadata.isLastSibling =
|
||||||
|
childParentMetadata.replies ===
|
||||||
|
childParentMetadata.seenReplies
|
||||||
|
}
|
||||||
|
metadatas.set(item.uri, childMetadata)
|
||||||
|
metadatas.set(childMetadata.text, childMetadata) // TODO debugging
|
||||||
|
|
||||||
const childPost = views.threadPost({
|
const childPost = views.threadPost({
|
||||||
uri: child.uri,
|
uri: child.uri,
|
||||||
depth: child.depth,
|
depth: child.depth,
|
||||||
@@ -352,8 +396,8 @@ export function sort(
|
|||||||
traversalMetadata: postDataMap.get(
|
traversalMetadata: postDataMap.get(
|
||||||
getPostRecord(child.value.post)?.reply?.parent?.uri || '',
|
getPostRecord(child.value.post)?.reply?.parent?.uri || '',
|
||||||
),
|
),
|
||||||
oneUp: thread[ci - 1],
|
oneUp: prevItem,
|
||||||
oneDown: thread[ci + 1],
|
oneDown: nextItem,
|
||||||
moderationOpts,
|
moderationOpts,
|
||||||
})
|
})
|
||||||
postDataMap.set(child.uri, getPostTraversalMetadata(childPost))
|
postDataMap.set(child.uri, getPostTraversalMetadata(childPost))
|
||||||
@@ -394,6 +438,26 @@ export function sort(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const item of items) {
|
||||||
|
if (item.type === 'threadPost') {
|
||||||
|
const metadata = metadatas.get(item.uri)
|
||||||
|
if (metadata) {
|
||||||
|
if (metadata.parentMetadata) {
|
||||||
|
metadata.skippedIndents = new Set([
|
||||||
|
...metadata.parentMetadata.skippedIndents,
|
||||||
|
])
|
||||||
|
}
|
||||||
|
if (metadata.isLastSibling) {
|
||||||
|
metadata.skippedIndents.add(item.depth - 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
item.ui = getThreadPostUI(metadata)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log(metadatas)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
items,
|
items,
|
||||||
hidden,
|
hidden,
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ export type Slice =
|
|||||||
* this item.
|
* this item.
|
||||||
*/
|
*/
|
||||||
precedesChildReadMore?: boolean
|
precedesChildReadMore?: boolean
|
||||||
|
skippedIndents: Set<number>
|
||||||
|
[key: string]: any
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
@@ -109,3 +111,18 @@ export type TraversalMetadata = {
|
|||||||
indent: number
|
indent: number
|
||||||
hasBranchingReplies: boolean
|
hasBranchingReplies: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type NTraversalMetadata = {
|
||||||
|
depth: number
|
||||||
|
indent: number
|
||||||
|
replies: number
|
||||||
|
unhydratedReplies: number
|
||||||
|
seenReplies: number
|
||||||
|
hasBranchingReplies: boolean
|
||||||
|
isLastSibling: boolean
|
||||||
|
parentMetadata?: NTraversalMetadata
|
||||||
|
prevItemDepth?: number
|
||||||
|
nextItemDepth?: number
|
||||||
|
skippedIndents: Set<number>
|
||||||
|
[key: string]: any
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ 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'
|
||||||
@@ -57,3 +58,67 @@ export function getPostTraversalMetadata(
|
|||||||
hasBranchingReplies: replyCount > 1 && replyCount - unhydratedReplies > 1,
|
hasBranchingReplies: replyCount > 1 && replyCount - unhydratedReplies > 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getTraversalMetadata({
|
||||||
|
item,
|
||||||
|
prevItem,
|
||||||
|
nextItem,
|
||||||
|
parentMetadata,
|
||||||
|
}: {
|
||||||
|
item: AppBskyUnspeccedGetPostThreadV2.ThreadItem
|
||||||
|
prevItem?: AppBskyUnspeccedGetPostThreadV2.ThreadItem
|
||||||
|
nextItem?: AppBskyUnspeccedGetPostThreadV2.ThreadItem
|
||||||
|
parentMetadata?: NTraversalMetadata
|
||||||
|
}): NTraversalMetadata {
|
||||||
|
if (!AppBskyUnspeccedGetPostThreadV2.isThreadItemPost(item.value)) {
|
||||||
|
throw new Error(`Expected thread item to be a post`)
|
||||||
|
}
|
||||||
|
const replies = item.value.post.replyCount || 0
|
||||||
|
const unhydratedReplies = item.value.moreReplies || 0
|
||||||
|
const hasBranchingReplies = replies > 1 && replies - unhydratedReplies > 1
|
||||||
|
|
||||||
|
return {
|
||||||
|
depth: item.depth,
|
||||||
|
// TODO maybe not used
|
||||||
|
indent: parentMetadata?.hasBranchingReplies
|
||||||
|
? item.depth
|
||||||
|
: parentMetadata?.indent || item.depth,
|
||||||
|
replies,
|
||||||
|
unhydratedReplies,
|
||||||
|
seenReplies: 0,
|
||||||
|
hasBranchingReplies,
|
||||||
|
parentMetadata,
|
||||||
|
isLastSibling: false,
|
||||||
|
skippedIndents: new Set(),
|
||||||
|
prevItemDepth: prevItem?.depth,
|
||||||
|
nextItemDepth: nextItem?.depth,
|
||||||
|
|
||||||
|
// TODO non-spec
|
||||||
|
text: getPostRecord(item.value.post).text,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getThreadPostUI({
|
||||||
|
depth,
|
||||||
|
indent,
|
||||||
|
replies,
|
||||||
|
parentMetadata,
|
||||||
|
prevItemDepth,
|
||||||
|
nextItemDepth,
|
||||||
|
skippedIndents,
|
||||||
|
}: NTraversalMetadata) {
|
||||||
|
return {
|
||||||
|
isAnchor: depth === 0,
|
||||||
|
showParentReplyLine:
|
||||||
|
!!prevItemDepth && prevItemDepth !== 0 && prevItemDepth < depth,
|
||||||
|
showChildReplyLine: replies > 0,
|
||||||
|
indent: depth,
|
||||||
|
parentHasBranchingReplies: !!parentMetadata?.hasBranchingReplies,
|
||||||
|
/*
|
||||||
|
* If there are no slices below this one, or the next slice is less
|
||||||
|
* indented than the computed indent for this post.
|
||||||
|
*/
|
||||||
|
isDeadEnd: nextItemDepth === undefined || nextItemDepth < indent,
|
||||||
|
skippedIndents,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -117,6 +117,7 @@ export function threadPost({
|
|||||||
* indented than the computed indent for this post.
|
* indented than the computed indent for this post.
|
||||||
*/
|
*/
|
||||||
isDeadEnd: !oneDown || oneDown?.depth < indent,
|
isDeadEnd: !oneDown || oneDown?.depth < indent,
|
||||||
|
skippedIndents: new Set(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -152,11 +153,9 @@ export function postViewToThreadPlaceholder(
|
|||||||
value: {
|
value: {
|
||||||
$type: 'app.bsky.unspecced.getPostThreadV2#threadItemPost',
|
$type: 'app.bsky.unspecced.getPostThreadV2#threadItemPost',
|
||||||
post,
|
post,
|
||||||
hiddenByThreadgate: false,
|
|
||||||
opThread: false,
|
opThread: false,
|
||||||
moreParents: false,
|
moreParents: false,
|
||||||
moreReplies: 0,
|
moreReplies: 0,
|
||||||
mutedByViewer: false,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user