Update APIs
This commit is contained in:
@@ -11,17 +11,13 @@ import {
|
|||||||
HiddenReplyKind,
|
HiddenReplyKind,
|
||||||
type UsePostThreadProps,
|
type UsePostThreadProps,
|
||||||
} from '#/state/queries/usePostThread/types'
|
} from '#/state/queries/usePostThread/types'
|
||||||
import {
|
import {getThreadgateRecord} from '#/state/queries/usePostThread/utils'
|
||||||
getThreadgateRecord,
|
|
||||||
mapSortOptionsToSortID,
|
|
||||||
} from '#/state/queries/usePostThread/utils'
|
|
||||||
import {useAgent, useSession} from '#/state/session'
|
import {useAgent, useSession} from '#/state/session'
|
||||||
import {useMergeThreadgateHiddenReplies} from '#/state/threadgate-hidden-replies'
|
import {useMergeThreadgateHiddenReplies} from '#/state/threadgate-hidden-replies'
|
||||||
|
|
||||||
export * from '#/state/queries/usePostThread/types'
|
export * from '#/state/queries/usePostThread/types'
|
||||||
|
|
||||||
export function usePostThread({
|
export function usePostThread({
|
||||||
uri,
|
|
||||||
enabled: isEnabled,
|
enabled: isEnabled,
|
||||||
params,
|
params,
|
||||||
state,
|
state,
|
||||||
@@ -32,9 +28,8 @@ export function usePostThread({
|
|||||||
const moderationOpts = useModerationOpts()
|
const moderationOpts = useModerationOpts()
|
||||||
const mergeThreadgateHiddenReplies = useMergeThreadgateHiddenReplies()
|
const mergeThreadgateHiddenReplies = useMergeThreadgateHiddenReplies()
|
||||||
|
|
||||||
const enabled = isEnabled !== false && !!uri && !!moderationOpts
|
const enabled = isEnabled !== false && !!params.anchor && !!moderationOpts
|
||||||
const queryKey = createPostThreadQueryKey({
|
const queryKey = createPostThreadQueryKey({
|
||||||
uri,
|
|
||||||
params,
|
params,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -44,16 +39,17 @@ export function usePostThread({
|
|||||||
gcTime: 0,
|
gcTime: 0,
|
||||||
async queryFn() {
|
async queryFn() {
|
||||||
const {data} = await agent.app.bsky.unspecced.getPostThreadV2({
|
const {data} = await agent.app.bsky.unspecced.getPostThreadV2({
|
||||||
anchor: uri!,
|
anchor: params.anchor!,
|
||||||
branchingFactor: params.view === 'linear' ? 1 : 3, // 100 TODO
|
branchingFactor: params.view === 'linear' ? 1 : 3, // 100 TODO
|
||||||
below: 3,
|
below: 3,
|
||||||
sorting: mapSortOptionsToSortID(params.sort),
|
sort: params.sort,
|
||||||
|
prioritizeFollowedUsers: params.prioritizeFollowedUsers,
|
||||||
})
|
})
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
placeholderData() {
|
placeholderData() {
|
||||||
if (!uri) return
|
if (!params.anchor) return
|
||||||
const placeholder = getThreadPlaceholder(qc, uri)
|
const placeholder = getThreadPlaceholder(qc, params.anchor)
|
||||||
if (placeholder) {
|
if (placeholder) {
|
||||||
return {thread: [placeholder]}
|
return {thread: [placeholder]}
|
||||||
}
|
}
|
||||||
@@ -96,7 +92,6 @@ export function usePostThread({
|
|||||||
return {
|
return {
|
||||||
...query,
|
...query,
|
||||||
data: {
|
data: {
|
||||||
anchorIndex: items.findIndex(i => Boolean(i.ui?.isAnchor)),
|
|
||||||
items,
|
items,
|
||||||
threadgate: query.data?.threadgate,
|
threadgate: query.data?.threadgate,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
APP_BSKY_UNSPECCED,
|
|
||||||
AtUri,
|
|
||||||
AppBskyUnspeccedGetPostThreadV2,
|
AppBskyUnspeccedGetPostThreadV2,
|
||||||
|
AtUri,
|
||||||
type ModerationDecision,
|
type ModerationDecision,
|
||||||
type ModerationOpts,
|
type ModerationOpts,
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
@@ -30,7 +29,11 @@ export function flatten(
|
|||||||
|
|
||||||
if (item.type === 'threadPost') {
|
if (item.type === 'threadPost') {
|
||||||
// TODO should not insert if not found post etc
|
// TODO should not insert if not found post etc
|
||||||
if (item.ui.isAnchor && hasSession && !item.value.post.viewer?.replyDisabled) {
|
if (
|
||||||
|
item.ui.isAnchor &&
|
||||||
|
hasSession &&
|
||||||
|
!item.value.post.viewer?.replyDisabled
|
||||||
|
) {
|
||||||
flattened.splice(i + 1, 0, {
|
flattened.splice(i + 1, 0, {
|
||||||
type: 'replyComposer',
|
type: 'replyComposer',
|
||||||
key: 'replyComposer',
|
key: 'replyComposer',
|
||||||
@@ -39,10 +42,10 @@ export function flatten(
|
|||||||
|
|
||||||
const prev = unhydratedReplyIntervals[unhydratedReplyIntervals.length - 1]
|
const prev = unhydratedReplyIntervals[unhydratedReplyIntervals.length - 1]
|
||||||
|
|
||||||
if (item.annotations.has(APP_BSKY_UNSPECCED.GetPostThreadV2HasMoreReplies)) {
|
if (item.value.moreReplies > 0) {
|
||||||
unhydratedReplyIntervals.push({
|
unhydratedReplyIntervals.push({
|
||||||
item,
|
item,
|
||||||
replyCount: item.value.post.replyCount || 0,
|
replyCount: item.value.moreReplies,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,7 +53,8 @@ export function flatten(
|
|||||||
* If direct child of previous item with `hasMoreReplies`, subtract
|
* If direct child of previous item with `hasMoreReplies`, subtract
|
||||||
*/
|
*/
|
||||||
if (prev && item.depth === prev.item.depth + 1) {
|
if (prev && item.depth === prev.item.depth + 1) {
|
||||||
prev.replyCount = Math.max(0, prev.replyCount - 1)
|
// TODO test if we need this
|
||||||
|
// prev.replyCount = Math.max(0, prev.replyCount - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prev && item.depth <= prev.item.depth) {
|
if (prev && item.depth <= prev.item.depth) {
|
||||||
|
|||||||
@@ -1,28 +1,26 @@
|
|||||||
import {
|
import {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
type APP_BSKY_UNSPECCED,
|
|
||||||
type AtUri,
|
|
||||||
type AppBskyFeedDefs,
|
type AppBskyFeedDefs,
|
||||||
type AppBskyFeedPost,
|
type AppBskyFeedPost,
|
||||||
type AppBskyUnspeccedGetPostThreadV2,
|
type AppBskyUnspeccedGetPostThreadV2,
|
||||||
type BskyThreadViewPreference,
|
type AtUri,
|
||||||
type ModerationDecision,
|
type ModerationDecision,
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
|
|
||||||
export const postThreadQueryKeyRoot = 'getPostThreadV2' as const
|
export const postThreadQueryKeyRoot = 'getPostThreadV2' as const
|
||||||
|
|
||||||
export const createPostThreadQueryKey = (
|
export const createPostThreadQueryKey = (
|
||||||
props: Pick<UsePostThreadProps, 'uri' | 'params'>,
|
props: Pick<UsePostThreadProps, 'params'>,
|
||||||
) => [postThreadQueryKeyRoot, props] as const
|
) => [postThreadQueryKeyRoot, props] as const
|
||||||
|
|
||||||
export type PostThreadParams = {
|
export type PostThreadParams = Pick<
|
||||||
|
AppBskyUnspeccedGetPostThreadV2.QueryParams,
|
||||||
|
'sort' | 'prioritizeFollowedUsers'
|
||||||
|
> & {
|
||||||
|
anchor?: string
|
||||||
view: 'tree' | 'linear'
|
view: 'tree' | 'linear'
|
||||||
sort: 'top' | 'oldest' | 'newest' | string
|
|
||||||
prioritizeFollows: BskyThreadViewPreference['prioritizeFollowedUsers']
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UsePostThreadProps = {
|
export type UsePostThreadProps = {
|
||||||
uri?: string
|
|
||||||
enabled?: boolean
|
enabled?: boolean
|
||||||
params: PostThreadParams
|
params: PostThreadParams
|
||||||
state: {
|
state: {
|
||||||
@@ -47,12 +45,6 @@ export type Slice =
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
moderation: ModerationDecision
|
moderation: ModerationDecision
|
||||||
/**
|
|
||||||
* Reference via {@link APP_BSKY_UNSPECCED}
|
|
||||||
*/
|
|
||||||
annotations: Set<
|
|
||||||
AppBskyUnspeccedGetPostThreadV2.ThreadItemPost['annotations'][number]
|
|
||||||
>
|
|
||||||
ui: {
|
ui: {
|
||||||
isAnchor: boolean
|
isAnchor: boolean
|
||||||
showParentReplyLine: boolean
|
showParentReplyLine: boolean
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import {
|
import {
|
||||||
APP_BSKY_UNSPECCED,
|
|
||||||
type AppBskyFeedDefs,
|
type AppBskyFeedDefs,
|
||||||
AppBskyFeedPost,
|
AppBskyFeedPost,
|
||||||
AppBskyFeedThreadgate,
|
AppBskyFeedThreadgate,
|
||||||
@@ -7,22 +6,8 @@ import {
|
|||||||
AtUri,
|
AtUri,
|
||||||
} from '@atproto/api'
|
} from '@atproto/api'
|
||||||
|
|
||||||
import {type PostThreadParams} from '#/state/queries/usePostThread/types'
|
|
||||||
import * as bsky from '#/types/bsky'
|
import * as bsky from '#/types/bsky'
|
||||||
|
|
||||||
export function mapSortOptionsToSortID(sort: PostThreadParams['sort']) {
|
|
||||||
switch (sort) {
|
|
||||||
case 'top':
|
|
||||||
return APP_BSKY_UNSPECCED.GetPostThreadV2Top
|
|
||||||
case 'oldest':
|
|
||||||
return APP_BSKY_UNSPECCED.GetPostThreadV2Oldest
|
|
||||||
case 'newest':
|
|
||||||
return APP_BSKY_UNSPECCED.GetPostThreadV2Newest
|
|
||||||
default:
|
|
||||||
return APP_BSKY_UNSPECCED.GetPostThreadV2Top
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getThreadgateRecord(
|
export function getThreadgateRecord(
|
||||||
view: AppBskyUnspeccedGetPostThreadV2.OutputSchema['threadgate'],
|
view: AppBskyUnspeccedGetPostThreadV2.OutputSchema['threadgate'],
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -90,7 +90,6 @@ export function threadPost({
|
|||||||
record: AppBskyFeedPost.Record
|
record: AppBskyFeedPost.Record
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
annotations: new Set(value.annotations),
|
|
||||||
moderation: moderatePost(value.post, moderationOpts),
|
moderation: moderatePost(value.post, moderationOpts),
|
||||||
ui: {
|
ui: {
|
||||||
isAnchor: depth === 0,
|
isAnchor: depth === 0,
|
||||||
@@ -114,7 +113,11 @@ export function postViewToThreadPlaceholder(
|
|||||||
value: {
|
value: {
|
||||||
$type: 'app.bsky.unspecced.getPostThreadV2#threadItemPost',
|
$type: 'app.bsky.unspecced.getPostThreadV2#threadItemPost',
|
||||||
post,
|
post,
|
||||||
annotations: [],
|
hiddenByThreadgate: false,
|
||||||
|
opThread: false,
|
||||||
|
moreParents: false,
|
||||||
|
moreReplies: 0,
|
||||||
|
mutedByViewer: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,24 +5,25 @@ import {useLingui} from '@lingui/react'
|
|||||||
import {useFocusEffect} from '@react-navigation/native'
|
import {useFocusEffect} from '@react-navigation/native'
|
||||||
|
|
||||||
import {HITSLOP_10} from '#/lib/constants'
|
import {HITSLOP_10} from '#/lib/constants'
|
||||||
|
// import {PostThread as PostThreadComponent} from '#/view/com/post-thread/PostThread'
|
||||||
|
import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender'
|
||||||
|
import {useOpenComposer} from '#/lib/hooks/useOpenComposer'
|
||||||
|
import {makeProfileLink} from '#/lib/routes/links'
|
||||||
import {
|
import {
|
||||||
type CommonNavigatorParams,
|
type CommonNavigatorParams,
|
||||||
type NativeStackScreenProps,
|
type NativeStackScreenProps,
|
||||||
} from '#/lib/routes/types'
|
} from '#/lib/routes/types'
|
||||||
|
import {ScrollProvider} from '#/lib/ScrollContext'
|
||||||
import {cleanError} from '#/lib/strings/errors'
|
import {cleanError} from '#/lib/strings/errors'
|
||||||
import {makeRecordUri} from '#/lib/strings/url-helpers'
|
import {makeRecordUri} from '#/lib/strings/url-helpers'
|
||||||
import {isNative} from '#/platform/detection'
|
import {isNative} from '#/platform/detection'
|
||||||
import {useSetMinimalShellMode} from '#/state/shell'
|
|
||||||
import {PostThread as PostThreadComponent} from '#/view/com/post-thread/PostThread'
|
|
||||||
import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender'
|
|
||||||
import {useOpenComposer} from '#/lib/hooks/useOpenComposer'
|
|
||||||
import {ScrollProvider} from '#/lib/ScrollContext'
|
|
||||||
import {usePreferencesQuery} from '#/state/queries/preferences'
|
import {usePreferencesQuery} from '#/state/queries/preferences'
|
||||||
import {
|
import {
|
||||||
HiddenReplyKind,
|
HiddenReplyKind,
|
||||||
type Slice,
|
type Slice,
|
||||||
usePostThread,
|
usePostThread,
|
||||||
} from '#/state/queries/usePostThread'
|
} from '#/state/queries/usePostThread'
|
||||||
|
import {useSetMinimalShellMode} from '#/state/shell'
|
||||||
import {type OnPostSuccessData} from '#/state/shell/composer'
|
import {type OnPostSuccessData} from '#/state/shell/composer'
|
||||||
import {PostThreadComposePrompt} from '#/view/com/post-thread/PostThreadComposePrompt'
|
import {PostThreadComposePrompt} from '#/view/com/post-thread/PostThreadComposePrompt'
|
||||||
import {PostThreadItem} from '#/view/com/post-thread/PostThreadItem'
|
import {PostThreadItem} from '#/view/com/post-thread/PostThreadItem'
|
||||||
@@ -30,21 +31,14 @@ import {PostThreadShowHiddenReplies} from '#/view/com/post-thread/PostThreadShow
|
|||||||
import {List, type ListMethods} from '#/view/com/util/List'
|
import {List, type ListMethods} from '#/view/com/util/List'
|
||||||
import {atoms as a, useBreakpoints, useTheme, web} from '#/alf'
|
import {atoms as a, useBreakpoints, useTheme, web} from '#/alf'
|
||||||
import {Button, ButtonIcon} from '#/components/Button'
|
import {Button, ButtonIcon} from '#/components/Button'
|
||||||
import {Link} from '#/components/Link'
|
|
||||||
import {makeProfileLink} from '#/lib/routes/links'
|
|
||||||
import {SettingsSliderVertical_Stroke2_Corner0_Rounded as SettingsSlider} from '#/components/icons/SettingsSlider'
|
|
||||||
import {CirclePlus_Stroke2_Corner0_Rounded as CirclePlus} from '#/components/icons/CirclePlus'
|
import {CirclePlus_Stroke2_Corner0_Rounded as CirclePlus} from '#/components/icons/CirclePlus'
|
||||||
|
import {SettingsSliderVertical_Stroke2_Corner0_Rounded as SettingsSlider} from '#/components/icons/SettingsSlider'
|
||||||
import * as Layout from '#/components/Layout'
|
import * as Layout from '#/components/Layout'
|
||||||
|
import {Link} from '#/components/Link'
|
||||||
import {ListFooter} from '#/components/Lists'
|
import {ListFooter} from '#/components/Lists'
|
||||||
import * as Menu from '#/components/Menu'
|
import * as Menu from '#/components/Menu'
|
||||||
import {Text} from '#/components/Typography'
|
import {Text} from '#/components/Typography'
|
||||||
|
|
||||||
const MAINTAIN_VISIBLE_CONTENT_POSITION = {
|
|
||||||
// We don't insert any elements before the root row while loading.
|
|
||||||
// So the row we want to use as the scroll anchor is the first row.
|
|
||||||
minIndexForVisible: 0,
|
|
||||||
}
|
|
||||||
|
|
||||||
type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostThread'>
|
type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostThread'>
|
||||||
export function PostThreadScreen({route}: Props) {
|
export function PostThreadScreen({route}: Props) {
|
||||||
const setMinimalShellMode = useSetMinimalShellMode()
|
const setMinimalShellMode = useSetMinimalShellMode()
|
||||||
@@ -144,12 +138,12 @@ export function Inner({uri}: {uri: string | undefined}) {
|
|||||||
>(new Set())
|
>(new Set())
|
||||||
|
|
||||||
const {isFetching, error, data, refetch, insertReplies} = usePostThread({
|
const {isFetching, error, data, refetch, insertReplies} = usePostThread({
|
||||||
uri,
|
|
||||||
enabled: isThreadPreferencesLoaded,
|
enabled: isThreadPreferencesLoaded,
|
||||||
params: {
|
params: {
|
||||||
|
anchor: uri,
|
||||||
sort: sortReplies,
|
sort: sortReplies,
|
||||||
view: treeViewEnabled ? 'tree' : 'linear',
|
view: treeViewEnabled ? 'tree' : 'linear',
|
||||||
prioritizeFollows: prioritizeFollowedUsers,
|
prioritizeFollowedUsers,
|
||||||
},
|
},
|
||||||
state: {
|
state: {
|
||||||
shownHiddenReplyKinds,
|
shownHiddenReplyKinds,
|
||||||
@@ -236,9 +230,7 @@ export function Inner({uri}: {uri: string | undefined}) {
|
|||||||
hasMore={false} // TODO need to replace this entirely
|
hasMore={false} // TODO need to replace this entirely
|
||||||
showChildReplyLine={item.ui.showChildReplyLine}
|
showChildReplyLine={item.ui.showChildReplyLine}
|
||||||
showParentReplyLine={item.ui.showParentReplyLine}
|
showParentReplyLine={item.ui.showParentReplyLine}
|
||||||
hasPrecedingItem={
|
hasPrecedingItem={item.ui.showParentReplyLine} // !!hasUnrevealedParents // TODO
|
||||||
item.ui.showParentReplyLine
|
|
||||||
} // !!hasUnrevealedParents // TODO
|
|
||||||
overrideBlur={
|
overrideBlur={
|
||||||
shownHiddenReplyKinds.has(HiddenReplyKind.Muted) && item.depth > 0
|
shownHiddenReplyKinds.has(HiddenReplyKind.Muted) && item.depth > 0
|
||||||
}
|
}
|
||||||
@@ -358,8 +350,6 @@ export function Inner({uri}: {uri: string | undefined}) {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('PostThreadScreen', data?.anchorIndex)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Layout.Header.Outer headerRef={headerRef}>
|
<Layout.Header.Outer headerRef={headerRef}>
|
||||||
@@ -400,7 +390,7 @@ export function Inner({uri}: {uri: string | undefined}) {
|
|||||||
*/
|
*/
|
||||||
maintainVisibleContentPosition={
|
maintainVisibleContentPosition={
|
||||||
isNative // && hasParents // TODO not sure we need this
|
isNative // && hasParents // TODO not sure we need this
|
||||||
? { minIndexForVisible: 0 } // MAINTAIN_VISIBLE_CONTENT_POSITION
|
? {minIndexForVisible: 0} // MAINTAIN_VISIBLE_CONTENT_POSITION
|
||||||
: undefined
|
: undefined
|
||||||
}
|
}
|
||||||
desktopFixedHeight
|
desktopFixedHeight
|
||||||
|
|||||||
Reference in New Issue
Block a user