Clean up traversal functions further
This commit is contained in:
@@ -293,7 +293,7 @@ export function Inner({uri}: {uri: string | undefined}) {
|
|||||||
<PostThreadShowHiddenReplies
|
<PostThreadShowHiddenReplies
|
||||||
type="hidden"
|
type="hidden"
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
item.onLoad()
|
item.onPress()
|
||||||
/*
|
/*
|
||||||
* Bit of a hack. This resets the ref value for the anchor so that
|
* Bit of a hack. This resets the ref value for the anchor so that
|
||||||
* the next time `onContentSizeChangeWebOnly` fires, it won't
|
* the next time `onContentSizeChangeWebOnly` fires, it won't
|
||||||
|
|||||||
@@ -8,7 +8,10 @@ import {
|
|||||||
createCacheMutator,
|
createCacheMutator,
|
||||||
getThreadPlaceholder,
|
getThreadPlaceholder,
|
||||||
} from '#/state/queries/usePostThread/queryCache'
|
} from '#/state/queries/usePostThread/queryCache'
|
||||||
import {combine, traverse} from '#/state/queries/usePostThread/traversal'
|
import {
|
||||||
|
buildThread,
|
||||||
|
sortAndAnnotateThreadItems,
|
||||||
|
} from '#/state/queries/usePostThread/traversal'
|
||||||
import {
|
import {
|
||||||
createPostThreadHiddenQueryKey,
|
createPostThreadHiddenQueryKey,
|
||||||
createPostThreadQueryKey,
|
createPostThreadQueryKey,
|
||||||
@@ -119,7 +122,7 @@ export function usePostThread({anchor}: {anchor?: string}) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const [hiddenItemsVisible, setHiddenItemsVisible] = useState(false)
|
const [hiddenItemsVisible, setHiddenItemsVisible] = useState(false)
|
||||||
const [additionalHiddenItems, setAdditionalHiddenItems] = useState<
|
const [serverHiddenThreadItems, setServerHiddenThreadItems] = useState<
|
||||||
ThreadItem[]
|
ThreadItem[]
|
||||||
>([])
|
>([])
|
||||||
|
|
||||||
@@ -129,10 +132,10 @@ export function usePostThread({anchor}: {anchor?: string}) {
|
|||||||
const setSort: typeof baseSetSort = useCallback(
|
const setSort: typeof baseSetSort = useCallback(
|
||||||
nextSort => {
|
nextSort => {
|
||||||
setHiddenItemsVisible(false)
|
setHiddenItemsVisible(false)
|
||||||
setAdditionalHiddenItems([])
|
setServerHiddenThreadItems([])
|
||||||
baseSetSort(nextSort)
|
baseSetSort(nextSort)
|
||||||
},
|
},
|
||||||
[baseSetSort, setAdditionalHiddenItems, setHiddenItemsVisible],
|
[baseSetSort, setServerHiddenThreadItems, setHiddenItemsVisible],
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -141,10 +144,10 @@ export function usePostThread({anchor}: {anchor?: string}) {
|
|||||||
const setView: typeof baseSetView = useCallback(
|
const setView: typeof baseSetView = useCallback(
|
||||||
nextView => {
|
nextView => {
|
||||||
setHiddenItemsVisible(false)
|
setHiddenItemsVisible(false)
|
||||||
setAdditionalHiddenItems([])
|
setServerHiddenThreadItems([])
|
||||||
baseSetView(nextView)
|
baseSetView(nextView)
|
||||||
},
|
},
|
||||||
[baseSetView, setAdditionalHiddenItems, setHiddenItemsVisible],
|
[baseSetView, setServerHiddenThreadItems, setHiddenItemsVisible],
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -169,7 +172,7 @@ export function usePostThread({anchor}: {anchor?: string}) {
|
|||||||
* the initial visible response(s) are shown immediately. Remote data is
|
* the initial visible response(s) are shown immediately. Remote data is
|
||||||
* fetched and inserted when it's available.
|
* fetched and inserted when it's available.
|
||||||
*/
|
*/
|
||||||
const loadServerHiddenItems = useCallback(async () => {
|
const loadServerHiddenThreadItems = useCallback(async () => {
|
||||||
/*
|
/*
|
||||||
* Show any moderated replies already in memory that were handled here on
|
* Show any moderated replies already in memory that were handled here on
|
||||||
* the client. If there are server-hidden replies, we'll fetch those next.
|
* the client. If there are server-hidden replies, we'll fetch those next.
|
||||||
@@ -181,7 +184,7 @@ export function usePostThread({anchor}: {anchor?: string}) {
|
|||||||
*/
|
*/
|
||||||
if (!hasServerHiddenItems) return
|
if (!hasServerHiddenItems) return
|
||||||
|
|
||||||
setAdditionalHiddenItems(
|
setServerHiddenThreadItems(
|
||||||
Array.from({length: 2}).map((_, i) =>
|
Array.from({length: 2}).map((_, i) =>
|
||||||
views.skeleton({
|
views.skeleton({
|
||||||
key: `${anchor!}-reply-${i}`,
|
key: `${anchor!}-reply-${i}`,
|
||||||
@@ -207,7 +210,7 @@ export function usePostThread({anchor}: {anchor?: string}) {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
const {items} = traverse(data || [], {
|
const {threadItems} = sortAndAnnotateThreadItems(data || [], {
|
||||||
view,
|
view,
|
||||||
skipHiddenReplyHandling: true,
|
skipHiddenReplyHandling: true,
|
||||||
threadgateHiddenReplies: mergeThreadgateHiddenReplies(threadgate?.record),
|
threadgateHiddenReplies: mergeThreadgateHiddenReplies(threadgate?.record),
|
||||||
@@ -215,7 +218,7 @@ export function usePostThread({anchor}: {anchor?: string}) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// insert the hidden replies into the state
|
// insert the hidden replies into the state
|
||||||
setAdditionalHiddenItems(items)
|
setServerHiddenThreadItems(threadItems)
|
||||||
}, [
|
}, [
|
||||||
qc,
|
qc,
|
||||||
agent,
|
agent,
|
||||||
@@ -229,90 +232,49 @@ export function usePostThread({anchor}: {anchor?: string}) {
|
|||||||
setHiddenItemsVisible,
|
setHiddenItemsVisible,
|
||||||
])
|
])
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Builds the full set of thread items, minus any server-hidden replies.
|
* This is the main thread response, sorted into separate buckets based on
|
||||||
|
* moderation, and annotated with all UI state needed for rendering.
|
||||||
*/
|
*/
|
||||||
const threadItems = useMemo(() => {
|
const {threadItems, hiddenThreadItems} = useMemo(() => {
|
||||||
const traversal = traverse(thread, {
|
return sortAndAnnotateThreadItems(thread, {
|
||||||
view: view,
|
view: view,
|
||||||
threadgateHiddenReplies: mergeThreadgateHiddenReplies(threadgate?.record),
|
threadgateHiddenReplies: mergeThreadgateHiddenReplies(threadgate?.record),
|
||||||
moderationOpts: moderationOpts!,
|
moderationOpts: moderationOpts!,
|
||||||
})
|
})
|
||||||
return combine(traversal, {
|
|
||||||
hasSession,
|
|
||||||
hasServerHiddenItems,
|
|
||||||
hiddenItemsVisible,
|
|
||||||
loadServerHiddenItems,
|
|
||||||
})
|
|
||||||
}, [
|
}, [
|
||||||
thread,
|
thread,
|
||||||
threadgate?.record,
|
threadgate?.record,
|
||||||
mergeThreadgateHiddenReplies,
|
mergeThreadgateHiddenReplies,
|
||||||
moderationOpts,
|
moderationOpts,
|
||||||
hasSession,
|
|
||||||
view,
|
view,
|
||||||
hasServerHiddenItems,
|
|
||||||
hiddenItemsVisible,
|
|
||||||
loadServerHiddenItems,
|
|
||||||
])
|
])
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* Computes the final thread items based on load state and the availability
|
* Take all three sets of thread items and combine them into a single thread,
|
||||||
* of server-hidden replies.
|
* along with any other thread items required for rendering e.g. "Show hidden
|
||||||
|
* replies" or the reply composer.
|
||||||
*/
|
*/
|
||||||
const items = useMemo(() => {
|
const items = useMemo(() => {
|
||||||
const result = [...threadItems]
|
return buildThread({
|
||||||
|
|
||||||
if (query.isPlaceholderData) {
|
|
||||||
const anchorPost = result.at(0)
|
|
||||||
const skeletonReplies =
|
|
||||||
anchorPost && anchorPost.type === 'threadPost'
|
|
||||||
? anchorPost?.value.post.replyCount ?? 4
|
|
||||||
: 4
|
|
||||||
|
|
||||||
if (!result.length) {
|
|
||||||
result.push(
|
|
||||||
views.skeleton({
|
|
||||||
key: anchor!,
|
|
||||||
item: 'anchor',
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
if (hasSession) {
|
|
||||||
result.push(
|
|
||||||
views.skeleton({
|
|
||||||
key: 'replyComposer',
|
|
||||||
item: 'replyComposer',
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < skeletonReplies; i++) {
|
|
||||||
result.push(
|
|
||||||
views.skeleton({
|
|
||||||
key: `${anchor!}-reply-${i}`,
|
|
||||||
item: 'reply',
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
} else {
|
|
||||||
result.push(...additionalHiddenItems)
|
|
||||||
result.push({
|
|
||||||
type: 'bookend',
|
|
||||||
key: 'bookend-down',
|
|
||||||
direction: 'down',
|
|
||||||
})
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}, [
|
|
||||||
query.isPlaceholderData,
|
|
||||||
threadItems,
|
threadItems,
|
||||||
additionalHiddenItems,
|
hiddenThreadItems,
|
||||||
anchor,
|
serverHiddenThreadItems,
|
||||||
|
isLoading: query.isPlaceholderData,
|
||||||
hasSession,
|
hasSession,
|
||||||
|
hasServerHiddenItems,
|
||||||
|
hiddenItemsVisible,
|
||||||
|
loadServerHiddenThreadItems,
|
||||||
|
})
|
||||||
|
}, [
|
||||||
|
threadItems,
|
||||||
|
hiddenThreadItems,
|
||||||
|
serverHiddenThreadItems,
|
||||||
|
query.isPlaceholderData,
|
||||||
|
hasSession,
|
||||||
|
hasServerHiddenItems,
|
||||||
|
hiddenItemsVisible,
|
||||||
|
loadServerHiddenThreadItems,
|
||||||
])
|
])
|
||||||
|
|
||||||
return useMemo(
|
return useMemo(
|
||||||
@@ -350,7 +312,6 @@ export function usePostThread({anchor}: {anchor?: string}) {
|
|||||||
}),
|
}),
|
||||||
[
|
[
|
||||||
query,
|
query,
|
||||||
items,
|
|
||||||
mutator.insertReplies,
|
mutator.insertReplies,
|
||||||
hiddenItemsVisible,
|
hiddenItemsVisible,
|
||||||
sort,
|
sort,
|
||||||
@@ -358,6 +319,7 @@ export function usePostThread({anchor}: {anchor?: string}) {
|
|||||||
setSort,
|
setSort,
|
||||||
setView,
|
setView,
|
||||||
threadgate,
|
threadgate,
|
||||||
|
items,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import {
|
|||||||
} 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'
|
||||||
|
|
||||||
export function traverse(
|
export function sortAndAnnotateThreadItems(
|
||||||
thread: ApiThreadItem[],
|
thread: ApiThreadItem[],
|
||||||
{
|
{
|
||||||
threadgateHiddenReplies,
|
threadgateHiddenReplies,
|
||||||
@@ -30,13 +30,13 @@ export function traverse(
|
|||||||
* post e.g. when fetching server-hidden replies. This will prevent
|
* post e.g. when fetching server-hidden replies. This will prevent
|
||||||
* additional sorting or nested-branch truncation, and all replies,
|
* additional sorting or nested-branch truncation, and all replies,
|
||||||
* regardless of moderation state, will be included in the resulting
|
* regardless of moderation state, will be included in the resulting
|
||||||
* `items` array.
|
* `threadItems` array.
|
||||||
*/
|
*/
|
||||||
skipHiddenReplyHandling?: boolean
|
skipHiddenReplyHandling?: boolean
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
const items: ThreadItem[] = []
|
const threadItems: ThreadItem[] = []
|
||||||
const hidden: ThreadItem[] = []
|
const hiddenThreadItems: ThreadItem[] = []
|
||||||
const metadatas = new Map<string, TraversalMetadata>()
|
const metadatas = new Map<string, TraversalMetadata>()
|
||||||
|
|
||||||
traversal: for (let i = 0; i < thread.length; i++) {
|
traversal: for (let i = 0; i < thread.length; i++) {
|
||||||
@@ -64,11 +64,11 @@ export function traverse(
|
|||||||
*/
|
*/
|
||||||
} else if (item.depth === 0) {
|
} else if (item.depth === 0) {
|
||||||
if (AppBskyUnspeccedDefs.isThreadItemNoUnauthenticated(item.value)) {
|
if (AppBskyUnspeccedDefs.isThreadItemNoUnauthenticated(item.value)) {
|
||||||
items.push(views.threadPostNoUnauthenticated(item))
|
threadItems.push(views.threadPostNoUnauthenticated(item))
|
||||||
} else if (AppBskyUnspeccedDefs.isThreadItemNotFound(item.value)) {
|
} else if (AppBskyUnspeccedDefs.isThreadItemNotFound(item.value)) {
|
||||||
items.push(views.threadPostNotFound(item))
|
threadItems.push(views.threadPostNotFound(item))
|
||||||
} else if (AppBskyUnspeccedDefs.isThreadItemBlocked(item.value)) {
|
} else if (AppBskyUnspeccedDefs.isThreadItemBlocked(item.value)) {
|
||||||
items.push(views.threadPostBlocked(item))
|
threadItems.push(views.threadPostBlocked(item))
|
||||||
} else if (AppBskyUnspeccedDefs.isThreadItemPost(item.value)) {
|
} else if (AppBskyUnspeccedDefs.isThreadItemPost(item.value)) {
|
||||||
const post = views.threadPost({
|
const post = views.threadPost({
|
||||||
uri: item.uri,
|
uri: item.uri,
|
||||||
@@ -77,7 +77,7 @@ export function traverse(
|
|||||||
moderationOpts,
|
moderationOpts,
|
||||||
threadgateHiddenReplies,
|
threadgateHiddenReplies,
|
||||||
})
|
})
|
||||||
items.push(post)
|
threadItems.push(post)
|
||||||
|
|
||||||
parentTraversal: for (let pi = i - 1; pi >= 0; pi--) {
|
parentTraversal: for (let pi = i - 1; pi >= 0; pi--) {
|
||||||
const parent = thread[pi]
|
const parent = thread[pi]
|
||||||
@@ -85,16 +85,16 @@ export function traverse(
|
|||||||
if (
|
if (
|
||||||
AppBskyUnspeccedDefs.isThreadItemNoUnauthenticated(parent.value)
|
AppBskyUnspeccedDefs.isThreadItemNoUnauthenticated(parent.value)
|
||||||
) {
|
) {
|
||||||
items.unshift(views.threadPostNoUnauthenticated(parent))
|
threadItems.unshift(views.threadPostNoUnauthenticated(parent))
|
||||||
break parentTraversal
|
break parentTraversal
|
||||||
} else if (AppBskyUnspeccedDefs.isThreadItemNotFound(parent.value)) {
|
} else if (AppBskyUnspeccedDefs.isThreadItemNotFound(parent.value)) {
|
||||||
items.unshift(views.threadPostNotFound(parent))
|
threadItems.unshift(views.threadPostNotFound(parent))
|
||||||
break parentTraversal
|
break parentTraversal
|
||||||
} else if (AppBskyUnspeccedDefs.isThreadItemBlocked(parent.value)) {
|
} else if (AppBskyUnspeccedDefs.isThreadItemBlocked(parent.value)) {
|
||||||
items.unshift(views.threadPostBlocked(parent))
|
threadItems.unshift(views.threadPostBlocked(parent))
|
||||||
break parentTraversal
|
break parentTraversal
|
||||||
} else if (AppBskyUnspeccedDefs.isThreadItemPost(parent.value)) {
|
} else if (AppBskyUnspeccedDefs.isThreadItemPost(parent.value)) {
|
||||||
items.unshift(
|
threadItems.unshift(
|
||||||
views.threadPost({
|
views.threadPost({
|
||||||
uri: parent.uri,
|
uri: parent.uri,
|
||||||
depth: parent.depth,
|
depth: parent.depth,
|
||||||
@@ -144,7 +144,7 @@ export function traverse(
|
|||||||
/*
|
/*
|
||||||
* Not moderated, need to insert it
|
* Not moderated, need to insert it
|
||||||
*/
|
*/
|
||||||
items.push(post)
|
threadItems.push(post)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Update seen reply count of parent
|
* Update seen reply count of parent
|
||||||
@@ -163,7 +163,7 @@ export function traverse(
|
|||||||
|
|
||||||
if (parentIsTopLevelReply) {
|
if (parentIsTopLevelReply) {
|
||||||
// push branch anchor into sorted array
|
// push branch anchor into sorted array
|
||||||
hidden.push(parent)
|
hiddenThreadItems.push(parent)
|
||||||
// skip branch anchor in branch traversal
|
// skip branch anchor in branch traversal
|
||||||
const startIndex = branch.start + 1
|
const startIndex = branch.start + 1
|
||||||
|
|
||||||
@@ -206,7 +206,7 @@ export function traverse(
|
|||||||
if (childPost.isBlurred) {
|
if (childPost.isBlurred) {
|
||||||
ci = getBranch(thread, ci, child.depth).end
|
ci = getBranch(thread, ci, child.depth).end
|
||||||
} else {
|
} else {
|
||||||
hidden.push(childPost)
|
hiddenThreadItems.push(childPost)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
@@ -228,10 +228,10 @@ export function traverse(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Both `items` and `hidden` now need to be traversed again to fully compute
|
* Both `threadItems` and `hiddenThreadItems` now need to be traversed again to fully compute
|
||||||
* UI state based on collected metadata. These arrays will be muted in situ.
|
* UI state based on collected metadata. These arrays will be muted in situ.
|
||||||
*/
|
*/
|
||||||
for (const subset of [items, hidden]) {
|
for (const subset of [threadItems, hiddenThreadItems]) {
|
||||||
for (let i = 0; i < subset.length; i++) {
|
for (let i = 0; i < subset.length; i++) {
|
||||||
const item = subset[i]
|
const item = subset[i]
|
||||||
const prevItem = subset.at(i - 1)
|
const prevItem = subset.at(i - 1)
|
||||||
@@ -363,36 +363,78 @@ export function traverse(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
items,
|
threadItems,
|
||||||
hidden,
|
hiddenThreadItems,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function combine(
|
export function buildThread({
|
||||||
{items, hidden}: {items: ThreadItem[]; hidden: ThreadItem[]},
|
threadItems,
|
||||||
{
|
hiddenThreadItems,
|
||||||
|
serverHiddenThreadItems,
|
||||||
|
isLoading,
|
||||||
hasSession,
|
hasSession,
|
||||||
hiddenItemsVisible,
|
hiddenItemsVisible,
|
||||||
hasServerHiddenItems,
|
hasServerHiddenItems,
|
||||||
loadServerHiddenItems,
|
loadServerHiddenThreadItems,
|
||||||
}: {
|
}: {
|
||||||
|
threadItems: ThreadItem[]
|
||||||
|
hiddenThreadItems: ThreadItem[]
|
||||||
|
serverHiddenThreadItems: ThreadItem[]
|
||||||
|
isLoading: boolean
|
||||||
hasSession: boolean
|
hasSession: boolean
|
||||||
hiddenItemsVisible: boolean
|
hiddenItemsVisible: boolean
|
||||||
hasServerHiddenItems: boolean
|
hasServerHiddenItems: boolean
|
||||||
loadServerHiddenItems: () => Promise<void>
|
loadServerHiddenThreadItems: () => Promise<void>
|
||||||
},
|
}) {
|
||||||
) {
|
/**
|
||||||
const result = [...items]
|
* `threadItems` is memoized here, so don't mutate it directly.
|
||||||
|
*/
|
||||||
|
const items = [...threadItems]
|
||||||
|
|
||||||
for (let i = 0; i < result.length; i++) {
|
if (isLoading) {
|
||||||
const item = result[i]
|
const anchorPost = items.at(0)
|
||||||
|
const skeletonReplies =
|
||||||
|
anchorPost && anchorPost.type === 'threadPost'
|
||||||
|
? anchorPost?.value.post.replyCount ?? 4
|
||||||
|
: 4
|
||||||
|
|
||||||
|
if (!items.length) {
|
||||||
|
items.push(
|
||||||
|
views.skeleton({
|
||||||
|
key: 'anchor-skeleton',
|
||||||
|
item: 'anchor',
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
if (hasSession) {
|
||||||
|
items.push(
|
||||||
|
views.skeleton({
|
||||||
|
key: 'replyComposer',
|
||||||
|
item: 'replyComposer',
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < skeletonReplies; i++) {
|
||||||
|
items.push(
|
||||||
|
views.skeleton({
|
||||||
|
key: `anchor-skeleton-reply-${i}`,
|
||||||
|
item: 'reply',
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
const item = items[i]
|
||||||
if (
|
if (
|
||||||
item.type === 'threadPost' &&
|
item.type === 'threadPost' &&
|
||||||
item.depth === 0 &&
|
item.depth === 0 &&
|
||||||
!item.value.post.viewer?.replyDisabled &&
|
!item.value.post.viewer?.replyDisabled &&
|
||||||
hasSession
|
hasSession
|
||||||
) {
|
) {
|
||||||
result.splice(i + 1, 0, {
|
items.splice(i + 1, 0, {
|
||||||
type: 'replyComposer',
|
type: 'replyComposer',
|
||||||
key: 'replyComposer',
|
key: 'replyComposer',
|
||||||
})
|
})
|
||||||
@@ -400,19 +442,21 @@ export function combine(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hidden.length || hasServerHiddenItems) {
|
if (hiddenThreadItems.length || hasServerHiddenItems) {
|
||||||
if (hiddenItemsVisible) {
|
if (hiddenItemsVisible) {
|
||||||
result.push(...hidden)
|
items.push(...hiddenThreadItems)
|
||||||
|
items.push(...serverHiddenThreadItems)
|
||||||
} else {
|
} else {
|
||||||
result.push({
|
items.push({
|
||||||
type: 'showHiddenReplies',
|
type: 'showHiddenReplies',
|
||||||
key: 'showHiddenReplies',
|
key: 'showHiddenReplies',
|
||||||
onLoad: loadServerHiddenItems,
|
onPress: loadServerHiddenThreadItems,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result
|
return items
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ export type ThreadItem =
|
|||||||
| {
|
| {
|
||||||
type: 'showHiddenReplies'
|
type: 'showHiddenReplies'
|
||||||
key: string
|
key: string
|
||||||
onLoad: () => Promise<void>
|
onPress: () => Promise<void>
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
type: 'readMore'
|
type: 'readMore'
|
||||||
|
|||||||
Reference in New Issue
Block a user