Bluesky app fork with some witchin' additions 💫
at linkat-integration 230 lines 7.5 kB view raw
1import React from 'react' 2import {View} from 'react-native' 3import {AppBskyGraphDefs} from '@atproto/api' 4import {msg, Trans} from '@lingui/macro' 5import {useLingui} from '@lingui/react' 6import {useQueryClient} from '@tanstack/react-query' 7 8import {useGoBack} from '#/lib/hooks/useGoBack' 9import {sanitizeHandle} from '#/lib/strings/handles' 10import {logger} from '#/logger' 11import {RQKEY_ROOT as listQueryRoot} from '#/state/queries/list' 12import {useListBlockMutation, useListMuteMutation} from '#/state/queries/list' 13import { 14 type UsePreferencesQueryResponse, 15 useRemoveFeedMutation, 16} from '#/state/queries/preferences' 17import {useSession} from '#/state/session' 18import * as Toast from '#/view/com/util/Toast' 19import {CenteredView} from '#/view/com/util/Views' 20import {atoms as a, useBreakpoints, useTheme} from '#/alf' 21import {Button, ButtonIcon, ButtonText} from '#/components/Button' 22import {EyeSlash_Stroke2_Corner0_Rounded as EyeSlash} from '#/components/icons/EyeSlash' 23import {Loader} from '#/components/Loader' 24import {useHider} from '#/components/moderation/Hider' 25import {Text} from '#/components/Typography' 26 27export function ListHiddenScreen({ 28 list, 29 preferences, 30}: { 31 list: AppBskyGraphDefs.ListView 32 preferences: UsePreferencesQueryResponse 33}) { 34 const {_} = useLingui() 35 const t = useTheme() 36 const {currentAccount} = useSession() 37 const {gtMobile} = useBreakpoints() 38 const isOwner = currentAccount?.did === list.creator.did 39 const goBack = useGoBack() 40 const queryClient = useQueryClient() 41 42 const isModList = list.purpose === AppBskyGraphDefs.MODLIST 43 44 const [isProcessing, setIsProcessing] = React.useState(false) 45 const listBlockMutation = useListBlockMutation() 46 const listMuteMutation = useListMuteMutation() 47 const {mutateAsync: removeSavedFeed} = useRemoveFeedMutation() 48 49 const {setIsContentVisible} = useHider() 50 51 const savedFeedConfig = preferences.savedFeeds.find(f => f.value === list.uri) 52 53 const onUnsubscribe = async () => { 54 setIsProcessing(true) 55 if (list.viewer?.muted) { 56 try { 57 await listMuteMutation.mutateAsync({uri: list.uri, mute: false}) 58 } catch (e) { 59 setIsProcessing(false) 60 logger.error('Failed to unmute list', {message: e}) 61 Toast.show( 62 _( 63 msg`There was an issue. Please check your internet connection and try again.`, 64 ), 65 ) 66 return 67 } 68 } 69 if (list.viewer?.blocked) { 70 try { 71 await listBlockMutation.mutateAsync({uri: list.uri, block: false}) 72 } catch (e) { 73 setIsProcessing(false) 74 logger.error('Failed to unblock list', {message: e}) 75 Toast.show( 76 _( 77 msg`There was an issue. Please check your internet connection and try again.`, 78 ), 79 ) 80 return 81 } 82 } 83 queryClient.invalidateQueries({ 84 queryKey: [listQueryRoot], 85 }) 86 Toast.show(_(msg`Unsubscribed from list`)) 87 setIsProcessing(false) 88 } 89 90 const onRemoveList = async () => { 91 if (!savedFeedConfig) return 92 try { 93 await removeSavedFeed(savedFeedConfig) 94 Toast.show(_(msg`Removed from saved feeds`)) 95 } catch (e) { 96 logger.error('Failed to remove list from saved feeds', {message: e}) 97 Toast.show( 98 _( 99 msg`There was an issue. Please check your internet connection and try again.`, 100 ), 101 ) 102 } finally { 103 setIsProcessing(false) 104 } 105 } 106 107 return ( 108 <CenteredView 109 style={[ 110 a.flex_1, 111 a.align_center, 112 a.gap_5xl, 113 !gtMobile && a.justify_between, 114 t.atoms.border_contrast_low, 115 {paddingTop: 175, paddingBottom: 110}, 116 ]} 117 sideBorders={true}> 118 <View style={[a.w_full, a.align_center, a.gap_lg]}> 119 <EyeSlash 120 style={{color: t.atoms.text_contrast_medium.color}} 121 height={42} 122 width={42} 123 /> 124 <View style={[a.gap_sm, a.align_center]}> 125 <Text style={[a.font_semi_bold, a.text_3xl]}> 126 {list.creator.viewer?.blocking || list.creator.viewer?.blockedBy ? ( 127 <Trans>Creator has been blocked</Trans> 128 ) : ( 129 <Trans>List has been hidden</Trans> 130 )} 131 </Text> 132 <Text 133 style={[ 134 a.text_md, 135 a.text_center, 136 a.px_md, 137 t.atoms.text_contrast_high, 138 {lineHeight: 1.4}, 139 ]}> 140 {list.creator.viewer?.blocking || list.creator.viewer?.blockedBy ? ( 141 <Trans> 142 Either the creator of this list has blocked you or you have 143 blocked the creator. 144 </Trans> 145 ) : isOwner ? ( 146 <Trans> 147 This list created by you contains possible violations of 148 Bluesky's community guidelines in its name or description. 149 </Trans> 150 ) : ( 151 <Trans> 152 This list – created by{' '} 153 <Text style={[a.font_semi_bold]}> 154 {sanitizeHandle(list.creator.handle, '@')} 155 </Text>{' '} 156 – contains possible violations of Bluesky's community guidelines 157 in its name or description. 158 </Trans> 159 )} 160 </Text> 161 </View> 162 </View> 163 <View style={[a.gap_md, gtMobile ? {width: 350} : [a.w_full, a.px_lg]]}> 164 <View style={[a.gap_md]}> 165 {savedFeedConfig ? ( 166 <Button 167 variant="solid" 168 color="secondary" 169 size="large" 170 label={_(msg`Remove from saved feeds`)} 171 onPress={onRemoveList} 172 disabled={isProcessing}> 173 <ButtonText> 174 <Trans>Remove from saved feeds</Trans> 175 </ButtonText> 176 {isProcessing ? ( 177 <ButtonIcon icon={Loader} position="right" /> 178 ) : null} 179 </Button> 180 ) : null} 181 {isOwner ? ( 182 <Button 183 variant="solid" 184 color="secondary" 185 size="large" 186 label={_(msg`Show list anyway`)} 187 onPress={() => setIsContentVisible(true)} 188 disabled={isProcessing}> 189 <ButtonText> 190 <Trans>Show anyway</Trans> 191 </ButtonText> 192 </Button> 193 ) : list.viewer?.muted || list.viewer?.blocked ? ( 194 <Button 195 variant="solid" 196 color="secondary" 197 size="large" 198 label={_(msg`Unsubscribe from list`)} 199 onPress={() => { 200 if (isModList) { 201 onUnsubscribe() 202 } else { 203 onRemoveList() 204 } 205 }} 206 disabled={isProcessing}> 207 <ButtonText> 208 <Trans>Unsubscribe from list</Trans> 209 </ButtonText> 210 {isProcessing ? ( 211 <ButtonIcon icon={Loader} position="right" /> 212 ) : null} 213 </Button> 214 ) : null} 215 </View> 216 <Button 217 variant="solid" 218 color="primary" 219 label={_(msg`Return to previous page`)} 220 onPress={goBack} 221 size="large" 222 disabled={isProcessing}> 223 <ButtonText> 224 <Trans>Go Back</Trans> 225 </ButtonText> 226 </Button> 227 </View> 228 </CenteredView> 229 ) 230}