diff --git a/src/components/PostControls/RepostButton.tsx b/src/components/PostControls/RepostButton.tsx
index cc3f0b7a0a..522e80dd3f 100644
--- a/src/components/PostControls/RepostButton.tsx
+++ b/src/components/PostControls/RepostButton.tsx
@@ -5,12 +5,12 @@ import {useLingui} from '@lingui/react'
import {useHaptics} from '#/lib/haptics'
import {useRequireAuth} from '#/state/session'
-import {formatCount} from '#/view/com/util/numeric/format'
import {atoms as a, useTheme} from '#/alf'
import {Button, ButtonText} from '#/components/Button'
import * as Dialog from '#/components/Dialog'
import {CloseQuote_Stroke2_Corner1_Rounded as Quote} from '#/components/icons/Quote'
import {Repost_Stroke2_Corner3_Rounded as Repost} from '#/components/icons/Repost'
+import {formatPostStatCount} from '#/components/PostControls/util'
import {Text} from '#/components/Typography'
import {
PostControlButton,
@@ -25,6 +25,7 @@ interface Props {
onQuote: () => void
big?: boolean
embeddingDisabled: boolean
+ compactCount?: boolean
}
let RepostButton = ({
@@ -34,6 +35,7 @@ let RepostButton = ({
onQuote,
big,
embeddingDisabled,
+ compactCount,
}: Props): React.ReactNode => {
const t = useTheme()
const {_, i18n} = useLingui()
@@ -86,7 +88,7 @@ let RepostButton = ({
{typeof repostCount !== 'undefined' && repostCount > 0 && (
- {formatCount(i18n, repostCount)}
+ {formatPostStatCount(i18n, repostCount, {compact: compactCount})}
)}
diff --git a/src/components/PostControls/index.tsx b/src/components/PostControls/index.tsx
index 0c7ea86c22..49157171bb 100644
--- a/src/components/PostControls/index.tsx
+++ b/src/components/PostControls/index.tsx
@@ -24,10 +24,10 @@ import {
ProgressGuideAction,
useProgressGuideControls,
} from '#/state/shell/progress-guide'
-import {formatCount} from '#/view/com/util/numeric/format'
import * as Toast from '#/view/com/util/Toast'
import {atoms as a, useBreakpoints} from '#/alf'
import {Reply as Bubble} from '#/components/icons/Reply'
+import {formatPostStatCount} from '#/components/PostControls/util'
import {BookmarkButton} from './BookmarkButton'
import {
PostControlButton,
@@ -52,6 +52,7 @@ let PostControls = ({
threadgateRecord,
onShowLess,
viaRepost,
+ variant,
}: {
big?: boolean
post: Shadow
@@ -66,6 +67,7 @@ let PostControls = ({
threadgateRecord?: AppBskyFeedThreadgate.Record
onShowLess?: (interaction: AppBskyFeedDefs.Interaction) => void
viaRepost?: {uri: string; cid: string}
+ variant?: 'compact' | 'normal' | 'large'
}): React.ReactNode => {
const {_, i18n} = useLingui()
const {openComposer} = useOpenComposer()
@@ -224,7 +226,9 @@ let PostControls = ({
{typeof post.replyCount !== 'undefined' && post.replyCount > 0 && (
- {formatCount(i18n, post.replyCount)}
+ {formatPostStatCount(i18n, post.replyCount, {
+ compact: variant === 'compact',
+ })}
)}
@@ -237,6 +241,7 @@ let PostControls = ({
onQuote={onQuote}
big={big}
embeddingDisabled={Boolean(post.viewer?.embeddingDisabled)}
+ compactCount={variant === 'compact'}
/>
@@ -277,6 +282,7 @@ let PostControls = ({
big={big}
isLiked={Boolean(post.viewer?.like)}
hasBeenToggled={hasLikeIconBeenToggled}
+ compactCount={variant === 'compact'}
/>
diff --git a/src/components/PostControls/util.ts b/src/components/PostControls/util.ts
new file mode 100644
index 0000000000..2997817cac
--- /dev/null
+++ b/src/components/PostControls/util.ts
@@ -0,0 +1,19 @@
+import {type I18n} from '@lingui/core'
+
+export function formatPostStatCount(
+ i18n: I18n,
+ count: number,
+ {
+ compact = false,
+ }: {
+ compact?: boolean
+ } = {},
+): string {
+ const isOver10k = count >= 10_000
+ return i18n.number(count, {
+ notation: 'compact',
+ maximumFractionDigits: isOver10k || compact ? 0 : 1,
+ // @ts-expect-error - roundingMode not in the types
+ roundingMode: 'trunc',
+ })
+}
diff --git a/src/lib/custom-animations/CountWheel.tsx b/src/lib/custom-animations/CountWheel.tsx
index 4b131db2dc..6db22554e1 100644
--- a/src/lib/custom-animations/CountWheel.tsx
+++ b/src/lib/custom-animations/CountWheel.tsx
@@ -10,9 +10,9 @@ import {i18n} from '@lingui/core'
import {decideShouldRoll} from '#/lib/custom-animations/util'
import {s} from '#/lib/styles'
-import {formatCount} from '#/view/com/util/numeric/format'
import {Text} from '#/view/com/util/text/Text'
import {atoms as a, useTheme} from '#/alf'
+import {formatPostStatCount} from '#/components/PostControls/util'
const animationConfig = {
duration: 400,
@@ -92,11 +92,13 @@ export function CountWheel({
big,
isLiked,
hasBeenToggled,
+ compactCount,
}: {
likeCount: number
big?: boolean
isLiked: boolean
hasBeenToggled: boolean
+ compactCount?: boolean
}) {
const t = useTheme()
const shouldAnimate = !useReducedMotion() && hasBeenToggled
@@ -109,8 +111,12 @@ export function CountWheel({
const [key, setKey] = React.useState(0)
const [prevCount, setPrevCount] = React.useState(likeCount)
const prevIsLiked = React.useRef(isLiked)
- const formattedCount = formatCount(i18n, likeCount)
- const formattedPrevCount = formatCount(i18n, prevCount)
+ const formattedCount = formatPostStatCount(i18n, likeCount, {
+ compact: compactCount,
+ })
+ const formattedPrevCount = formatPostStatCount(i18n, prevCount, {
+ compact: compactCount,
+ })
React.useEffect(() => {
if (isLiked === prevIsLiked.current) {
diff --git a/src/screens/PostThread/components/ThreadItemAnchor.tsx b/src/screens/PostThread/components/ThreadItemAnchor.tsx
index b59397b0b5..2386e6f339 100644
--- a/src/screens/PostThread/components/ThreadItemAnchor.tsx
+++ b/src/screens/PostThread/components/ThreadItemAnchor.tsx
@@ -32,7 +32,6 @@ import {useSession} from '#/state/session'
import {type OnPostSuccessData} from '#/state/shell/composer'
import {useMergedThreadgateHiddenReplies} from '#/state/threadgate-hidden-replies'
import {type PostSource} from '#/state/unstable-post-source'
-import {formatCount} from '#/view/com/util/numeric/format'
import {PreviewableUserAvatar} from '#/view/com/util/UserAvatar'
import {ThreadItemAnchorFollowButton} from '#/screens/PostThread/components/ThreadItemAnchorFollowButton'
import {
@@ -53,6 +52,7 @@ import {PostAlerts} from '#/components/moderation/PostAlerts'
import {type AppModerationCause} from '#/components/Pills'
import {Embed, PostEmbedViewContext} from '#/components/Post/Embed'
import {PostControls} from '#/components/PostControls'
+import {formatPostStatCount} from '#/components/PostControls/util'
import {ProfileHoverCard} from '#/components/ProfileHoverCard'
import * as Prompt from '#/components/Prompt'
import {RichText} from '#/components/RichText'
@@ -434,7 +434,7 @@ const ThreadItemAnchorInner = memo(function ThreadItemAnchorInner({
testID="repostCount-expanded"
style={[a.text_md, t.atoms.text_contrast_medium]}>
- {formatCount(i18n, post.repostCount)}
+ {formatPostStatCount(i18n, post.repostCount)}
{' '}
- {formatCount(i18n, post.quoteCount)}
+ {formatPostStatCount(i18n, post.quoteCount)}
{' '}
- {formatCount(i18n, post.likeCount)}
+ {formatPostStatCount(i18n, post.likeCount)}
{' '}
diff --git a/src/screens/PostThread/components/ThreadItemTreePost.tsx b/src/screens/PostThread/components/ThreadItemTreePost.tsx
index b009695a98..5d31233585 100644
--- a/src/screens/PostThread/components/ThreadItemTreePost.tsx
+++ b/src/screens/PostThread/components/ThreadItemTreePost.tsx
@@ -368,6 +368,7 @@ const ThreadItemTreePostInner = memo(function ThreadItemTreePostInner({
)}