Bluesky app fork with some witchin' additions 馃挮 witchsky.app
bluesky fork client
119
fork

Configure Feed

Select the types of activity you want to include in your feed.

at a876aae44ea07494ebea9727350aa060b81f317b 184 lines 5.7 kB view raw
1import {useMemo} from 'react' 2import { 3 BSKY_LABELER_DID, 4 type ModerationCause, 5 type ModerationCauseSource, 6} from '@atproto/api' 7import {msg} from '@lingui/core/macro' 8import {useLingui} from '@lingui/react' 9 10import {sanitizeHandle} from '#/lib/strings/handles' 11import {useLabelDefinitions} from '#/state/preferences' 12import {useSession} from '#/state/session' 13import {CircleBanSign_Stroke2_Corner0_Rounded as CircleBanSign} from '#/components/icons/CircleBanSign' 14import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo' 15import {type Props as SVGIconProps} from '#/components/icons/common' 16import {EyeSlash_Stroke2_Corner0_Rounded as EyeSlash} from '#/components/icons/EyeSlash' 17import {Warning_Stroke2_Corner0_Rounded as Warning} from '#/components/icons/Warning' 18import {type AppModerationCause} from '#/components/Pills' 19import {useGlobalLabelStrings} from './useGlobalLabelStrings' 20import {getDefinition, getLabelStrings} from './useLabelInfo' 21 22export interface ModerationCauseDescription { 23 icon: React.ComponentType<SVGIconProps> 24 name: string 25 description: string 26 source?: string 27 sourceDisplayName?: string 28 sourceType?: ModerationCauseSource['type'] 29 sourceAvi?: string 30 sourceDid?: string 31 isSubjectAccount?: boolean 32} 33 34export function useModerationCauseDescription( 35 cause: ModerationCause | AppModerationCause | undefined, 36): ModerationCauseDescription { 37 const {currentAccount} = useSession() 38 const {_, i18n} = useLingui() 39 const {labelDefs, labelers} = useLabelDefinitions() 40 const globalLabelStrings = useGlobalLabelStrings() 41 42 return useMemo(() => { 43 if (!cause) { 44 return { 45 icon: Warning, 46 name: _(msg`Content Warning`), 47 description: _( 48 msg`Moderator has chosen to set a general warning on the content.`, 49 ), 50 } 51 } 52 if (cause.type === 'blocking') { 53 if (cause.source.type === 'list') { 54 return { 55 icon: CircleBanSign, 56 name: _(msg`User Blocked by "${cause.source.list.name}"`), 57 description: _( 58 msg`You have blocked this user. You cannot view their content.`, 59 ), 60 } 61 } else { 62 return { 63 icon: CircleBanSign, 64 name: _(msg`User Blocked`), 65 description: _( 66 msg`You have blocked this user. You cannot view their content.`, 67 ), 68 } 69 } 70 } 71 if (cause.type === 'blocked-by') { 72 return { 73 icon: CircleBanSign, 74 name: _(msg`User Blocking You`), 75 description: _( 76 msg`This user has blocked you. You cannot view their content.`, 77 ), 78 } 79 } 80 if (cause.type === 'block-other') { 81 return { 82 icon: CircleBanSign, 83 name: _(msg`Content Not Available`), 84 description: _( 85 msg`This content is not available because one of the users involved has blocked the other.`, 86 ), 87 } 88 } 89 if (cause.type === 'muted') { 90 if (cause.source.type === 'list') { 91 return { 92 icon: EyeSlash, 93 name: _(msg`Muted by "${cause.source.list.name}"`), 94 description: _(msg`You have muted this user`), 95 } 96 } else { 97 return { 98 icon: EyeSlash, 99 name: _(msg`Account Muted`), 100 description: _(msg`You have muted this account.`), 101 } 102 } 103 } 104 if (cause.type === 'mute-word') { 105 return { 106 icon: EyeSlash, 107 name: _(msg`Post Hidden by Muted Word`), 108 description: _( 109 msg`You've chosen to hide a word or tag within this post.`, 110 ), 111 } 112 } 113 if (cause.type === 'hidden') { 114 return { 115 icon: EyeSlash, 116 name: _(msg`Post Hidden by You`), 117 description: _(msg`You have hidden this post`), 118 } 119 } 120 if (cause.type === 'reply-hidden') { 121 const isMe = currentAccount?.did === cause.source.did 122 return { 123 icon: EyeSlash, 124 name: isMe 125 ? _(msg`Reply Hidden by You`) 126 : _(msg`Reply Hidden by Thread Author`), 127 description: isMe 128 ? _(msg`You hid this reply.`) 129 : _(msg`The author of this thread has hidden this reply.`), 130 } 131 } 132 if (cause.type === 'label') { 133 const def = cause.labelDef || getDefinition(labelDefs, cause.label) 134 const strings = getLabelStrings(i18n.locale, globalLabelStrings, def) 135 const labeler = labelers.find(l => l.creator.did === cause.label.src) 136 let source = labeler 137 ? sanitizeHandle(labeler.creator.handle, '@') 138 : undefined 139 let sourceDisplayName = labeler?.creator.displayName 140 if (!source) { 141 if (cause.label.src === BSKY_LABELER_DID) { 142 source = 'moderation.bsky.app' 143 sourceDisplayName = 'Bluesky Moderation Service' 144 } else { 145 source = _(msg`an unknown labeler`) 146 } 147 } 148 if (def.identifier === 'porn' || def.identifier === 'sexual') { 149 strings.name = _(msg`Adult Content`) 150 } 151 152 return { 153 icon: 154 def.identifier === '!no-unauthenticated' 155 ? EyeSlash 156 : def.severity === 'alert' 157 ? Warning 158 : CircleInfo, 159 name: strings.name, 160 description: strings.description, 161 source, 162 sourceDisplayName, 163 sourceType: cause.source.type, 164 sourceAvi: labeler?.creator.avatar, 165 sourceDid: cause.label.src, 166 isSubjectAccount: cause.label.uri.startsWith('did:'), 167 } 168 } 169 // should never happen 170 return { 171 icon: CircleInfo, 172 name: '', 173 description: ``, 174 } 175 }, [ 176 labelDefs, 177 labelers, 178 globalLabelStrings, 179 cause, 180 _, 181 i18n.locale, 182 currentAccount?.did, 183 ]) 184}