Bluesky app fork with some witchin' additions 馃挮
0
fork

Configure Feed

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

at main 199 lines 6.9 kB view raw
1import {View} from 'react-native' 2import {type $Typed, ComAtprotoLabelDefs} from '@atproto/api' 3import {Trans, useLingui} from '@lingui/react/macro' 4import {type NativeStackScreenProps} from '@react-navigation/native-stack' 5import {useQueryClient} from '@tanstack/react-query' 6 7import {type CommonNavigatorParams} from '#/lib/routes/types' 8import {RQKEY_ROOT as POST_FEED_RQKEY_ROOT} from '#/state/queries/post-feed' 9import { 10 useProfileQuery, 11 useProfileUpdateMutation, 12} from '#/state/queries/profile' 13import {postThreadQueryKeyRoot} from '#/state/queries/usePostThread/types' 14import {useSession} from '#/state/session' 15import {UserAvatar} from '#/view/com/util/UserAvatar' 16import {atoms as a, platform, useTheme} from '#/alf' 17import * as Toggle from '#/components/forms/Toggle' 18import {Pet_Filled as PetIcon} from '#/components/icons/Pet' 19import * as Layout from '#/components/Layout' 20import {PetBadge} from '#/components/PetBadge' 21import {Text} from '#/components/Typography' 22import {useSimpleVerificationState} from '#/components/verification' 23import {VerificationCheck} from '#/components/verification/VerificationCheck' 24import {useAnalytics} from '#/analytics' 25import * as bsky from '#/types/bsky' 26 27type Props = NativeStackScreenProps<CommonNavigatorParams, 'PetLabelSettings'> 28export function PetLabelSettingsScreen({}: Props) { 29 const t = useTheme() 30 const ax = useAnalytics() 31 const {t: l} = useLingui() 32 const queryClient = useQueryClient() 33 const {currentAccount} = useSession() 34 const {data: profile} = useProfileQuery({did: currentAccount?.did}) 35 const updateProfile = useProfileUpdateMutation() 36 const verification = useSimpleVerificationState({profile}) 37 38 const isPetLabeled = 39 profile?.labels?.some(l => l.val === 'pet' && l.src === profile.did) ?? 40 false 41 const canToggle = profile && !updateProfile.isPending 42 43 const onToggle = () => { 44 if (!profile) { 45 return 46 } 47 let wasAdded = false 48 ax.metric('pet:label:toggle', {state: isPetLabeled ? 'remove' : 'add'}) 49 updateProfile.mutate( 50 { 51 profile, 52 updates: existing => { 53 const labels: $Typed<ComAtprotoLabelDefs.SelfLabels> = bsky.validate( 54 existing.labels, 55 ComAtprotoLabelDefs.validateSelfLabels, 56 ) 57 ? existing.labels 58 : { 59 $type: 'com.atproto.label.defs#selfLabels', 60 values: [], 61 } 62 63 const hasLabel = labels.values.some(l => l.val === 'pet') 64 if (hasLabel) { 65 wasAdded = false 66 labels.values = labels.values.filter(l => l.val !== 'pet') 67 } else { 68 wasAdded = true 69 labels.values.push({val: 'pet'}) 70 } 71 72 if (labels.values.length === 0) { 73 delete existing.labels 74 } else { 75 existing.labels = labels 76 } 77 78 return existing 79 }, 80 checkCommitted: res => { 81 const exists = !!res.data.labels?.some(l => l.val === 'pet') 82 return exists === wasAdded 83 }, 84 }, 85 { 86 onSuccess() { 87 queryClient.invalidateQueries({queryKey: [POST_FEED_RQKEY_ROOT]}) 88 queryClient.invalidateQueries({queryKey: [postThreadQueryKeyRoot]}) 89 }, 90 }, 91 ) 92 } 93 94 return ( 95 <Layout.Screen> 96 <Layout.Header.Outer> 97 <Layout.Header.BackButton /> 98 <Layout.Header.Content> 99 <Layout.Header.TitleText> 100 <Trans>Pet Label</Trans> 101 </Layout.Header.TitleText> 102 </Layout.Header.Content> 103 <Layout.Header.Slot /> 104 </Layout.Header.Outer> 105 <Layout.Content> 106 <View style={[a.p_xl, a.gap_xl]}> 107 {profile && ( 108 <View 109 style={[ 110 a.flex_row, 111 a.justify_center, 112 a.align_center, 113 a.gap_sm, 114 a.rounded_lg, 115 a.border, 116 t.atoms.bg_contrast_50, 117 t.atoms.border_contrast_low, 118 { 119 height: 160, 120 paddingRight: 20, 121 }, 122 ]}> 123 <UserAvatar size={42} avatar={profile.avatar} type="user" /> 124 <View> 125 <View style={[a.flex_row, a.align_baseline]}> 126 <View style={[a.flex_row, a.align_center, a.gap_xs]}> 127 <Text 128 emoji 129 style={[ 130 a.text_xl, 131 a.font_semi_bold, 132 a.flex_shrink, 133 a.leading_tight, 134 ]} 135 numberOfLines={1}> 136 {profile.displayName || profile.handle} 137 </Text> 138 {verification.isVerified && ( 139 <VerificationCheck 140 verifier={verification.role === 'verifier'} 141 size="sm" 142 /> 143 )} 144 <View style={{top: platform({ios: -1})}}> 145 <PetBadge profile={profile} alwaysShow width={17} /> 146 </View> 147 </View> 148 </View> 149 <Text 150 style={[ 151 a.text_md, 152 a.leading_snug, 153 t.atoms.text_contrast_medium, 154 ]} 155 numberOfLines={1}> 156 @{profile.handle} 157 </Text> 158 </View> 159 </View> 160 )} 161 <View style={[a.gap_sm]}> 162 <Text style={[a.text_2xl, a.font_bold]}> 163 <Trans>Add pet label to account</Trans> 164 </Text> 165 <Text style={[a.text_md, a.leading_snug]}> 166 <Trans> 167 This label lets the world know that the account holder is a pet. 168 If turned on, this label appears next to the account's name on 169 their profile and posts. It can be turned on or off at any time. 170 </Trans> 171 </Text> 172 </View> 173 <Toggle.Item 174 name="pet_label" 175 disabled={!canToggle || updateProfile.isPending} 176 value={isPetLabeled} 177 onChange={onToggle} 178 label={l`Show pet label`} 179 style={[ 180 a.w_full, 181 a.p_md, 182 a.rounded_lg, 183 a.border, 184 t.atoms.border_contrast_low, 185 t.atoms.bg_contrast_50, 186 ]}> 187 <View style={[a.pr_xs]}> 188 <PetIcon width={24} fill={t.atoms.text_contrast_medium.color} /> 189 </View> 190 <Toggle.LabelText style={[a.flex_1, a.text_md, a.font_medium]}> 191 <Trans>Show pet label</Trans> 192 </Toggle.LabelText> 193 <Toggle.Platform /> 194 </Toggle.Item> 195 </View> 196 </Layout.Content> 197 </Layout.Screen> 198 ) 199}