Bluesky app fork with some witchin' additions 💫

add option to remove "Feeds" promo when one feed is selected

+84 -6
+20
src/screens/Settings/DeerSettings.tsx
··· 35 35 useSetDirectFetchRecords, 36 36 } from '#/state/preferences/direct-fetch-records' 37 37 import { 38 + useHideFeedsPromoTab, 39 + useSetHideFeedsPromoTab, 40 + } from '#/state/preferences/hide-feeds-promo-tab' 41 + import { 38 42 useHideFollowNotifications, 39 43 useSetHideFollowNotifications, 40 44 } from '#/state/preferences/hide-follow-notifications' ··· 262 266 263 267 const hideFollowNotifications = useHideFollowNotifications() 264 268 const setHideFollowNotifications = useSetHideFollowNotifications() 269 + 270 + const hideFeedsPromoTab = useHideFeedsPromoTab() 271 + const setHideFeedsPromoTab = useSetHideFeedsPromoTab() 265 272 266 273 const location = useGeolocation() 267 274 const setLocationControl = Dialog.useDialogControl() ··· 518 525 <Trans> 519 526 On non-bsky.social handles, show a link to that URL 520 527 </Trans> 528 + </Toggle.LabelText> 529 + <Toggle.Platform /> 530 + </Toggle.Item> 531 + <Toggle.Item 532 + name="hide_feeds_promo_tab" 533 + label={_( 534 + msg`Hide "Feeds ✨" tab when only one feed is selected`, 535 + )} 536 + value={hideFeedsPromoTab} 537 + onChange={value => setHideFeedsPromoTab(value)} 538 + style={[a.w_full]}> 539 + <Toggle.LabelText style={[a.flex_1]}> 540 + <Trans>Hide "Feeds ✨" tab when only one feed is selected</Trans> 521 541 </Toggle.LabelText> 522 542 <Toggle.Platform /> 523 543 </Toggle.Item>
+2
src/state/persisted/schema.ts
··· 134 134 hideFollowNotifications: z.boolean().optional(), 135 135 constellationInstance: z.string().optional(), 136 136 showLinkInHandle: z.boolean().optional(), 137 + hideFeedsPromoTab: z.boolean().optional(), 137 138 deerVerification: z 138 139 .object({ 139 140 enabled: z.boolean(), ··· 203 204 hideFollowNotifications: false, 204 205 constellationInstance: 'https://constellation.microcosm.blue/', 205 206 showLinkInHandle: false, 207 + hideFeedsPromoTab: false, 206 208 deerVerification: { 207 209 enabled: false, 208 210 // https://deer.social/profile/did:plc:p2cp5gopk7mgjegy6wadk3ep/post/3lndyqyyr4k2k
+50
src/state/preferences/hide-feeds-promo-tab.tsx
··· 1 + import React from 'react' 2 + 3 + import * as persisted from '#/state/persisted' 4 + 5 + // Preference: hideFeedsPromoTab – when true, suppress the "Feeds ✨" promotional tab in HomeHeader. 6 + 7 + type StateContext = persisted.Schema['hideFeedsPromoTab'] 8 + // Same setter signature used across other preference modules 9 + type SetContext = (v: persisted.Schema['hideFeedsPromoTab']) => void 10 + 11 + const stateContext = React.createContext<StateContext>( 12 + persisted.defaults.hideFeedsPromoTab, 13 + ) 14 + const setContext = React.createContext<SetContext>( 15 + (_: persisted.Schema['hideFeedsPromoTab']) => {}, 16 + ) 17 + 18 + export function Provider({children}: React.PropsWithChildren<{}>) { 19 + const [state, setState] = React.useState(persisted.get('hideFeedsPromoTab')) 20 + 21 + const setStateWrapped = React.useCallback( 22 + (value: persisted.Schema['hideFeedsPromoTab']) => { 23 + setState(value) 24 + persisted.write('hideFeedsPromoTab', value) 25 + }, 26 + [setState], 27 + ) 28 + 29 + React.useEffect(() => { 30 + return persisted.onUpdate('hideFeedsPromoTab', next => { 31 + setState(next) 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 useHideFeedsPromoTab() { 45 + return React.useContext(stateContext) 46 + } 47 + 48 + export function useSetHideFeedsPromoTab() { 49 + return React.useContext(setContext) 50 + }
+6 -2
src/state/preferences/index.tsx
··· 8 8 import {Provider as DirectFetchRecordsProvider} from './direct-fetch-records' 9 9 import {Provider as DisableHapticsProvider} from './disable-haptics' 10 10 import {Provider as ExternalEmbedsProvider} from './external-embeds-prefs' 11 + import {Provider as FollowNotificationsProvider} from './hide-follow-notifications' 11 12 import {Provider as GoLinksProvider} from './go-links-enabled' 12 13 import {Provider as HiddenPostsProvider} from './hidden-posts' 13 - import {Provider as FollowNotificationsProvider} from './hide-follow-notifications' 14 + import {Provider as HideFeedsPromoTabProvider} from './hide-feeds-promo-tab' 14 15 import {Provider as InAppBrowserProvider} from './in-app-browser' 15 16 import {Provider as KawaiiProvider} from './kawaii' 16 17 import {Provider as LanguagesProvider} from './languages' ··· 35 36 } from './external-embeds-prefs' 36 37 export {useGoLinksEnabled, useSetGoLinksEnabled} from './go-links-enabled' 37 38 export * from './hidden-posts' 39 + export {useHideFeedsPromoTab, useSetHideFeedsPromoTab} from './hide-feeds-promo-tab' 38 40 export {useLabelDefinitions} from './label-defs' 39 41 export {useLanguagePrefs, useLanguagePrefsApi} from './languages' 40 42 export {useSetSubtitlesEnabled, useSubtitlesEnabled} from './subtitles' ··· 63 65 <TrendingSettingsProvider> 64 66 <RepostCarouselProvider> 65 67 <KawaiiProvider> 66 - {children} 68 + <HideFeedsPromoTabProvider> 69 + {children} 70 + </HideFeedsPromoTabProvider> 67 71 </KawaiiProvider> 68 72 </RepostCarouselProvider> 69 73 </TrendingSettingsProvider>
+6 -4
src/view/com/home/HomeHeader.tsx
··· 1 1 import React from 'react' 2 2 import {useNavigation} from '@react-navigation/native' 3 + import {useHideFeedsPromoTab} from '#/state/preferences/hide-feeds-promo-tab' 3 4 4 5 import {NavigationProp} from '#/lib/routes/types' 5 6 import {FeedSourceInfo} from '#/state/queries/feed' ··· 17 18 ) { 18 19 const {feeds} = props 19 20 const {hasSession} = useSession() 21 + const hideFeedsPromoTab = useHideFeedsPromoTab() 20 22 const navigation = useNavigation<NavigationProp>() 21 23 22 24 const hasPinnedCustom = React.useMemo<boolean>(() => { ··· 29 31 30 32 const items = React.useMemo(() => { 31 33 const pinnedNames = feeds.map(f => f.displayName) 32 - if (!hasPinnedCustom) { 34 + if (!hasPinnedCustom && !hideFeedsPromoTab) { 33 35 return pinnedNames.concat('Feeds ✨') 34 36 } 35 37 return pinnedNames 36 - }, [hasPinnedCustom, feeds]) 38 + }, [hasPinnedCustom, hideFeedsPromoTab, feeds]) 37 39 38 40 const onPressFeedsLink = React.useCallback(() => { 39 41 navigation.navigate('Feeds') ··· 41 43 42 44 const onSelect = React.useCallback( 43 45 (index: number) => { 44 - if (!hasPinnedCustom && index === items.length - 1) { 46 + if (!hasPinnedCustom && !hideFeedsPromoTab && index === items.length - 1) { 45 47 onPressFeedsLink() 46 48 } else if (props.onSelect) { 47 49 props.onSelect(index) 48 50 } 49 51 }, 50 - [items.length, onPressFeedsLink, props, hasPinnedCustom], 52 + [items.length, onPressFeedsLink, props, hasPinnedCustom, hideFeedsPromoTab], 51 53 ) 52 54 53 55 return (