Bluesky app fork with some witchin' additions 馃挮
at main 228 lines 7.3 kB view raw
1import {View} from 'react-native' 2import {type ModerationCause} from '@atproto/api' 3import {msg} from '@lingui/core/macro' 4import {useLingui} from '@lingui/react' 5import {Trans} from '@lingui/react/macro' 6 7import {useGetTimeAgo} from '#/lib/hooks/useTimeAgo' 8import {useModerationCauseDescription} from '#/lib/moderation/useModerationCauseDescription' 9import {makeProfileLink} from '#/lib/routes/links' 10import {listUriToHref} from '#/lib/strings/url-helpers' 11import {useSession} from '#/state/session' 12import {atoms as a, useGutters, useTheme} from '#/alf' 13import * as Dialog from '#/components/Dialog' 14import {InlineLinkText} from '#/components/Link' 15import {type AppModerationCause} from '#/components/Pills' 16import {Text} from '#/components/Typography' 17import {IS_NATIVE} from '#/env' 18 19export {useDialogControl as useModerationDetailsDialogControl} from '#/components/Dialog' 20 21export interface ModerationDetailsDialogProps { 22 control: Dialog.DialogOuterProps['control'] 23 modcause?: ModerationCause | AppModerationCause 24} 25 26export function ModerationDetailsDialog(props: ModerationDetailsDialogProps) { 27 return ( 28 <Dialog.Outer 29 control={props.control} 30 nativeOptions={{preventExpansion: true}}> 31 <Dialog.Handle /> 32 <ModerationDetailsDialogInner {...props} /> 33 </Dialog.Outer> 34 ) 35} 36 37function ModerationDetailsDialogInner({ 38 modcause, 39 control, 40}: ModerationDetailsDialogProps & { 41 control: Dialog.DialogOuterProps['control'] 42}) { 43 const t = useTheme() 44 const xGutters = useGutters([0, 'base']) 45 const {_} = useLingui() 46 const desc = useModerationCauseDescription(modcause) 47 const {currentAccount} = useSession() 48 const timeDiff = useGetTimeAgo({future: true}) 49 50 let name 51 let description 52 if (!modcause) { 53 name = _(msg`Content Warning`) 54 description = _( 55 msg`Moderator has chosen to set a general warning on the content.`, 56 ) 57 } else if (modcause.type === 'blocking') { 58 if (modcause.source.type === 'list') { 59 const list = modcause.source.list 60 name = _(msg`User Blocked by List`) 61 description = ( 62 <Trans> 63 This user is included in the{' '} 64 <InlineLinkText 65 label={list.name} 66 to={listUriToHref(list.uri)} 67 style={[a.text_sm]}> 68 {list.name} 69 </InlineLinkText>{' '} 70 list which you have blocked. 71 </Trans> 72 ) 73 } else { 74 name = _(msg`User Blocked`) 75 description = _( 76 msg`You have blocked this user. You cannot view their content.`, 77 ) 78 } 79 } else if (modcause.type === 'blocked-by') { 80 name = _(msg`User Blocks You`) 81 description = _( 82 msg`This user has blocked you. You cannot view their content.`, 83 ) 84 } else if (modcause.type === 'block-other') { 85 name = _(msg`Content Not Available`) 86 description = _( 87 msg`This content is not available because one of the users involved has blocked the other.`, 88 ) 89 } else if (modcause.type === 'muted') { 90 if (modcause.source.type === 'list') { 91 const list = modcause.source.list 92 name = _(msg`Account Muted by List`) 93 description = ( 94 <Trans> 95 This user is included in the{' '} 96 <InlineLinkText 97 label={list.name} 98 to={listUriToHref(list.uri)} 99 style={[a.text_sm]}> 100 {list.name} 101 </InlineLinkText>{' '} 102 list which you have muted. 103 </Trans> 104 ) 105 } else { 106 name = _(msg`Account Muted`) 107 description = _(msg`You have muted this account.`) 108 } 109 } else if (modcause.type === 'mute-word') { 110 name = _(msg`Post Hidden by Muted Word`) 111 description = _(msg`You've chosen to hide a word or tag within this post.`) 112 } else if (modcause.type === 'hidden') { 113 name = _(msg`Post Hidden by You`) 114 description = _(msg`You have hidden this post.`) 115 } else if (modcause.type === 'reply-hidden') { 116 const isYou = currentAccount?.did === modcause.source.did 117 name = isYou 118 ? _(msg`Reply Hidden by You`) 119 : _(msg`Reply Hidden by Thread Author`) 120 description = isYou 121 ? _(msg`You hid this reply.`) 122 : _(msg`The author of this thread has hidden this reply.`) 123 } else if (modcause.type === 'label') { 124 name = desc.name 125 description = ( 126 <Text emoji style={[t.atoms.text, a.text_md, a.leading_snug]}> 127 {desc.description} 128 </Text> 129 ) 130 } else { 131 // should never happen 132 name = '' 133 description = '' 134 } 135 136 const sourceName = 137 desc.source || desc.sourceDisplayName || _(msg`an unknown labeler`) 138 139 return ( 140 <Dialog.ScrollableInner 141 label={_(msg`Moderation details`)} 142 contentContainerStyle={{ 143 paddingLeft: 0, 144 paddingRight: 0, 145 paddingBottom: 0, 146 }}> 147 <View style={[xGutters, a.pb_lg]}> 148 <Text emoji style={[t.atoms.text, a.text_2xl, a.font_bold, a.mb_sm]}> 149 {name} 150 </Text> 151 <Text style={[t.atoms.text, a.text_sm, a.leading_snug]}> 152 {description} 153 </Text> 154 </View> 155 156 {modcause?.type === 'label' && ( 157 <View 158 style={[ 159 xGutters, 160 a.py_md, 161 a.border_t, 162 !IS_NATIVE && t.atoms.bg_contrast_25, 163 t.atoms.border_contrast_low, 164 { 165 borderBottomLeftRadius: a.rounded_md.borderRadius, 166 borderBottomRightRadius: a.rounded_md.borderRadius, 167 }, 168 ]}> 169 {modcause.source.type === 'user' ? ( 170 <Text style={[t.atoms.text, a.text_md, a.leading_snug]}> 171 <Trans>This label was applied by the author.</Trans> 172 </Text> 173 ) : ( 174 <> 175 <View 176 style={[ 177 a.flex_row, 178 a.justify_between, 179 a.gap_xl, 180 {paddingBottom: 1}, 181 ]}> 182 <Text 183 style={[ 184 a.flex_1, 185 a.leading_snug, 186 t.atoms.text_contrast_medium, 187 ]} 188 numberOfLines={1}> 189 <Trans> 190 Source:{' '} 191 <InlineLinkText 192 label={sourceName} 193 to={makeProfileLink({ 194 did: modcause.label.src, 195 handle: '', 196 })} 197 onPress={() => control.close()}> 198 {sourceName} 199 </InlineLinkText> 200 </Trans> 201 </Text> 202 {modcause.label.exp && ( 203 <View> 204 <Text 205 style={[ 206 a.leading_snug, 207 a.text_sm, 208 a.italic, 209 t.atoms.text_contrast_medium, 210 ]}> 211 <Trans> 212 Expires in {timeDiff(Date.now(), modcause.label.exp)} 213 </Trans> 214 </Text> 215 </View> 216 )} 217 </View> 218 </> 219 )} 220 </View> 221 )} 222 223 {IS_NATIVE && <View style={{height: 40}} />} 224 225 <Dialog.Close /> 226 </Dialog.ScrollableInner> 227 ) 228}