diff --git a/assets/icons/calendarClock_stroke2_corner0_rounded.svg b/assets/icons/calendarClock_stroke2_corner0_rounded.svg
new file mode 100644
index 0000000000..e6535e0861
--- /dev/null
+++ b/assets/icons/calendarClock_stroke2_corner0_rounded.svg
@@ -0,0 +1 @@
+
diff --git a/src/components/icons/CalendarClock.tsx b/src/components/icons/CalendarClock.tsx
new file mode 100644
index 0000000000..52ba8094e0
--- /dev/null
+++ b/src/components/icons/CalendarClock.tsx
@@ -0,0 +1,5 @@
+import {createSinglePathSVG} from './TEMPLATE'
+
+export const CalendarClock_Stroke2_Corner0_Rounded = createSinglePathSVG({
+ path: 'M15.439 3.148a1 1 0 0 1 .41.645l.568 3.22a7 7 0 1 1-6.174 10.97L4.32 19.027a1 1 0 0 1-1.159-.811L1.078 6.398a1 1 0 0 1 .81-1.158l12.803-2.258a1 1 0 0 1 .748.166ZM9.325 16.114A7 7 0 0 1 9 14c0-1.56.51-3 1.372-4.164l-6.456 1.139 1.041 5.909 4.368-.77ZM3.568 9.005l10.833-1.91-.347-1.97L3.22 7.036l.347 1.97ZM16 9a5 5 0 1 0 0 10 5 5 0 0 0 0-10Zm0 2a1 1 0 0 1 1 1v1.586l1.374 1.374a1 1 0 0 1-1.414 1.414l-1.667-1.667A1 1 0 0 1 15 14v-2a1 1 0 0 1 1-1Z',
+})
diff --git a/src/view/com/post-thread/PostThreadItem.tsx b/src/view/com/post-thread/PostThreadItem.tsx
index 5044f9621a..9edca4335d 100644
--- a/src/view/com/post-thread/PostThreadItem.tsx
+++ b/src/view/com/post-thread/PostThreadItem.tsx
@@ -1,5 +1,5 @@
import React, {memo, useMemo} from 'react'
-import {StyleSheet, View} from 'react-native'
+import {StyleSheet, Text as RNText, View} from 'react-native'
import {
AppBskyFeedDefs,
AppBskyFeedPost,
@@ -8,7 +8,6 @@ import {
ModerationDecision,
RichText as RichTextAPI,
} from '@atproto/api'
-import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {msg, Plural, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
@@ -21,6 +20,7 @@ import {sanitizeHandle} from '#/lib/strings/handles'
import {countLines} from '#/lib/strings/helpers'
import {niceDate} from '#/lib/strings/time'
import {s} from '#/lib/styles'
+import {getTranslatorLink, isPostInLanguage} from '#/locale/helpers'
import {POST_TOMBSTONE, Shadow, usePostShadow} from '#/state/cache/post-shadow'
import {useLanguagePrefs} from '#/state/preferences'
import {ThreadPost} from '#/state/queries/post-thread'
@@ -28,26 +28,30 @@ import {useSession} from '#/state/session'
import {useComposerControls} from '#/state/shell/composer'
import {useMergedThreadgateHiddenReplies} from '#/state/threadgate-hidden-replies'
import {PostThreadFollowBtn} from '#/view/com/post-thread/PostThreadFollowBtn'
+import {ErrorMessage} from '#/view/com/util/error/ErrorMessage'
+import {Link, TextLink} from '#/view/com/util/Link'
+import {formatCount} from '#/view/com/util/numeric/format'
+import {PostCtrls} from '#/view/com/util/post-ctrls/PostCtrls'
+import {PostEmbeds, PostEmbedViewContext} from '#/view/com/util/post-embeds'
+import {PostMeta} from '#/view/com/util/PostMeta'
+import {PreviewableUserAvatar} from '#/view/com/util/UserAvatar'
import {atoms as a, useTheme} from '#/alf'
+import {colors} from '#/components/Admonition'
+import {Button} from '#/components/Button'
+import {CalendarClock_Stroke2_Corner0_Rounded as CalendarClockIcon} from '#/components/icons/CalendarClock'
+import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRightIcon} from '#/components/icons/Chevron'
+import {Trash_Stroke2_Corner0_Rounded as TrashIcon} from '#/components/icons/Trash'
import {InlineLinkText} from '#/components/Link'
+import {ContentHider} from '#/components/moderation/ContentHider'
+import {LabelsOnMyPost} from '#/components/moderation/LabelsOnMe'
+import {PostAlerts} from '#/components/moderation/PostAlerts'
+import {PostHider} from '#/components/moderation/PostHider'
import {AppModerationCause} from '#/components/Pills'
+import * as Prompt from '#/components/Prompt'
import {RichText} from '#/components/RichText'
import {SubtleWebHover} from '#/components/SubtleWebHover'
-import {Text as NewText} from '#/components/Typography'
-import {ContentHider} from '../../../components/moderation/ContentHider'
-import {LabelsOnMyPost} from '../../../components/moderation/LabelsOnMe'
-import {PostAlerts} from '../../../components/moderation/PostAlerts'
-import {PostHider} from '../../../components/moderation/PostHider'
-import {WhoCanReply} from '../../../components/WhoCanReply'
-import {getTranslatorLink, isPostInLanguage} from '../../../locale/helpers'
-import {ErrorMessage} from '../util/error/ErrorMessage'
-import {Link, TextLink} from '../util/Link'
-import {formatCount} from '../util/numeric/format'
-import {PostCtrls} from '../util/post-ctrls/PostCtrls'
-import {PostEmbeds, PostEmbedViewContext} from '../util/post-embeds'
-import {PostMeta} from '../util/PostMeta'
-import {Text} from '../util/text/Text'
-import {PreviewableUserAvatar} from '../util/UserAvatar'
+import {Text} from '#/components/Typography'
+import {WhoCanReply} from '#/components/WhoCanReply'
export function PostThreadItem({
post,
@@ -125,19 +129,20 @@ export function PostThreadItem({
}
function PostThreadItemDeleted({hideTopBorder}: {hideTopBorder?: boolean}) {
- const pal = usePalette('default')
+ const t = useTheme()
return (
-
-
+
+
This post has been deleted.
@@ -308,7 +313,7 @@ let PostThreadItemLoaded = ({
/>
-
@@ -317,10 +322,10 @@ let PostThreadItemLoaded = ({
sanitizeHandle(post.author.handle),
moderation.ui('displayName'),
)}
-
+
-
{sanitizeHandle(post.author.handle, '@')}
-
+
{currentAccount?.did !== post.author.did && (
@@ -393,48 +398,48 @@ let PostThreadItemLoaded = ({
]}>
{post.repostCount != null && post.repostCount !== 0 ? (
-
-
+
{formatCount(i18n, post.repostCount)}
- {' '}
+ {' '}
-
+
) : null}
{post.quoteCount != null &&
post.quoteCount !== 0 &&
!post.viewer?.embeddingDisabled ? (
-
-
+
{formatCount(i18n, post.quoteCount)}
- {' '}
+ {' '}
-
+
) : null}
{post.likeCount != null && post.likeCount !== 0 ? (
-
-
+
{formatCount(i18n, post.likeCount)}
- {' '}
+ {' '}
-
+
) : null}
@@ -617,13 +622,13 @@ let PostThreadItemLoaded = ({
href={postHref}
title={itemTitle}
noFeedback>
-
+
More
-
) : undefined}
@@ -732,32 +737,124 @@ function ExpandedPostDetails({
}, [openLink, translatorUrl])
return (
-
-
- {niceDate(i18n, post.indexedAt)}
-
- {isRootPost && (
-
- )}
- {needsTranslation && (
- <>
-
- ·
-
+
+
+
+
+ {niceDate(i18n, post.indexedAt)}
+
+ {isRootPost && (
+
+ )}
+ {needsTranslation && (
+ <>
+
+ ·
+
-
- Translate
-
- >
- )}
+
+ Translate
+
+ >
+ )}
+
)
}
+function BackdatedPostIndicator({post}: {post: AppBskyFeedDefs.PostView}) {
+ const t = useTheme()
+ const {_, i18n} = useLingui()
+ const control = Prompt.usePromptControl()
+
+ const indexedAt = new Date(post.indexedAt)
+ const createdAt = AppBskyFeedPost.isRecord(post.record)
+ ? new Date(post.record.createdAt)
+ : new Date(post.indexedAt)
+
+ // backdated if createdAt is 24 hours or more before indexedAt
+ const isBackdated =
+ indexedAt.getTime() - createdAt.getTime() > 24 * 60 * 60 * 1000
+
+ if (!isBackdated) return null
+
+ const orange = t.name === 'light' ? colors.warning.dark : colors.warning.light
+
+ return (
+ <>
+
+
+
+
+ Archived post
+
+
+
+ This post claims to have been created on{' '}
+ {niceDate(i18n, createdAt)},
+ but was first seen by Bluesky on{' '}
+ {niceDate(i18n, indexedAt)}.
+
+
+
+
+ Bluesky cannot confirm the authenticity of the claimed date.
+
+
+
+ {}} />
+
+
+ >
+ )
+}
+
function getThreadAuthor(
post: AppBskyFeedDefs.PostView,
record: AppBskyFeedPost.Record,