mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import React from 'react'
2import {StyleProp, View, ViewStyle} from 'react-native'
3import {
4 AppBskyFeedDefs,
5 AppBskyFeedThreadgate,
6 AppBskyGraphDefs,
7 AtUri,
8} from '@atproto/api'
9import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
10import {Trans} from '@lingui/macro'
11
12import {useColorSchemeStyle} from '#/lib/hooks/useColorSchemeStyle'
13import {usePalette} from '#/lib/hooks/usePalette'
14import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
15import {makeListLink, makeProfileLink} from '#/lib/routes/links'
16import {colors} from '#/lib/styles'
17import {TextLink} from '../util/Link'
18import {Text} from '../util/text/Text'
19
20export function WhoCanReply({
21 post,
22 style,
23}: {
24 post: AppBskyFeedDefs.PostView
25 style?: StyleProp<ViewStyle>
26}) {
27 const pal = usePalette('default')
28 const {isMobile} = useWebMediaQueries()
29 const containerStyles = useColorSchemeStyle(
30 {
31 borderColor: pal.colors.unreadNotifBorder,
32 backgroundColor: pal.colors.unreadNotifBg,
33 },
34 {
35 borderColor: pal.colors.unreadNotifBorder,
36 backgroundColor: pal.colors.unreadNotifBg,
37 },
38 )
39 const iconStyles = useColorSchemeStyle(
40 {
41 backgroundColor: colors.blue3,
42 },
43 {
44 backgroundColor: colors.blue3,
45 },
46 )
47 const textStyles = useColorSchemeStyle(
48 {color: colors.gray7},
49 {color: colors.blue1},
50 )
51 const record = React.useMemo(
52 () =>
53 post.threadgate &&
54 AppBskyFeedThreadgate.isRecord(post.threadgate.record) &&
55 AppBskyFeedThreadgate.validateRecord(post.threadgate.record).success
56 ? post.threadgate.record
57 : null,
58 [post],
59 )
60 if (record) {
61 return (
62 <View
63 style={[
64 {
65 flexDirection: 'row',
66 alignItems: 'center',
67 gap: isMobile ? 8 : 10,
68 paddingHorizontal: isMobile ? 16 : 18,
69 paddingVertical: 12,
70 borderWidth: 1,
71 borderLeftWidth: isMobile ? 0 : 1,
72 borderRightWidth: isMobile ? 0 : 1,
73 },
74 containerStyles,
75 style,
76 ]}>
77 <View
78 style={[
79 {
80 flexDirection: 'row',
81 alignItems: 'center',
82 justifyContent: 'center',
83 width: 32,
84 height: 32,
85 borderRadius: 19,
86 },
87 iconStyles,
88 ]}>
89 <FontAwesomeIcon
90 icon={['far', 'comments']}
91 size={16}
92 color={'#fff'}
93 />
94 </View>
95 <View style={{flex: 1}}>
96 <Text type="sm" style={[{flexWrap: 'wrap'}, textStyles]}>
97 {!record.allow?.length ? (
98 <Trans>Replies to this thread are disabled</Trans>
99 ) : (
100 <Trans>
101 Only{' '}
102 {record.allow.map((rule, i) => (
103 <>
104 <Rule
105 key={`rule-${i}`}
106 rule={rule}
107 post={post}
108 lists={post.threadgate!.lists}
109 />
110 <Separator
111 key={`sep-${i}`}
112 i={i}
113 length={record.allow!.length}
114 />
115 </>
116 ))}{' '}
117 can reply.
118 </Trans>
119 )}
120 </Text>
121 </View>
122 </View>
123 )
124 }
125 return null
126}
127
128function Rule({
129 rule,
130 post,
131 lists,
132}: {
133 rule: any
134 post: AppBskyFeedDefs.PostView
135 lists: AppBskyGraphDefs.ListViewBasic[] | undefined
136}) {
137 const pal = usePalette('default')
138 if (AppBskyFeedThreadgate.isMentionRule(rule)) {
139 return <Trans>mentioned users</Trans>
140 }
141 if (AppBskyFeedThreadgate.isFollowingRule(rule)) {
142 return (
143 <Trans>
144 users followed by{' '}
145 <TextLink
146 type="sm"
147 href={makeProfileLink(post.author)}
148 text={`@${post.author.handle}`}
149 style={pal.link}
150 />
151 </Trans>
152 )
153 }
154 if (AppBskyFeedThreadgate.isListRule(rule)) {
155 const list = lists?.find(l => l.uri === rule.list)
156 if (list) {
157 const listUrip = new AtUri(list.uri)
158 return (
159 <Trans>
160 <TextLink
161 type="sm"
162 href={makeListLink(listUrip.hostname, listUrip.rkey)}
163 text={list.name}
164 style={pal.link}
165 />{' '}
166 members
167 </Trans>
168 )
169 }
170 }
171}
172
173function Separator({i, length}: {i: number; length: number}) {
174 if (length < 2 || i === length - 1) {
175 return null
176 }
177 if (i === length - 2) {
178 return (
179 <>
180 {length > 2 ? ',' : ''} <Trans>and</Trans>{' '}
181 </>
182 )
183 }
184 return <>, </>
185}