Sorta working linear view optimistic state
This commit is contained in:
@@ -74,6 +74,7 @@ export function usePostThread({
|
|||||||
|
|
||||||
const items = flatten(
|
const items = flatten(
|
||||||
sort(query.data?.thread || [], {
|
sort(query.data?.thread || [], {
|
||||||
|
view: params.view,
|
||||||
threadgateHiddenReplies: mergeThreadgateHiddenReplies(
|
threadgateHiddenReplies: mergeThreadgateHiddenReplies(
|
||||||
query.data?.threadgate?.record,
|
query.data?.threadgate?.record,
|
||||||
),
|
),
|
||||||
@@ -85,6 +86,7 @@ export function usePostThread({
|
|||||||
showHidden: state.shownHiddenReplyKinds.has(HiddenReplyKind.Hidden),
|
showHidden: state.shownHiddenReplyKinds.has(HiddenReplyKind.Hidden),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
console.log(items)
|
||||||
|
|
||||||
const mutator = createCacheMutator({
|
const mutator = createCacheMutator({
|
||||||
queryKey,
|
queryKey,
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import {
|
import {
|
||||||
|
AtUri,
|
||||||
AppBskyUnspeccedGetPostThreadV2,
|
AppBskyUnspeccedGetPostThreadV2,
|
||||||
type ModerationDecision,
|
type ModerationDecision,
|
||||||
type ModerationOpts,
|
type ModerationOpts,
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
|
|
||||||
import {HiddenReplyKind,type Slice} from '#/state/queries/usePostThread/types'
|
import {HiddenReplyKind, type PostThreadParams, type Slice} from '#/state/queries/usePostThread/types'
|
||||||
import * as views from '#/state/queries/usePostThread/views'
|
import * as views from '#/state/queries/usePostThread/views'
|
||||||
|
|
||||||
export function flatten(
|
export function flatten(
|
||||||
@@ -58,12 +59,13 @@ export function flatten(
|
|||||||
if (hasSession) {
|
if (hasSession) {
|
||||||
for (let i = 0; i < flattened.length; i++) {
|
for (let i = 0; i < flattened.length; i++) {
|
||||||
const item = flattened[i]
|
const item = flattened[i]
|
||||||
if ('depth' in item && item.depth === 0) {
|
|
||||||
|
// TODO should not insert if not found post etc
|
||||||
|
if (item.type === 'threadPost' && item.depth === 0) {
|
||||||
flattened.splice(i + 1, 0, {
|
flattened.splice(i + 1, 0, {
|
||||||
type: 'replyComposer',
|
type: 'replyComposer',
|
||||||
key: 'replyComposer',
|
key: 'replyComposer',
|
||||||
})
|
})
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -74,9 +76,11 @@ export function flatten(
|
|||||||
export function sort(
|
export function sort(
|
||||||
thread: AppBskyUnspeccedGetPostThreadV2.OutputSchema['thread'],
|
thread: AppBskyUnspeccedGetPostThreadV2.OutputSchema['thread'],
|
||||||
{
|
{
|
||||||
|
view,
|
||||||
threadgateHiddenReplies,
|
threadgateHiddenReplies,
|
||||||
moderationOpts,
|
moderationOpts,
|
||||||
}: {
|
}: {
|
||||||
|
view: PostThreadParams['view']
|
||||||
threadgateHiddenReplies: Set<string>
|
threadgateHiddenReplies: Set<string>
|
||||||
moderationOpts: ModerationOpts
|
moderationOpts: ModerationOpts
|
||||||
},
|
},
|
||||||
@@ -181,29 +185,97 @@ export function sort(
|
|||||||
const isFirstReply =
|
const isFirstReply =
|
||||||
lastSlice.type === 'replyComposer' ||
|
lastSlice.type === 'replyComposer' ||
|
||||||
(lastSlice.type === 'threadPost' && lastSlice.depth === 0)
|
(lastSlice.type === 'threadPost' && lastSlice.depth === 0)
|
||||||
const parent = views.threadPost({
|
const oneUp = isFirstReply ? undefined : thread.at(i - 1)
|
||||||
|
const oneDown = thread.at(i + 1)
|
||||||
|
const post = views.threadPost({
|
||||||
uri: item.uri,
|
uri: item.uri,
|
||||||
depth: item.depth,
|
depth: item.depth,
|
||||||
value: item.value,
|
value: item.value,
|
||||||
oneUp: isFirstReply ? undefined : thread[i - 1],
|
oneUp,
|
||||||
oneDown: thread[i + 1],
|
oneDown,
|
||||||
moderationOpts,
|
moderationOpts,
|
||||||
})
|
})
|
||||||
const parentMod = getModerationState(parent.moderation)
|
const postMod = getModerationState(post.moderation)
|
||||||
const parentIsHidden = threadgateHiddenReplies.has(item.uri)
|
const postIsHidden = threadgateHiddenReplies.has(item.uri)
|
||||||
const parentIsTopLevelReply = item.depth === 1
|
const postIsModerated =
|
||||||
const parentIsModerated =
|
postIsHidden || postMod.blurred || postMod.muted
|
||||||
parentIsHidden || parentMod.blurred || parentMod.muted
|
|
||||||
|
|
||||||
if (!parentIsModerated) {
|
if (!postIsModerated) {
|
||||||
/*
|
/*
|
||||||
* Not hidden, so show it
|
* Not moderated, probably need to insert it
|
||||||
*/
|
*/
|
||||||
items.push(parent)
|
// items.push(post)
|
||||||
|
if (view === 'tree') {
|
||||||
|
items.push(post)
|
||||||
|
} else {
|
||||||
|
if (post.depth > 1) {
|
||||||
|
const maybeNextSiblingIndex = getBranch(thread, i, post.depth).end + 1
|
||||||
|
const maybeNextSibling = thread.at(maybeNextSiblingIndex)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we've got two replies at the same depth, we need to decide
|
||||||
|
* which one to show.
|
||||||
|
*/
|
||||||
|
if (post.depth === maybeNextSibling?.depth) {
|
||||||
|
// continue with next sibling
|
||||||
|
i = maybeNextSiblingIndex - 1
|
||||||
|
debugger;
|
||||||
|
continue traversal
|
||||||
|
} else {
|
||||||
|
const maybePrevSiblingIndex = getBranchUp(thread, i - 1, post.depth).end
|
||||||
|
const maybePrevSibling = thread.at(maybePrevSiblingIndex)
|
||||||
|
|
||||||
|
if (post.depth === maybePrevSibling?.depth) {
|
||||||
|
const post = views.threadPost({
|
||||||
|
uri: item.uri,
|
||||||
|
depth: item.depth,
|
||||||
|
value: item.value,
|
||||||
|
oneUp: thread.at(maybePrevSiblingIndex - 1),
|
||||||
|
oneDown,
|
||||||
|
moderationOpts,
|
||||||
|
})
|
||||||
|
debugger;
|
||||||
|
items.push(post)
|
||||||
|
} else {
|
||||||
|
items.push(post)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (post.depth === oneDown?.depth) {
|
||||||
|
const opDid = new AtUri(post.value.post.record.reply?.root?.uri).host
|
||||||
|
const postAuthorDid = new AtUri(post.uri).host
|
||||||
|
debugger;
|
||||||
|
if (postAuthorDid === opDid) {
|
||||||
|
// prioritize OP optimistic reply
|
||||||
|
items.push(post)
|
||||||
|
// skip next reply
|
||||||
|
i = getBranch(thread, i, oneDown.depth).end
|
||||||
|
debugger;
|
||||||
|
continue traversal
|
||||||
|
} else {
|
||||||
|
i = getBranch(thread, i, post.depth).end
|
||||||
|
debugger;
|
||||||
|
continue traversal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
} else {
|
||||||
|
items.push(post)
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const branch = getBranch(thread, i, item.depth)
|
/*
|
||||||
|
* Moderated in some way, we're going to walk children
|
||||||
|
*/
|
||||||
|
const parent = post
|
||||||
|
const parentMod = postMod
|
||||||
|
const parentIsTopLevelReply = parent.depth === 1
|
||||||
const sortArray = parentMod.muted ? muted : hidden
|
const sortArray = parentMod.muted ? muted : hidden
|
||||||
|
|
||||||
|
// get sub tree
|
||||||
|
const branch = getBranch(thread, i, item.depth)
|
||||||
|
|
||||||
if (parentIsTopLevelReply) {
|
if (parentIsTopLevelReply) {
|
||||||
// push branch anchor into sorted array
|
// push branch anchor into sorted array
|
||||||
sortArray.push(parent)
|
sortArray.push(parent)
|
||||||
@@ -302,6 +374,29 @@ function getBranch(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getBranchUp(
|
||||||
|
thread: AppBskyUnspeccedGetPostThreadV2.OutputSchema['thread'],
|
||||||
|
branchStartIndex: number,
|
||||||
|
branchEndDepth: number,
|
||||||
|
) {
|
||||||
|
let start = branchStartIndex
|
||||||
|
|
||||||
|
for (let ci = branchStartIndex; ci >= 0; ci--) {
|
||||||
|
const next = thread[ci]
|
||||||
|
if (next.depth > branchEndDepth) {
|
||||||
|
start = ci
|
||||||
|
} else {
|
||||||
|
start = ci
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
start,
|
||||||
|
end: branchStartIndex,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function getModerationState(moderation: ModerationDecision) {
|
export function getModerationState(moderation: ModerationDecision) {
|
||||||
const modui = moderation.ui('contentList')
|
const modui = moderation.ui('contentList')
|
||||||
const blurred = modui.blur || modui.filter
|
const blurred = modui.blur || modui.filter
|
||||||
|
|||||||
@@ -80,3 +80,8 @@ export type Slice =
|
|||||||
key: string
|
key: string
|
||||||
kind: HiddenReplyKind
|
kind: HiddenReplyKind
|
||||||
}
|
}
|
||||||
|
| {
|
||||||
|
type: 'threadPostNoOp'
|
||||||
|
key: string
|
||||||
|
comment: string
|
||||||
|
}
|
||||||
|
|||||||
@@ -98,6 +98,8 @@ export function threadPost({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// export function threadPostNoOp({ })
|
||||||
|
|
||||||
export function postViewToThreadPlaceholder(
|
export function postViewToThreadPlaceholder(
|
||||||
post: AppBskyFeedDefs.PostView,
|
post: AppBskyFeedDefs.PostView,
|
||||||
): $Typed<
|
): $Typed<
|
||||||
|
|||||||
Reference in New Issue
Block a user