Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

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

feat: Follows you pill toggle

also some import fixes

xan.lol b39e0799 e93bc65e

+146 -33
+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/react/macro' 4 5 5 6 import {useModerationCauseDescription} from '#/lib/moderation/useModerationCauseDescription' 6 7 import {useEnableSquareButtons} from '#/state/preferences/enable-square-buttons' ··· 152 153 </> 153 154 ) 154 155 } 156 + 157 + export function FollowsYou({size = 'sm'}: CommonProps) { 158 + const t = useTheme() 159 + 160 + const variantStyles = React.useMemo(() => { 161 + switch (size) { 162 + case 'sm': 163 + case 'lg': 164 + default: 165 + return [ 166 + { 167 + paddingHorizontal: 6, 168 + paddingVertical: 3, 169 + borderRadius: 4, 170 + }, 171 + ] 172 + } 173 + }, [size]) 174 + 175 + return ( 176 + <View style={[variantStyles, a.justify_center, t.atoms.bg_contrast_50]}> 177 + <Text style={[a.text_xs, a.leading_tight]}> 178 + <Trans>Follows You</Trans> 179 + </Text> 180 + </View> 181 + ) 182 + }
+4 -1
src/components/ProfileCard.tsx
··· 20 20 import {sanitizeDisplayName} from '#/lib/strings/display-names' 21 21 import {sanitizeHandle} from '#/lib/strings/handles' 22 22 import {useProfileShadow} from '#/state/cache/profile-shadow' 23 + import {useShowFollowsYouBadge} from '#/state/preferences/show-follows-you-badge' 23 24 import {useProfileFollowMutationQueue} from '#/state/queries/profile' 24 25 import {useSession} from '#/state/session' 25 26 import * as Toast from '#/view/com/util/Toast' ··· 647 648 const moderation = moderateProfile(profile, moderationOpts) 648 649 const modui = moderation.ui('profileList') 649 650 const followedBy = profile.viewer?.followedBy 651 + const showFollowsYouBadge = useShowFollowsYouBadge() 650 652 651 - if (!followedBy && !modui.inform && !modui.alert) { 653 + if (!(followedBy && showFollowsYouBadge) && !modui.inform && !modui.alert) { 652 654 return null 653 655 } 654 656 655 657 return ( 656 658 <Pills.Row style={[a.pt_xs]}> 659 + {followedBy && showFollowsYouBadge && <Pills.FollowsYou />} 657 660 {modui.alerts.map(alert => ( 658 661 <Pills.Label key={getModerationCauseKey(alert)} cause={alert} /> 659 662 ))}
+11
src/screens/Profile/Header/Handle.tsx
··· 2 2 import {type AppBskyActorDefs} from '@atproto/api' 3 3 import {msg} from '@lingui/core/macro' 4 4 import {useLingui} from '@lingui/react' 5 + import {Trans} from '@lingui/react/macro' 5 6 6 7 import {isInvalidHandle, sanitizeHandle} from '#/lib/strings/handles' 7 8 import {sanitizePronouns} from '#/lib/strings/pronouns' 8 9 import {type Shadow} from '#/state/cache/types' 10 + import {useShowFollowsYouBadge} from '#/state/preferences/show-follows-you-badge' 9 11 import {useShowLinkInHandle} from '#/state/preferences/show-link-in-handle.tsx' 10 12 import {atoms as a, useTheme, web} from '#/alf' 11 13 import {InlineLinkText} from '#/components/Link.tsx' ··· 24 26 const {_} = useLingui() 25 27 const invalidHandle = isInvalidHandle(profile.handle) 26 28 const pronouns = profile.pronouns 29 + const blockHide = profile.viewer?.blocking || profile.viewer?.blockedBy 27 30 const isBskySocialHandle = profile.handle.endsWith('.bsky.social') 31 + const showFollowsYouBadge = useShowFollowsYouBadge() 28 32 const showProfileInHandle = useShowLinkInHandle() 29 33 const sanitized = sanitizeHandle( 30 34 profile.handle, ··· 37 41 style={[a.flex_row, a.gap_sm, a.align_center, {maxWidth: '100%'}]} 38 42 pointerEvents={disableTaps ? 'none' : IS_IOS ? 'auto' : 'box-none'}> 39 43 <NewskieDialog profile={profile} disabled={disableTaps} /> 44 + {showFollowsYouBadge && profile.viewer?.followedBy && !blockHide ? ( 45 + <View style={[t.atoms.bg_contrast_50, a.rounded_xs, a.px_sm, a.py_xs]}> 46 + <Text style={[t.atoms.text, a.text_sm]}> 47 + <Trans>Follows you</Trans> 48 + </Text> 49 + </View> 50 + ) : undefined} 40 51 <View style={[a.flex_row, a.flex_wrap, {gap: 6}]}> 41 52 <Text 42 53 emoji
+21 -2
src/screens/Settings/RunesSettings.tsx
··· 134 134 useSetRepostCarouselEnabled, 135 135 } from '#/state/preferences/repost-carousel-enabled' 136 136 import { 137 + useSetShowFollowsYouBadge, 138 + useShowFollowsYouBadge, 139 + } from '#/state/preferences/show-follows-you-badge' 140 + import { 137 141 useSetShowLinkInHandle, 138 142 useShowLinkInHandle, 139 143 } from '#/state/preferences/show-link-in-handle.tsx' ··· 802 806 const repostCarouselEnabled = useRepostCarouselEnabled() 803 807 const setRepostCarouselEnabled = useSetRepostCarouselEnabled() 804 808 809 + const showFollowsYouBadge = useShowFollowsYouBadge() 810 + const setShowFollowsYouBadge = useSetShowFollowsYouBadge() 811 + 805 812 const showLinkInHandle = useShowLinkInHandle() 806 813 const setShowLinkInHandle = useSetShowLinkInHandle() 807 814 ··· 1425 1432 </Toggle.Item> 1426 1433 1427 1434 <Toggle.Item 1435 + name="show_follows_you_badge" 1436 + label={_(msg`Show "Follows you" badge`)} 1437 + value={showFollowsYouBadge} 1438 + onChange={value => setShowFollowsYouBadge(value)} 1439 + style={[a.w_full]}> 1440 + <Toggle.LabelText style={[a.flex_1]}> 1441 + <Trans>Show "Follows you" badge</Trans> 1442 + </Toggle.LabelText> 1443 + <Toggle.Platform /> 1444 + </Toggle.Item> 1445 + 1446 + <Toggle.Item 1428 1447 name="disable_posts_metrics" 1429 - label={_(msg`Disable posts metrics`)} 1448 + label={_(msg`Disable post counts metrics`)} 1430 1449 value={disablePostsMetrics} 1431 1450 onChange={value => setDisablePostsMetrics(value)} 1432 1451 style={[a.w_full]}> 1433 1452 <Toggle.LabelText style={[a.flex_1]}> 1434 - <Trans>Disable posts metrics</Trans> 1453 + <Trans>Disable post counts metrics</Trans> 1435 1454 </Toggle.LabelText> 1436 1455 <Toggle.Platform /> 1437 1456 </Toggle.Item>
+1 -5
src/screens/Signup/StepInfo/index.tsx
··· 33 33 import * as Toast from '#/components/Toast' 34 34 import {Text} from '#/components/Typography' 35 35 import { 36 - isUnderAge, 37 36 MIN_ACCESS_AGE, 38 37 useAgeAssuranceRegionConfigWithFallback, 39 38 } from '#/ageAssurance/util' 40 39 import {useAnalytics} from '#/analytics' 41 40 import {IS_NATIVE, IS_WEB} from '#/env' 42 - import { 43 - useDeviceGeolocationApi, 44 - useIsDeviceGeolocationGranted, 45 - } from '#/geolocation' 41 + import {useDeviceGeolocationApi} from '#/geolocation' 46 42 import {BackNextButtons} from '../BackNextButtons' 47 43 48 44 function sanitizeDate(date: Date): Date {
+2
src/state/persisted/schema.ts
··· 161 161 disableFollowingMetrics: z.boolean().optional(), 162 162 disableFollowedByMetrics: z.boolean().optional(), 163 163 disablePostsMetrics: z.boolean().optional(), 164 + showFollowsYouBadge: z.boolean().optional(), 164 165 hideSimilarAccountsRecomm: z.boolean().optional(), 165 166 discoverContextEnabled: z.boolean().optional(), 166 167 enableSquareAvatars: z.boolean().optional(), ··· 278 279 disableFollowingMetrics: false, 279 280 disableFollowedByMetrics: false, 280 281 disablePostsMetrics: false, 282 + showFollowsYouBadge: false, 281 283 hideSimilarAccountsRecomm: true, 282 284 discoverContextEnabled: false, 283 285 enableSquareAvatars: true,
+26 -23
src/state/preferences/index.tsx
··· 41 41 import {Provider as PdsLabelProvider} from './pds-label' 42 42 import {Provider as PostNameReplacementProvider} from './post-name-replacement.tsx' 43 43 import {Provider as RepostCarouselProvider} from './repost-carousel-enabled' 44 + import {Provider as ShowFollowsYouBadgeProvider} from './show-follows-you-badge' 44 45 import {Provider as ShowLinkInHandleProvider} from './show-link-in-handle' 45 46 import {Provider as SubtitlesProvider} from './subtitles' 46 47 import {Provider as TranslationServicePreferenceProvider} from './translation-service-preference' ··· 127 128 <DisableFollowingMetricsProvider> 128 129 <DisableFollowedByMetricsProvider> 129 130 <DisablePostsMetricsProvider> 130 - <HideSimilarAccountsRecommProvider> 131 - <HideUnreplyablePostsProvider> 132 - <EnableSquareAvatarsProvider> 133 - <EnableSquareButtonsProvider> 134 - <PostNameReplacementProvider> 135 - <DisableVerifyEmailReminderProvider> 136 - <TranslationServicePreferenceProvider> 137 - <OpenRouterProvider> 138 - <DisableComposerPromptProvider> 139 - <DiscoverContextEnabledProvider> 140 - { 141 - children 142 - } 143 - </DiscoverContextEnabledProvider> 144 - </DisableComposerPromptProvider> 145 - </OpenRouterProvider> 146 - </TranslationServicePreferenceProvider> 147 - </DisableVerifyEmailReminderProvider> 148 - </PostNameReplacementProvider> 149 - </EnableSquareButtonsProvider> 150 - </EnableSquareAvatarsProvider> 151 - </HideUnreplyablePostsProvider> 152 - </HideSimilarAccountsRecommProvider> 131 + <ShowFollowsYouBadgeProvider> 132 + <HideSimilarAccountsRecommProvider> 133 + <HideUnreplyablePostsProvider> 134 + <EnableSquareAvatarsProvider> 135 + <EnableSquareButtonsProvider> 136 + <PostNameReplacementProvider> 137 + <DisableVerifyEmailReminderProvider> 138 + <TranslationServicePreferenceProvider> 139 + <OpenRouterProvider> 140 + <DisableComposerPromptProvider> 141 + <DiscoverContextEnabledProvider> 142 + { 143 + children 144 + } 145 + </DiscoverContextEnabledProvider> 146 + </DisableComposerPromptProvider> 147 + </OpenRouterProvider> 148 + </TranslationServicePreferenceProvider> 149 + </DisableVerifyEmailReminderProvider> 150 + </PostNameReplacementProvider> 151 + </EnableSquareButtonsProvider> 152 + </EnableSquareAvatarsProvider> 153 + </HideUnreplyablePostsProvider> 154 + </HideSimilarAccountsRecommProvider> 155 + </ShowFollowsYouBadgeProvider> 153 156 </DisablePostsMetricsProvider> 154 157 </DisableFollowedByMetricsProvider> 155 158 </DisableFollowingMetricsProvider>
+50
src/state/preferences/show-follows-you-badge.tsx
··· 1 + import React from 'react' 2 + 3 + import * as persisted from '#/state/persisted' 4 + 5 + type StateContext = persisted.Schema['showFollowsYouBadge'] 6 + type SetContext = (v: persisted.Schema['showFollowsYouBadge']) => void 7 + 8 + const stateContext = React.createContext<StateContext>( 9 + persisted.defaults.showFollowsYouBadge, 10 + ) 11 + const setContext = React.createContext<SetContext>( 12 + (_: persisted.Schema['showFollowsYouBadge']) => {}, 13 + ) 14 + 15 + export function Provider({children}: React.PropsWithChildren<{}>) { 16 + const [state, setState] = React.useState(persisted.get('showFollowsYouBadge')) 17 + 18 + const setStateWrapped = React.useCallback( 19 + (showFollowsYouBadge: persisted.Schema['showFollowsYouBadge']) => { 20 + setState(showFollowsYouBadge) 21 + persisted.write('showFollowsYouBadge', showFollowsYouBadge) 22 + }, 23 + [setState], 24 + ) 25 + 26 + React.useEffect(() => { 27 + return persisted.onUpdate( 28 + 'showFollowsYouBadge', 29 + nextShowFollowsYouBadge => { 30 + setState(nextShowFollowsYouBadge) 31 + }, 32 + ) 33 + }, [setStateWrapped]) 34 + 35 + return ( 36 + <stateContext.Provider value={state}> 37 + <setContext.Provider value={setStateWrapped}> 38 + {children} 39 + </setContext.Provider> 40 + </stateContext.Provider> 41 + ) 42 + } 43 + 44 + export function useShowFollowsYouBadge() { 45 + return React.useContext(stateContext) 46 + } 47 + 48 + export function useSetShowFollowsYouBadge() { 49 + return React.useContext(setContext) 50 + }
+2 -1
src/view/com/posts/PostFeedItemCarousel.tsx
··· 1 1 import React from 'react' 2 2 import {Dimensions, ScrollView, View} from 'react-native' 3 - import {msg, Plural} from '@lingui/macro' 3 + import {msg} from '@lingui/core/macro' 4 4 import {useLingui} from '@lingui/react' 5 + import {Plural} from '@lingui/react/macro' 5 6 6 7 import {useEnableSquareButtons} from '#/state/preferences/enable-square-buttons' 7 8 import {type FeedPostSlice} from '#/state/queries/post-feed'
+1 -1
src/view/screens/PostThread.tsx
··· 1 1 import {useCallback} from 'react' 2 - import {msg} from '@lingui/macro' 2 + import {msg} from '@lingui/core/macro' 3 3 import {useLingui} from '@lingui/react' 4 4 import {useFocusEffect} from '@react-navigation/native' 5 5