forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {StyleSheet, View} from 'react-native'
2import {AppBskyFeedDefs, type ModerationDecision} from '@atproto/api'
3import {msg, Trans} from '@lingui/macro'
4import {useLingui} from '@lingui/react'
5
6import {isReasonFeedSource, type ReasonFeedSource} from '#/lib/api/feed/types'
7import {createSanitizedDisplayName} from '#/lib/moderation/create-sanitized-display-name'
8import {makeProfileLink} from '#/lib/routes/links'
9import {getTerminology, TERMINOLOGY} from '#/lib/strings/terminology'
10import {useTerminologyPreference} from '#/state/preferences'
11import {useSession} from '#/state/session'
12import {atoms as a, useTheme} from '#/alf'
13import {Pin_Stroke2_Corner0_Rounded as PinIcon} from '#/components/icons/Pin'
14import {Repost_Stroke2_Corner3_Rounded as RepostIcon} from '#/components/icons/Repost'
15import {Link} from '#/components/Link'
16import {ProfileHoverCard} from '#/components/ProfileHoverCard'
17import {Text} from '#/components/Typography'
18import {FeedNameText} from '../util/FeedInfoText'
19
20export function PostFeedReason({
21 reason,
22 moderation,
23 onOpenReposter,
24}: {
25 reason:
26 | ReasonFeedSource
27 | AppBskyFeedDefs.ReasonRepost
28 | AppBskyFeedDefs.ReasonPin
29 | {[k: string]: unknown; $type: string}
30 moderation?: ModerationDecision
31 onOpenReposter?: () => void
32}) {
33 const t = useTheme()
34 const {_} = useLingui()
35 const terminologyPreference = useTerminologyPreference()
36
37 const {currentAccount} = useSession()
38
39 if (isReasonFeedSource(reason)) {
40 return (
41 <Link label={_(msg`Go to feed`)} to={reason.href}>
42 <Text
43 style={[
44 t.atoms.text_contrast_medium,
45 a.font_medium,
46 a.leading_snug,
47 a.leading_snug,
48 ]}
49 numberOfLines={1}>
50 <Trans context="from-feed">
51 From{' '}
52 <FeedNameText
53 uri={reason.uri}
54 href={reason.href}
55 style={[
56 t.atoms.text_contrast_medium,
57 a.font_medium,
58 a.leading_snug,
59 ]}
60 numberOfLines={1}
61 />
62 </Trans>
63 </Text>
64 </Link>
65 )
66 }
67
68 if (AppBskyFeedDefs.isReasonRepost(reason)) {
69 const isOwner = reason.by.did === currentAccount?.did
70 const reposter = createSanitizedDisplayName(
71 reason.by,
72 false,
73 moderation?.ui('displayName'),
74 )
75 return (
76 <Link
77 style={styles.includeReason}
78 to={makeProfileLink(reason.by)}
79 label={
80 isOwner
81 ? _(getTerminology(terminologyPreference, TERMINOLOGY.repost.byLine))
82 : `${_(getTerminology(terminologyPreference, TERMINOLOGY.repost.byLine))} ${reposter}`
83 }
84 onPress={onOpenReposter}>
85 <RepostIcon
86 style={[t.atoms.text_contrast_medium, {marginRight: 3}]}
87 width={13}
88 height={13}
89 />
90 <ProfileHoverCard did={reason.by.did}>
91 <Text
92 style={[
93 t.atoms.text_contrast_medium,
94 a.font_medium,
95 a.leading_snug,
96 ]}
97 numberOfLines={1}>
98 {isOwner ? (
99 <Trans>{_(getTerminology(terminologyPreference, TERMINOLOGY.repost.byLine))}</Trans>
100 ) : (
101 <Trans>{_(getTerminology(terminologyPreference, TERMINOLOGY.repost.byLine))} {reposter}</Trans>
102 )}
103 </Text>
104 </ProfileHoverCard>
105 </Link>
106 )
107 }
108
109 if (AppBskyFeedDefs.isReasonPin(reason)) {
110 return (
111 <View style={styles.includeReason}>
112 <PinIcon
113 style={[t.atoms.text_contrast_medium, {marginRight: 3}]}
114 width={13}
115 height={13}
116 />
117 <Text
118 style={[t.atoms.text_contrast_medium, a.font_medium, a.leading_snug]}
119 numberOfLines={1}>
120 <Trans>Pinned</Trans>
121 </Text>
122 </View>
123 )
124 }
125}
126
127const styles = StyleSheet.create({
128 includeReason: {
129 flexDirection: 'row',
130 alignItems: 'center',
131 marginBottom: 2,
132 marginLeft: -16,
133 },
134})