Fix up no-unauthenticated posts

This commit is contained in:
Eric Bailey
2025-06-09 17:16:44 -05:00
parent 4bf439d339
commit 03bf51206b
9 changed files with 161 additions and 7 deletions
+8 -3
View File
@@ -1,3 +1,4 @@
import {type ReactNode} from 'react'
import {View} from 'react-native'
import {
@@ -44,14 +45,17 @@ export function Text({blend, style}: TextStyleProp & SkeletonProps) {
}
export function Circle({
children,
size,
blend,
style,
}: ViewStyleProp & {size: number} & SkeletonProps) {
}: ViewStyleProp & {children?: ReactNode; size: number} & SkeletonProps) {
const t = useTheme()
return (
<View
style={[
a.justify_center,
a.align_center,
a.rounded_full,
t.atoms.bg_contrast_25,
{
@@ -60,8 +64,9 @@ export function Circle({
opacity: blend ? 0.6 : 1,
},
style,
]}
/>
]}>
{children}
</View>
)
}
@@ -0,0 +1,32 @@
import {View} from 'react-native'
import {Trans} from '@lingui/macro'
import {atoms as a, useTheme} from '#/alf'
import {Lock_Stroke2_Corner0_Rounded as LockIcon} from '#/components/icons/Lock'
import * as Skele from '#/components/Skeleton'
import {Text} from '#/components/Typography'
export function ThreadItemAnchorNoUnauthenticated() {
const t = useTheme()
return (
<View style={[a.p_lg, a.gap_md]}>
<Skele.Row style={[a.align_center, a.gap_md]}>
<Skele.Circle size={42}>
<LockIcon size="md" fill={t.atoms.text_contrast_medium.color} />
</Skele.Circle>
<Skele.Col>
<Skele.Text style={[a.text_lg, {width: '20%'}]} />
<Skele.Text blend style={[a.text_md, {width: '40%'}]} />
</Skele.Col>
</Skele.Row>
<View style={[a.py_sm]}>
<Text style={[a.text_xl, a.italic, t.atoms.text_contrast_medium]}>
<Trans>You must sign-in to view this post.</Trans>
</Text>
</View>
</View>
)
}
@@ -0,0 +1,74 @@
import {View} from 'react-native'
import {Trans} from '@lingui/macro'
import {type ThreadItem} from '#/state/queries/usePostThread/types'
import {
LINEAR_AVI_WIDTH,
OUTER_SPACE,
REPLY_LINE_WIDTH,
} from '#/screens/PostThread/const'
import {atoms as a, useTheme} from '#/alf'
import {Lock_Stroke2_Corner0_Rounded as LockIcon} from '#/components/icons/Lock'
import * as Skele from '#/components/Skeleton'
import {Text} from '#/components/Typography'
export function ThreadItemPostNoUnauthenticated({
item,
}: {
item: Extract<ThreadItem, {type: 'threadPostNoUnauthenticated'}>
}) {
const t = useTheme()
return (
<View style={[{paddingHorizontal: OUTER_SPACE}]}>
<View style={[a.flex_row, {height: 12}]}>
<View style={{width: LINEAR_AVI_WIDTH}}>
{item.ui.showParentReplyLine && (
<View
style={[
a.mx_auto,
a.flex_1,
a.mb_xs,
{
width: REPLY_LINE_WIDTH,
backgroundColor: t.atoms.border_contrast_low.borderColor,
},
]}
/>
)}
</View>
</View>
<Skele.Row style={[a.align_center, a.gap_md]}>
<Skele.Circle size={LINEAR_AVI_WIDTH}>
<LockIcon size="md" fill={t.atoms.text_contrast_medium.color} />
</Skele.Circle>
<Text style={[a.text_md, a.italic, t.atoms.text_contrast_medium]}>
<Trans>You must sign-in to view this post.</Trans>
</Text>
</Skele.Row>
<View
style={[
a.flex_row,
a.justify_center,
{
height: OUTER_SPACE / 1.5,
width: LINEAR_AVI_WIDTH,
},
]}>
{item.ui.showChildReplyLine && (
<View
style={[
a.mt_xs,
a.h_full,
{
width: REPLY_LINE_WIDTH,
backgroundColor: t.atoms.border_contrast_low.borderColor,
},
]}
/>
)}
</View>
</View>
)
}
+8
View File
@@ -20,10 +20,12 @@ import {
ThreadAnchorSkeleton,
} from '#/screens/PostThread/components/ThreadAnchor'
import {ThreadError} from '#/screens/PostThread/components/ThreadError'
import {ThreadItemAnchorNoUnauthenticated} from '#/screens/PostThread/components/ThreadItemAnchorNoUnauthenticated'
import {
ThreadItemPost,
ThreadItemPostSkeleton,
} from '#/screens/PostThread/components/ThreadItemPost'
import {ThreadItemPostNoUnauthenticated} from '#/screens/PostThread/components/ThreadItemPostNoUnauthenticated'
import {ThreadItemPostTombstone} from '#/screens/PostThread/components/ThreadItemPostTombstone'
import {ThreadItemReadMore} from '#/screens/PostThread/components/ThreadItemReadMore'
import {ThreadItemReadMoreUp} from '#/screens/PostThread/components/ThreadItemReadMoreUp'
@@ -400,6 +402,12 @@ export function Inner({uri}: {uri: string | undefined}) {
)
}
}
} else if (item.type === 'threadPostNoUnauthenticated') {
if (item.depth < 0) {
return <ThreadItemPostNoUnauthenticated item={item} />
} else if (item.depth === 0) {
return <ThreadItemAnchorNoUnauthenticated />
}
} else if (item.type === 'readMore') {
return (
<ThreadItemReadMore
+12 -3
View File
@@ -8,6 +8,7 @@ import {
} from '#/state/queries/usePostThread/types'
import {
getPostRecord,
getThreadPostNoUnauthenticatedUI,
getThreadPostUI,
getTraversalMetadata,
storeTraversalMetadata,
@@ -59,7 +60,7 @@ export function sortAndAnnotateThreadItems(
if (item.depth < 0) {
/*
* Parents are ignored until we find the highlighted post, then we walk
* Parents are ignored until we find the anchor post, then we walk
* _up_ from there.
*/
} else if (item.depth === 0) {
@@ -85,8 +86,14 @@ export function sortAndAnnotateThreadItems(
if (
AppBskyUnspeccedDefs.isThreadItemNoUnauthenticated(parent.value)
) {
threadItems.unshift(views.threadPostNoUnauthenticated(parent))
break parentTraversal
const post = views.threadPostNoUnauthenticated(parent)
post.ui = getThreadPostNoUnauthenticatedUI({
depth: parent.depth,
prevItemDepth: thread[pi - 1]?.depth,
nextItemDepth: thread[pi + 1]?.depth,
})
threadItems.unshift(post)
// break parentTraversal
} else if (AppBskyUnspeccedDefs.isThreadItemNotFound(parent.value)) {
threadItems.unshift(views.threadPostNotFound(parent))
break parentTraversal
@@ -105,6 +112,8 @@ export function sortAndAnnotateThreadItems(
)
}
}
console.log(threadItems)
}
} else if (item.depth > 0) {
/*
+4
View File
@@ -68,6 +68,10 @@ export type ThreadItem =
uri: string
depth: number
value: AppBskyUnspeccedDefs.ThreadItemNoUnauthenticated
ui: {
showParentReplyLine: boolean
showChildReplyLine: boolean
}
}
| {
type: 'threadPostNotFound'
+20
View File
@@ -154,3 +154,23 @@ export function getThreadPostUI({
precedesChildReadMore: precedesChildReadMore ?? false,
}
}
export function getThreadPostNoUnauthenticatedUI({
depth,
prevItemDepth,
nextItemDepth,
}: {
depth: number
prevItemDepth?: number
nextItemDepth?: number
}): Extract<ThreadItem, {type: 'threadPostNoUnauthenticated'}>['ui'] {
console.log('getThreadPostNoUnauthenticatedUI', {
depth,
prevItemDepth,
nextItemDepth,
})
return {
showChildReplyLine: depth < 0,
showParentReplyLine: Boolean(prevItemDepth && prevItemDepth < depth),
}
}
+2
View File
@@ -27,6 +27,8 @@ export function threadPostNoUnauthenticated({
uri,
depth,
value: value as AppBskyUnspeccedDefs.ThreadItemNoUnauthenticated,
// @ts-ignore populated by the traversal
ui: {},
}
}
+1 -1
View File
@@ -28,7 +28,7 @@ export function PostThreadScreen({route}: Props) {
return (
<Layout.Screen testID="postThreadScreen">
{gate('post_threads_v2_unspecced') ? (
{gate('post_threads_v2_unspecced') || __DEV__ ? (
<Inner uri={uri} />
) : (
<PostThreadComponent uri={uri} />