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