Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

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

feat: toggle to hide follow button on posts and scrolled profile header

+149 -56
+5 -1
src/screens/PostThread/components/ThreadItemAnchor.tsx
··· 27 27 import {useDisableRepostsMetrics} from '#/state/preferences/disable-reposts-metrics' 28 28 import {useDisableSavesMetrics} from '#/state/preferences/disable-saves-metrics' 29 29 import {useEnableSquareButtons} from '#/state/preferences/enable-square-buttons' 30 + import {useHideScaryFollowButtons} from '#/state/preferences/hide-scary-follow-buttons' 30 31 import {useShowViaClient} from '#/state/preferences/show-via-client' 31 32 import {type ThreadItem} from '#/state/queries/usePostThread/types' 32 33 import {useSession} from '#/state/session' ··· 245 246 const onlyFollowersCanReply = !!threadgateRecord?.allow?.find( 246 247 rule => rule.$type === 'app.bsky.feed.threadgate#followerRule', 247 248 ) 249 + const hideScaryFollowButtons = useHideScaryFollowButtons() 248 250 const showFollowButton = 249 - currentAccount?.did !== post.author.did && !onlyFollowersCanReply 251 + currentAccount?.did !== post.author.did && 252 + !onlyFollowersCanReply && 253 + !hideScaryFollowButtons 250 254 251 255 const viaRepost = useMemo(() => { 252 256 const reason = postSource?.post.reason
+31 -28
src/screens/Profile/Header/ProfileHeaderStandard.tsx
··· 22 22 import {logger} from '#/logger' 23 23 import {type Shadow, useProfileShadow} from '#/state/cache/profile-shadow' 24 24 import {useDisableFollowedByMetrics} from '#/state/preferences/disable-followed-by-metrics' 25 + import {useHideScaryFollowButtons} from '#/state/preferences/hide-scary-follow-buttons' 25 26 import { 26 27 useProfileBlockMutationQueue, 27 28 useProfileFollowMutationQueue, ··· 327 328 const [, queueUnblock] = useProfileBlockMutationQueue(profile) 328 329 const editProfileControl = useDialogControl() 329 330 const unblockPromptControl = Prompt.usePromptControl() 331 + const hideScaryFollowButtons = useHideScaryFollowButtons() 330 332 331 333 const isMe = currentAccount?.did === profile.did 332 334 ··· 458 460 </> 459 461 )} 460 462 461 - {(!minimal || !profile.viewer?.following) && ( 462 - <Button 463 - testID={profile.viewer?.following ? 'unfollowBtn' : 'followBtn'} 464 - size="small" 465 - color={profile.viewer?.following ? 'secondary' : 'primary'} 466 - label={ 467 - profile.viewer?.following 468 - ? _(msg`Unfollow ${profile.handle}`) 469 - : _(msg`Follow ${profile.handle}`) 470 - } 471 - onPress={ 472 - profile.viewer?.following ? onPressUnfollow : onPressFollow 473 - }> 474 - {!profile.viewer?.following && <ButtonIcon icon={Plus} />} 475 - <ButtonText> 476 - {profile.viewer?.following ? ( 477 - profile.viewer?.followedBy ? ( 478 - <Trans>Mutuals</Trans> 463 + {(!minimal || !profile.viewer?.following) && 464 + !(minimal && hideScaryFollowButtons) && ( 465 + <Button 466 + testID={profile.viewer?.following ? 'unfollowBtn' : 'followBtn'} 467 + size="small" 468 + color={profile.viewer?.following ? 'secondary' : 'primary'} 469 + label={ 470 + profile.viewer?.following 471 + ? _(msg`Unfollow ${profile.handle}`) 472 + : _(msg`Follow ${profile.handle}`) 473 + } 474 + onPress={ 475 + profile.viewer?.following ? onPressUnfollow : onPressFollow 476 + }> 477 + {!profile.viewer?.following && <ButtonIcon icon={Plus} />} 478 + <ButtonText> 479 + {profile.viewer?.following ? ( 480 + profile.viewer?.followedBy ? ( 481 + <Trans>Mutuals</Trans> 482 + ) : ( 483 + <Trans>Following</Trans> 484 + ) 485 + ) : profile.viewer?.followedBy ? ( 486 + <Trans>Follow back</Trans> 479 487 ) : ( 480 - <Trans>Following</Trans> 481 - ) 482 - ) : profile.viewer?.followedBy ? ( 483 - <Trans>Follow back</Trans> 484 - ) : ( 485 - <Trans>Follow</Trans> 486 - )} 487 - </ButtonText> 488 - </Button> 489 - )} 488 + <Trans>Follow</Trans> 489 + )} 490 + </ButtonText> 491 + </Button> 492 + )} 490 493 </> 491 494 ) : null} 492 495 <ProfileMenu profile={profile} />
+23
src/screens/Settings/RunesSettings/UsabilitySettings.tsx
··· 18 18 useSetHideFeedsPromoTab, 19 19 } from '#/state/preferences/hide-feeds-promo-tab' 20 20 import { 21 + useHideScaryFollowButtons, 22 + useSetHideScaryFollowButtons, 23 + } from '#/state/preferences/hide-scary-follow-buttons' 24 + import { 21 25 useHideSimilarAccountsRecomm, 22 26 useSetHideSimilarAccountsRecomm, 23 27 } from '#/state/preferences/hide-similar-accounts-recommendations' ··· 40 44 import {EyeSlash_Stroke2_Corner0_Rounded as EyeSlashIcon} from '#/components/icons/EyeSlash' 41 45 import {PencilLine_Stroke2_Corner2_Rounded as PencilIcon} from '#/components/icons/Pencil' 42 46 import {PersonGroup_Stroke2_Corner2_Rounded as PersonGroupIcon} from '#/components/icons/Person' 47 + import {PlusLarge_Stroke2_Corner0_Rounded as PlusIcon} from '#/components/icons/Plus' 43 48 import {Reply as ReplyIcon} from '#/components/icons/Reply' 44 49 import {RunesScreenLayout} from './components/RunesScreenLayout' 45 50 ··· 60 65 61 66 const hideUnreplyablePosts = useHideUnreplyablePosts() 62 67 const setHideUnreplyablePosts = useSetHideUnreplyablePosts() 68 + 69 + const hideScaryFollowButtons = useHideScaryFollowButtons() 70 + const setHideScaryFollowButtons = useSetHideScaryFollowButtons() 63 71 64 72 const disableComposerPrompt = useDisableComposerPrompt() 65 73 const setDisableComposerPrompt = useSetDisableComposerPrompt() ··· 146 154 <SettingsList.ItemIcon icon={ArrowTopIcon} /> 147 155 <SettingsList.ItemText> 148 156 <Trans>Disable top-of-feed button</Trans> 157 + </SettingsList.ItemText> 158 + <Toggle.Platform /> 159 + </SettingsList.Item> 160 + </Toggle.Item> 161 + <Toggle.Item 162 + name="hide_scary_follow_buttons" 163 + label={l`Hide follow button on posts and scrolled profile header`} 164 + value={hideScaryFollowButtons} 165 + onChange={value => setHideScaryFollowButtons(value)}> 166 + <SettingsList.Item> 167 + <SettingsList.ItemIcon icon={PlusIcon} /> 168 + <SettingsList.ItemText> 169 + <Trans> 170 + Hide follow button on posts and scrolled profile header 171 + </Trans> 149 172 </SettingsList.ItemText> 150 173 <Toggle.Platform /> 151 174 </SettingsList.Item>
+2
src/state/persisted/schema.ts
··· 187 187 disablePostsMetrics: z.boolean().optional(), 188 188 showFollowsYouBadge: z.boolean().optional(), 189 189 hideSimilarAccountsRecomm: z.boolean().optional(), 190 + hideScaryFollowButtons: z.boolean().optional(), 190 191 discoverContextEnabled: z.boolean().optional(), 191 192 enableSquareAvatars: z.boolean().optional(), 192 193 enableSquareButtons: z.boolean().optional(), ··· 316 317 disablePostsMetrics: false, 317 318 showFollowsYouBadge: false, 318 319 hideSimilarAccountsRecomm: true, 320 + hideScaryFollowButtons: false, 319 321 discoverContextEnabled: false, 320 322 enableSquareAvatars: true, 321 323 enableSquareButtons: true,
+54
src/state/preferences/hide-scary-follow-buttons.tsx
··· 1 + import { 2 + createContext, 3 + type PropsWithChildren, 4 + useCallback, 5 + useContext, 6 + useEffect, 7 + useState, 8 + } from 'react' 9 + 10 + import * as persisted from '#/state/persisted' 11 + 12 + type StateContext = persisted.Schema['hideScaryFollowButtons'] 13 + type SetContext = (v: persisted.Schema['hideScaryFollowButtons']) => void 14 + 15 + const stateContext = createContext<StateContext>( 16 + persisted.defaults.hideScaryFollowButtons, 17 + ) 18 + const setContext = createContext<SetContext>( 19 + (_: persisted.Schema['hideScaryFollowButtons']) => {}, 20 + ) 21 + 22 + export function Provider({children}: PropsWithChildren<{}>) { 23 + const [state, setState] = useState(persisted.get('hideScaryFollowButtons')) 24 + 25 + const setStateWrapped = useCallback( 26 + (hideScaryFollowButtons: persisted.Schema['hideScaryFollowButtons']) => { 27 + setState(hideScaryFollowButtons) 28 + persisted.write('hideScaryFollowButtons', hideScaryFollowButtons) 29 + }, 30 + [setState], 31 + ) 32 + 33 + useEffect(() => { 34 + return persisted.onUpdate('hideScaryFollowButtons', nextValue => { 35 + setState(nextValue) 36 + }) 37 + }, [setStateWrapped]) 38 + 39 + return ( 40 + <stateContext.Provider value={state}> 41 + <setContext.Provider value={setStateWrapped}> 42 + {children} 43 + </setContext.Provider> 44 + </stateContext.Provider> 45 + ) 46 + } 47 + 48 + export function useHideScaryFollowButtons() { 49 + return useContext(stateContext) ?? persisted.defaults.hideScaryFollowButtons 50 + } 51 + 52 + export function useSetHideScaryFollowButtons() { 53 + return useContext(setContext) 54 + }
+34 -27
src/state/preferences/index.tsx
··· 30 30 import {Provider as GoLinksProvider} from './go-links-enabled' 31 31 import {Provider as HiddenPostsProvider} from './hidden-posts' 32 32 import {Provider as HideFeedsPromoTabProvider} from './hide-feeds-promo-tab' 33 + import {Provider as HideScaryFollowButtonsProvider} from './hide-scary-follow-buttons.tsx' 33 34 import {Provider as HideSimilarAccountsRecommProvider} from './hide-similar-accounts-recommendations' 34 35 import {Provider as HideUnreplyablePostsProvider} from './hide-unreplyable-posts' 35 36 import {Provider as HighQualityImagesProvider} from './high-quality-images' ··· 85 86 useHideFeedsPromoTab, 86 87 useSetHideFeedsPromoTab, 87 88 } from './hide-feeds-promo-tab' 89 + export { 90 + useHideScaryFollowButtons, 91 + useSetHideScaryFollowButtons, 92 + } from './hide-scary-follow-buttons' 88 93 export {useImageCdnHost, useSetImageCdnHost} from './image-cdn-host' 89 94 export {useLabelDefinitions} from './label-defs' 90 95 export {useLanguagePrefs, useLanguagePrefsApi} from './languages' ··· 152 157 <DisablePostsMetricsProvider> 153 158 <ShowFollowsYouBadgeProvider> 154 159 <HideSimilarAccountsRecommProvider> 155 - <HideUnreplyablePostsProvider> 156 - <EnableSquareAvatarsProvider> 157 - <EnableSquareButtonsProvider> 158 - <ShowViaClientProvider> 159 - <PostNameReplacementProvider> 160 - <DisableVerifyEmailReminderProvider> 161 - <TranslationServicePreferenceProvider> 162 - <OpenRouterProvider> 163 - <DisableComposerPromptProvider> 164 - <DisableTopOfFeedButtonProvider> 165 - <DiscoverContextEnabledProvider> 166 - <OmitViaFieldProvider> 167 - { 168 - children 169 - } 170 - </OmitViaFieldProvider> 171 - </DiscoverContextEnabledProvider> 172 - </DisableTopOfFeedButtonProvider> 173 - </DisableComposerPromptProvider> 174 - </OpenRouterProvider> 175 - </TranslationServicePreferenceProvider> 176 - </DisableVerifyEmailReminderProvider> 177 - </PostNameReplacementProvider> 178 - </ShowViaClientProvider> 179 - </EnableSquareButtonsProvider> 180 - </EnableSquareAvatarsProvider> 181 - </HideUnreplyablePostsProvider> 160 + <HideScaryFollowButtonsProvider> 161 + <HideUnreplyablePostsProvider> 162 + <EnableSquareAvatarsProvider> 163 + <EnableSquareButtonsProvider> 164 + <ShowViaClientProvider> 165 + <PostNameReplacementProvider> 166 + <DisableVerifyEmailReminderProvider> 167 + <TranslationServicePreferenceProvider> 168 + <OpenRouterProvider> 169 + <DisableComposerPromptProvider> 170 + <DisableTopOfFeedButtonProvider> 171 + <DiscoverContextEnabledProvider> 172 + <OmitViaFieldProvider> 173 + { 174 + children 175 + } 176 + </OmitViaFieldProvider> 177 + </DiscoverContextEnabledProvider> 178 + </DisableTopOfFeedButtonProvider> 179 + </DisableComposerPromptProvider> 180 + </OpenRouterProvider> 181 + </TranslationServicePreferenceProvider> 182 + </DisableVerifyEmailReminderProvider> 183 + </PostNameReplacementProvider> 184 + </ShowViaClientProvider> 185 + </EnableSquareButtonsProvider> 186 + </EnableSquareAvatarsProvider> 187 + </HideUnreplyablePostsProvider> 188 + </HideScaryFollowButtonsProvider> 182 189 </HideSimilarAccountsRecommProvider> 183 190 </ShowFollowsYouBadgeProvider> 184 191 </DisablePostsMetricsProvider>