deer social fork for personal usage. but you might see a use idk. github mirror
4
fork

Configure Feed

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

removes follows you pill to instead use the follow button as mutual indicator

ayla 44190195 fcb46f75

+41 -137
-28
src/components/Pills.tsx
··· 1 1 import React from 'react' 2 2 import {View} from 'react-native' 3 3 import {BSKY_LABELER_DID, type ModerationCause} from '@atproto/api' 4 - import {Trans} from '@lingui/macro' 5 4 6 5 import {useModerationCauseDescription} from '#/lib/moderation/useModerationCauseDescription' 7 6 import {UserAvatar} from '#/view/com/util/UserAvatar' ··· 150 149 </> 151 150 ) 152 151 } 153 - 154 - export function FollowsYou({size = 'sm'}: CommonProps) { 155 - const t = useTheme() 156 - 157 - const variantStyles = React.useMemo(() => { 158 - switch (size) { 159 - case 'sm': 160 - case 'lg': 161 - default: 162 - return [ 163 - { 164 - paddingHorizontal: 6, 165 - paddingVertical: 3, 166 - borderRadius: 4, 167 - }, 168 - ] 169 - } 170 - }, [size]) 171 - 172 - return ( 173 - <View style={[variantStyles, a.justify_center, t.atoms.bg_contrast_25]}> 174 - <Text style={[a.text_xs, a.leading_tight]}> 175 - <Trans>Follows You</Trans> 176 - </Text> 177 - </View> 178 - ) 179 - }
+13 -7
src/components/ProfileCard.tsx
··· 507 507 } 508 508 } 509 509 510 - const unfollowLabel = _( 511 - msg({ 512 - message: 'Following', 513 - comment: 'User is following this account, click to unfollow', 514 - }), 515 - ) 510 + const unfollowLabel = profile.viewer?.followedBy 511 + ? _( 512 + msg({ 513 + message: 'Mutuals', 514 + comment: 'User is following this account, click to unfollow', 515 + }), 516 + ) 517 + : _( 518 + msg({ 519 + message: 'Following', 520 + comment: 'User is following this account, click to unfollow', 521 + }), 522 + ) 516 523 const followLabel = profile.viewer?.followedBy 517 524 ? _( 518 525 msg({ ··· 603 610 604 611 return ( 605 612 <Pills.Row style={[a.pt_xs]}> 606 - {followedBy && <Pills.FollowsYou />} 607 613 {modui.alerts.map(alert => ( 608 614 <Pills.Label key={getModerationCauseKey(alert)} cause={alert} /> 609 615 ))}
+12 -4
src/components/ProfileHoverCard/index.web.tsx
··· 492 492 variant="solid" 493 493 label={ 494 494 profileShadow.viewer?.following 495 - ? _(msg`Following`) 496 - : _(msg`Follow`) 495 + ? profileShadow.viewer?.followedBy 496 + ? _(msg`Mutuals`) 497 + : _(msg`Following`) 498 + : profileShadow.viewer?.followedBy 499 + ? _(msg`Follow back`) 500 + : _(msg`Follow`) 497 501 } 498 502 style={[a.rounded_full]} 499 503 onPress={profileShadow.viewer?.following ? unfollow : follow}> ··· 503 507 /> 504 508 <ButtonText> 505 509 {profileShadow.viewer?.following 506 - ? _(msg`Following`) 507 - : _(msg`Follow`)} 510 + ? profileShadow.viewer?.followedBy 511 + ? _(msg`Mutuals`) 512 + : _(msg`Following`) 513 + : profileShadow.viewer?.followedBy 514 + ? _(msg`Follow back`) 515 + : _(msg`Follow`)} 508 516 </ButtonText> 509 517 </Button> 510 518 ))}
+2
src/screens/PostThread/components/ThreadItemAnchorFollowButton.tsx
··· 130 130 ) : ( 131 131 <Trans>Follow</Trans> 132 132 ) 133 + ) : isFollowedBy ? ( 134 + <Trans>Mutuals</Trans> 133 135 ) : ( 134 136 <Trans>Following</Trans> 135 137 )}
-10
src/screens/Profile/Header/Handle.tsx
··· 1 1 import {View} from 'react-native' 2 2 import {type AppBskyActorDefs} from '@atproto/api' 3 - import {Trans} from '@lingui/macro' 4 3 import {useLingui} from '@lingui/react' 5 4 6 5 import {isInvalidHandle, sanitizeHandle} from '#/lib/strings/handles' ··· 24 23 const {_} = useLingui() 25 24 const invalidHandle = isInvalidHandle(profile.handle) 26 25 const pronouns = profile.pronouns 27 - const blockHide = profile.viewer?.blocking || profile.viewer?.blockedBy 28 26 const isBskySocialHandle = profile.handle.endsWith('.bsky.social') 29 27 const showProfileInHandle = useShowLinkInHandle() 30 28 const sanitized = sanitizeHandle( ··· 38 36 style={[a.flex_row, {gap: 6}, a.align_center, {maxWidth: '100%'}]} 39 37 pointerEvents={disableTaps ? 'none' : isIOS ? 'auto' : 'box-none'}> 40 38 <NewskieDialog profile={profile} disabled={disableTaps} /> 41 - 42 - {profile.viewer?.followedBy && !blockHide ? ( 43 - <View style={[t.atoms.bg_contrast_25, a.rounded_xs, a.px_sm, a.py_xs]}> 44 - <Text style={[t.atoms.text, a.text_sm]}> 45 - <Trans>Follows you</Trans> 46 - </Text> 47 - </View> 48 - ) : undefined} 49 39 50 40 <Text 51 41 emoji
+5 -1
src/screens/Profile/Header/ProfileHeaderStandard.tsx
··· 261 261 )} 262 262 <ButtonText> 263 263 {profile.viewer?.following ? ( 264 - <Trans>Following</Trans> 264 + profile.viewer?.followedBy ? ( 265 + <Trans>Mutuals</Trans> 266 + ) : ( 267 + <Trans>Following</Trans> 268 + ) 265 269 ) : profile.viewer?.followedBy ? ( 266 270 <Trans>Follow back</Trans> 267 271 ) : (
-85
src/view/com/profile/FollowButton.tsx
··· 1 - import {type StyleProp, type TextStyle, View} from 'react-native' 2 - import {msg} from '@lingui/macro' 3 - import {useLingui} from '@lingui/react' 4 - 5 - import {type Shadow} from '#/state/cache/types' 6 - import {useProfileFollowMutationQueue} from '#/state/queries/profile' 7 - import type * as bsky from '#/types/bsky' 8 - import {Button, type ButtonType} from '../util/forms/Button' 9 - import * as Toast from '../util/Toast' 10 - 11 - export function FollowButton({ 12 - unfollowedType = 'inverted', 13 - followedType = 'default', 14 - profile, 15 - labelStyle, 16 - logContext, 17 - onFollow, 18 - }: { 19 - unfollowedType?: ButtonType 20 - followedType?: ButtonType 21 - profile: Shadow<bsky.profile.AnyProfileView> 22 - labelStyle?: StyleProp<TextStyle> 23 - logContext: 'ProfileCard' | 'StarterPackProfilesList' 24 - onFollow?: () => void 25 - }) { 26 - const [queueFollow, queueUnfollow] = useProfileFollowMutationQueue( 27 - profile, 28 - logContext, 29 - ) 30 - const {_} = useLingui() 31 - 32 - const onPressFollow = async () => { 33 - try { 34 - await queueFollow() 35 - onFollow?.() 36 - } catch (e: any) { 37 - if (e?.name !== 'AbortError') { 38 - Toast.show(_(msg`An issue occurred, please try again.`), 'xmark') 39 - } 40 - } 41 - } 42 - 43 - const onPressUnfollow = async () => { 44 - try { 45 - await queueUnfollow() 46 - } catch (e: any) { 47 - if (e?.name !== 'AbortError') { 48 - Toast.show(_(msg`An issue occurred, please try again.`), 'xmark') 49 - } 50 - } 51 - } 52 - 53 - if (!profile.viewer) { 54 - return <View /> 55 - } 56 - 57 - if (profile.viewer.following) { 58 - return ( 59 - <Button 60 - type={followedType} 61 - labelStyle={labelStyle} 62 - onPress={onPressUnfollow} 63 - label={_(msg({message: 'Unfollow', context: 'action'}))} 64 - /> 65 - ) 66 - } else if (!profile.viewer.followedBy) { 67 - return ( 68 - <Button 69 - type={unfollowedType} 70 - labelStyle={labelStyle} 71 - onPress={onPressFollow} 72 - label={_(msg({message: 'Follow', context: 'action'}))} 73 - /> 74 - ) 75 - } else { 76 - return ( 77 - <Button 78 - type={unfollowedType} 79 - labelStyle={labelStyle} 80 - onPress={onPressFollow} 81 - label={_(msg({message: 'Follow back', context: 'action'}))} 82 - /> 83 - ) 84 - } 85 - }
+9 -2
src/view/com/profile/ProfileMenu.tsx
··· 77 77 const queryClient = useQueryClient() 78 78 const navigation = useNavigation<NavigationProp>() 79 79 const isSelf = currentAccount?.did === profile.did 80 + const isFollowedBy = profile.viewer?.followedBy 80 81 const isFollowing = profile.viewer?.following 81 82 const isBlocked = profile.viewer?.blocking || profile.viewer?.blockedBy 82 83 const isFollowingBlockedAccount = isFollowing && isBlocked ··· 315 316 testID="profileHeaderDropdownFollowBtn" 316 317 label={ 317 318 isFollowing 318 - ? _(msg`Unfollow account`) 319 + ? isFollowedBy 320 + ? _(msg`Divorce mutual`) 321 + : _(msg`Unfollow account`) 319 322 : _(msg`Follow account`) 320 323 } 321 324 onPress={ ··· 325 328 }> 326 329 <Menu.ItemText> 327 330 {isFollowing ? ( 328 - <Trans>Unfollow account</Trans> 331 + isFollowedBy ? ( 332 + <Trans>Divorce mutual</Trans> 333 + ) : ( 334 + <Trans>Unfollow account</Trans> 335 + ) 329 336 ) : ( 330 337 <Trans>Follow account</Trans> 331 338 )}