Bluesky app fork with some witchin' additions 💫

add toggle to hide similar accounts recommendations

+130 -48
+53 -47
src/components/FeedInterstitials.tsx
··· 9 9 import {logEvent} from '#/lib/statsig/statsig' 10 10 import {logger} from '#/logger' 11 11 import {isIOS} from '#/platform/detection' 12 + import {useHideSimilarAccountsRecomm} from '#/state/preferences/hide-similar-accounts-recommendations' 12 13 import {useModerationOpts} from '#/state/preferences/moderation-opts' 13 14 import {useGetPopularFeedsQuery} from '#/state/queries/feed' 14 15 import {type FeedDescriptor} from '#/state/queries/post-feed' ··· 258 259 const maxLength = gtMobile ? 3 : isProfileHeaderContext ? 12 : 6 259 260 const minLength = gtMobile ? 3 : 4 260 261 262 + // hide similar accounts 263 + const hideSimilarAccountsRecomm = useHideSimilarAccountsRecomm() 264 + 261 265 const content = isLoading 262 266 ? Array(maxLength) 263 267 .fill(0) ··· 363 367 return null 364 368 } 365 369 366 - return ( 367 - <View 368 - style={[ 369 - !isProfileHeaderContext && a.border_t, 370 - t.atoms.border_contrast_low, 371 - t.atoms.bg_contrast_25, 372 - ]} 373 - pointerEvents={isIOS ? 'auto' : 'box-none'}> 370 + if (!hideSimilarAccountsRecomm) { 371 + return ( 374 372 <View 375 373 style={[ 376 - a.px_lg, 377 - a.pt_md, 378 - a.flex_row, 379 - a.align_center, 380 - a.justify_between, 374 + !isProfileHeaderContext && a.border_t, 375 + t.atoms.border_contrast_low, 376 + t.atoms.bg_contrast_25, 381 377 ]} 382 378 pointerEvents={isIOS ? 'auto' : 'box-none'}> 383 - <Text style={[a.text_sm, a.font_bold, t.atoms.text]}> 384 - {isFeedContext ? ( 385 - <Trans>Suggested for you</Trans> 386 - ) : ( 387 - <Trans>Similar accounts</Trans> 379 + <View 380 + style={[ 381 + a.px_lg, 382 + a.pt_md, 383 + a.flex_row, 384 + a.align_center, 385 + a.justify_between, 386 + ]} 387 + pointerEvents={isIOS ? 'auto' : 'box-none'}> 388 + <Text style={[a.text_sm, a.font_bold, t.atoms.text]}> 389 + {isFeedContext ? ( 390 + <Trans>Suggested for you</Trans> 391 + ) : ( 392 + <Trans>Similar accounts</Trans> 393 + )} 394 + </Text> 395 + {!isProfileHeaderContext && ( 396 + <InlineLinkText 397 + label={_(msg`See more suggested profiles on the Explore page`)} 398 + to="/search"> 399 + <Trans>See more</Trans> 400 + </InlineLinkText> 388 401 )} 389 - </Text> 390 - {!isProfileHeaderContext && ( 391 - <InlineLinkText 392 - label={_(msg`See more suggested profiles on the Explore page`)} 393 - to="/search"> 394 - <Trans>See more</Trans> 395 - </InlineLinkText> 396 - )} 397 - </View> 402 + </View> 398 403 399 - {gtMobile ? ( 400 - <View style={[a.p_lg, a.pt_md]}> 401 - <View style={[a.flex_1, a.flex_row, a.flex_wrap, a.gap_md]}> 402 - {content} 404 + {gtMobile ? ( 405 + <View style={[a.p_lg, a.pt_md]}> 406 + <View style={[a.flex_1, a.flex_row, a.flex_wrap, a.gap_md]}> 407 + {content} 408 + </View> 403 409 </View> 404 - </View> 405 - ) : ( 406 - <BlockDrawerGesture> 407 - <ScrollView 408 - horizontal 409 - showsHorizontalScrollIndicator={false} 410 - contentContainerStyle={[a.p_lg, a.pt_md, a.flex_row, a.gap_md]} 411 - snapToInterval={MOBILE_CARD_WIDTH + a.gap_md.gap} 412 - decelerationRate="fast"> 413 - {content} 410 + ) : ( 411 + <BlockDrawerGesture> 412 + <ScrollView 413 + horizontal 414 + showsHorizontalScrollIndicator={false} 415 + contentContainerStyle={[a.p_lg, a.pt_md, a.flex_row, a.gap_md]} 416 + snapToInterval={MOBILE_CARD_WIDTH + a.gap_md.gap} 417 + decelerationRate="fast"> 418 + {content} 414 419 415 - {!isProfileHeaderContext && <SeeMoreSuggestedProfilesCard />} 416 - </ScrollView> 417 - </BlockDrawerGesture> 418 - )} 419 - </View> 420 - ) 420 + {!isProfileHeaderContext && <SeeMoreSuggestedProfilesCard />} 421 + </ScrollView> 422 + </BlockDrawerGesture> 423 + )} 424 + </View> 425 + ) 426 + } 421 427 } 422 428 423 429 function SeeMoreSuggestedProfilesCard() {
+19
src/screens/Settings/DeerSettings.tsx
··· 62 62 useSetHideFeedsPromoTab, 63 63 } from '#/state/preferences/hide-feeds-promo-tab' 64 64 import { 65 + useHideSimilarAccountsRecomm, 66 + useSetHideSimilarAccountsRecomm, 67 + } from '#/state/preferences/hide-similar-accounts-recommendations' 68 + import { 65 69 useHighQualityImages, 66 70 useSetHighQualityImages, 67 71 } from '#/state/preferences/high-quality-images' ··· 268 272 269 273 const disableReplyMetrics = useDisableReplyMetrics() 270 274 const setDisableReplyMetrics = useSetDisableReplyMetrics() 275 + 276 + const hideSimilarAccountsRecomm = useHideSimilarAccountsRecomm() 277 + const setHideSimilarAccountsRecomm = useSetHideSimilarAccountsRecomm() 271 278 272 279 const constellationInstance = useConstellationInstance() 273 280 const setConstellationInstanceControl = Dialog.useDialogControl() ··· 564 571 you like/repost a post someone else has reposted for privacy. 565 572 </Trans> 566 573 </Admonition> 574 + 575 + <Toggle.Item 576 + name="hide_similar_accounts_recommendations" 577 + label={_(msg`Hide similar accounts recommendations`)} 578 + value={hideSimilarAccountsRecomm} 579 + onChange={value => setHideSimilarAccountsRecomm(value)} 580 + style={[a.w_full]}> 581 + <Toggle.LabelText style={[a.flex_1]}> 582 + <Trans>Hide similar accounts recommendations</Trans> 583 + </Toggle.LabelText> 584 + <Toggle.Platform /> 585 + </Toggle.Item> 567 586 </SettingsList.Group> 568 587 569 588 <SettingsList.Group contentContainerStyle={[a.gap_sm]}>
+2
src/state/persisted/schema.ts
··· 140 140 disableQuotesMetrics: z.boolean().optional(), 141 141 disableSavesMetrics: z.boolean().optional(), 142 142 disableReplyMetrics: z.boolean().optional(), 143 + hideSimilarAccountsRecomm: z.boolean().optional(), 143 144 deerVerification: z 144 145 .object({ 145 146 enabled: z.boolean(), ··· 216 217 disableQuotesMetrics: false, 217 218 disableSavesMetrics: false, 218 219 disableReplyMetrics: false, 220 + hideSimilarAccountsRecomm: false, 219 221 deerVerification: { 220 222 enabled: false, 221 223 // https://social.daniela.lol/profile/did:plc:p2cp5gopk7mgjegy6wadk3ep/post/3lndyqyyr4k2k
+52
src/state/preferences/hide-similar-accounts-recommendations.tsx
··· 1 + import React from 'react' 2 + 3 + import * as persisted from '#/state/persisted' 4 + 5 + // Preference: hideSimilarAccountsRecomm – when true, hides similar accounts recommendations 6 + 7 + type StateContext = persisted.Schema['hideSimilarAccountsRecomm'] 8 + // Same setter signature used across other preference modules 9 + type SetContext = (v: persisted.Schema['hideSimilarAccountsRecomm']) => void 10 + 11 + const stateContext = React.createContext<StateContext>( 12 + persisted.defaults.hideSimilarAccountsRecomm, 13 + ) 14 + const setContext = React.createContext<SetContext>( 15 + (_: persisted.Schema['hideSimilarAccountsRecomm']) => {}, 16 + ) 17 + 18 + export function Provider({children}: React.PropsWithChildren<{}>) { 19 + const [state, setState] = React.useState( 20 + persisted.get('hideSimilarAccountsRecomm'), 21 + ) 22 + 23 + const setStateWrapped = React.useCallback( 24 + (value: persisted.Schema['hideSimilarAccountsRecomm']) => { 25 + setState(value) 26 + persisted.write('hideSimilarAccountsRecomm', value) 27 + }, 28 + [setState], 29 + ) 30 + 31 + React.useEffect(() => { 32 + return persisted.onUpdate('hideSimilarAccountsRecomm', next => { 33 + setState(next) 34 + }) 35 + }, [setStateWrapped]) 36 + 37 + return ( 38 + <stateContext.Provider value={state}> 39 + <setContext.Provider value={setStateWrapped}> 40 + {children} 41 + </setContext.Provider> 42 + </stateContext.Provider> 43 + ) 44 + } 45 + 46 + export function useHideSimilarAccountsRecomm() { 47 + return React.useContext(stateContext) 48 + } 49 + 50 + export function useSetHideSimilarAccountsRecomm() { 51 + return React.useContext(setContext) 52 + }
+4 -1
src/state/preferences/index.tsx
··· 17 17 import {Provider as GoLinksProvider} from './go-links-enabled' 18 18 import {Provider as HiddenPostsProvider} from './hidden-posts' 19 19 import {Provider as HideFeedsPromoTabProvider} from './hide-feeds-promo-tab' 20 + import {Provider as HideSimilarAccountsRecommProvider} from './hide-similar-accounts-recommendations' 20 21 import {Provider as HighQualityImagesProvider} from './high-quality-images' 21 22 import {Provider as InAppBrowserProvider} from './in-app-browser' 22 23 import {Provider as KawaiiProvider} from './kawaii' ··· 81 82 <DisableQuotesMetricsProvider> 82 83 <DisableSavesMetricsProvider> 83 84 <DisableReplyMetricsProvider> 84 - {children} 85 + <HideSimilarAccountsRecommProvider> 86 + {children} 87 + </HideSimilarAccountsRecommProvider> 85 88 </DisableReplyMetricsProvider> 86 89 </DisableSavesMetricsProvider> 87 90 </DisableQuotesMetricsProvider>