Fix optimistic deletion for thread
This commit is contained in:
@@ -36,6 +36,11 @@ import {Link} from '#/view/com/util/Link'
|
|||||||
import {formatCount} from '#/view/com/util/numeric/format'
|
import {formatCount} from '#/view/com/util/numeric/format'
|
||||||
import {PostEmbeds, PostEmbedViewContext} from '#/view/com/util/post-embeds'
|
import {PostEmbeds, PostEmbedViewContext} from '#/view/com/util/post-embeds'
|
||||||
import {PreviewableUserAvatar} from '#/view/com/util/UserAvatar'
|
import {PreviewableUserAvatar} from '#/view/com/util/UserAvatar'
|
||||||
|
import {
|
||||||
|
LINEAR_AVI_WIDTH,
|
||||||
|
OUTER_SPACE,
|
||||||
|
REPLY_LINE_WIDTH,
|
||||||
|
} from '#/screens/PostThread/const'
|
||||||
import {atoms as a, useTheme} from '#/alf'
|
import {atoms as a, useTheme} from '#/alf'
|
||||||
import {colors} from '#/components/Admonition'
|
import {colors} from '#/components/Admonition'
|
||||||
import {Button} from '#/components/Button'
|
import {Button} from '#/components/Button'
|
||||||
@@ -65,9 +70,11 @@ export function ThreadAnchor({
|
|||||||
threadgateRecord?: AppBskyFeedThreadgate.Record
|
threadgateRecord?: AppBskyFeedThreadgate.Record
|
||||||
}) {
|
}) {
|
||||||
const postShadow = usePostShadow(item.value.post)
|
const postShadow = usePostShadow(item.value.post)
|
||||||
|
const threadRootUri = item.value.post.record.reply?.root?.uri || item.uri
|
||||||
|
const isRoot = threadRootUri === item.uri
|
||||||
|
|
||||||
if (postShadow === POST_TOMBSTONE) {
|
if (postShadow === POST_TOMBSTONE) {
|
||||||
return <PostThreadItemDeleted />
|
return <PostThreadItemDeleted isRoot={isRoot} />
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -75,6 +82,7 @@ export function ThreadAnchor({
|
|||||||
// Safeguard from clobbering per-post state below:
|
// Safeguard from clobbering per-post state below:
|
||||||
key={postShadow.uri}
|
key={postShadow.uri}
|
||||||
item={item}
|
item={item}
|
||||||
|
isRoot={isRoot}
|
||||||
postShadow={postShadow}
|
postShadow={postShadow}
|
||||||
onPostSuccess={onPostSuccess}
|
onPostSuccess={onPostSuccess}
|
||||||
threadgateRecord={threadgateRecord}
|
threadgateRecord={threadgateRecord}
|
||||||
@@ -82,34 +90,80 @@ export function ThreadAnchor({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function PostThreadItemDeleted({hideTopBorder}: {hideTopBorder?: boolean}) {
|
function PostThreadItemDeleted({isRoot}: {isRoot: boolean}) {
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
|
<ThreadItemAnchorParentReplyLine isRoot={isRoot} />
|
||||||
|
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
t.atoms.bg,
|
{
|
||||||
t.atoms.border_contrast_low,
|
paddingHorizontal: OUTER_SPACE,
|
||||||
a.p_xl,
|
paddingBottom: OUTER_SPACE,
|
||||||
a.pl_lg,
|
},
|
||||||
a.flex_row,
|
isRoot && [a.pt_lg],
|
||||||
a.gap_md,
|
|
||||||
!hideTopBorder && a.border_t,
|
|
||||||
]}>
|
]}>
|
||||||
<TrashIcon style={[t.atoms.text]} />
|
<View
|
||||||
<Text style={[t.atoms.text_contrast_medium, a.mt_2xs]}>
|
style={[
|
||||||
<Trans>This post has been deleted.</Trans>
|
a.flex_row,
|
||||||
|
a.align_center,
|
||||||
|
a.py_md,
|
||||||
|
a.rounded_sm,
|
||||||
|
t.atoms.bg_contrast_25,
|
||||||
|
]}>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
a.flex_row,
|
||||||
|
a.align_center,
|
||||||
|
a.justify_center,
|
||||||
|
{
|
||||||
|
width: LINEAR_AVI_WIDTH,
|
||||||
|
},
|
||||||
|
]}>
|
||||||
|
<TrashIcon style={[t.atoms.text_contrast_medium]} />
|
||||||
|
</View>
|
||||||
|
<Text style={[a.text_md, a.font_bold, t.atoms.text_contrast_medium]}>
|
||||||
|
<Trans>Post has been deleted</Trans>
|
||||||
</Text>
|
</Text>
|
||||||
</View>
|
</View>
|
||||||
|
</View>
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ThreadItemAnchorParentReplyLine({isRoot}: {isRoot: boolean}) {
|
||||||
|
const t = useTheme()
|
||||||
|
|
||||||
|
return !isRoot ? (
|
||||||
|
<View style={[a.pl_lg, a.flex_row, a.pb_xs, {height: a.pt_lg.paddingTop}]}>
|
||||||
|
<View style={{width: 42}}>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
{
|
||||||
|
width: REPLY_LINE_WIDTH,
|
||||||
|
marginLeft: 'auto',
|
||||||
|
marginRight: 'auto',
|
||||||
|
flexGrow: 1,
|
||||||
|
backgroundColor: t.atoms.border_contrast_low.borderColor,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
|
|
||||||
let PostThreadItemLoaded = ({
|
let PostThreadItemLoaded = ({
|
||||||
item,
|
item,
|
||||||
|
isRoot,
|
||||||
postShadow,
|
postShadow,
|
||||||
onPostSuccess,
|
onPostSuccess,
|
||||||
threadgateRecord,
|
threadgateRecord,
|
||||||
}: {
|
}: {
|
||||||
item: Extract<ThreadItem, {type: 'threadPost'}>
|
item: Extract<ThreadItem, {type: 'threadPost'}>
|
||||||
|
isRoot: boolean
|
||||||
postShadow: Shadow<AppBskyFeedDefs.PostView>
|
postShadow: Shadow<AppBskyFeedDefs.PostView>
|
||||||
onPostSuccess?: (data: OnPostSuccessData) => void
|
onPostSuccess?: (data: OnPostSuccessData) => void
|
||||||
threadgateRecord?: AppBskyFeedThreadgate.Record
|
threadgateRecord?: AppBskyFeedThreadgate.Record
|
||||||
@@ -134,7 +188,6 @@ let PostThreadItemLoaded = ({
|
|||||||
)
|
)
|
||||||
|
|
||||||
const threadRootUri = record.reply?.root?.uri || post.uri
|
const threadRootUri = record.reply?.root?.uri || post.uri
|
||||||
const isThreadRoot = threadRootUri === post.uri
|
|
||||||
const authorHref = makeProfileLink(post.author)
|
const authorHref = makeProfileLink(post.author)
|
||||||
const authorTitle = post.author.handle
|
const authorTitle = post.author.handle
|
||||||
const isThreadAuthor = getThreadAuthor(post, record) === currentAccount?.did
|
const isThreadAuthor = getThreadAuthor(post, record) === currentAccount?.did
|
||||||
@@ -191,31 +244,15 @@ let PostThreadItemLoaded = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{!isThreadRoot && (
|
<ThreadItemAnchorParentReplyLine isRoot={isRoot} />
|
||||||
<View
|
|
||||||
style={[a.pl_lg, a.flex_row, a.pb_xs, {height: a.pt_lg.paddingTop}]}>
|
|
||||||
<View style={{width: 42}}>
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
{
|
|
||||||
width: 2,
|
|
||||||
marginLeft: 'auto',
|
|
||||||
marginRight: 'auto',
|
|
||||||
flexGrow: 1,
|
|
||||||
backgroundColor: t.atoms.border_contrast_low.borderColor,
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<View
|
<View
|
||||||
testID={`postThreadItem-by-${post.author.handle}`}
|
testID={`postThreadItem-by-${post.author.handle}`}
|
||||||
style={[
|
style={[
|
||||||
a.px_lg,
|
{
|
||||||
t.atoms.border_contrast_low,
|
paddingHorizontal: OUTER_SPACE,
|
||||||
isThreadRoot && [a.pt_lg],
|
},
|
||||||
|
isRoot && [a.pt_lg],
|
||||||
]}>
|
]}>
|
||||||
<View style={[a.flex_row, a.gap_md, a.pb_md]}>
|
<View style={[a.flex_row, a.gap_md, a.pb_md]}>
|
||||||
<PreviewableUserAvatar
|
<PreviewableUserAvatar
|
||||||
|
|||||||
Reference in New Issue
Block a user