Bluesky app fork with some witchin' additions 💫 witchsky.app
bluesky fork client

Merge branch 'main' of https://github.com/AutumnAurelium/deer-social

+97 -5
+21
src/screens/Settings/DeerSettings.tsx
··· 34 34 useSetDirectFetchRecords, 35 35 } from '#/state/preferences/direct-fetch-records' 36 36 import { 37 + useHideFeedsPromoTab, 38 + useSetHideFeedsPromoTab, 39 + } from '#/state/preferences/hide-feeds-promo-tab' 40 + import { 37 41 useHideFollowNotifications, 38 42 useSetHideFollowNotifications, 39 43 } from '#/state/preferences/hide-follow-notifications' ··· 227 231 228 232 const hideFollowNotifications = useHideFollowNotifications() 229 233 const setHideFollowNotifications = useSetHideFollowNotifications() 234 + 235 + const hideFeedsPromoTab = useHideFeedsPromoTab() 236 + const setHideFeedsPromoTab = useSetHideFeedsPromoTab() 230 237 231 238 const constellationInstance = useConstellationInstance() 232 239 const setConstellationInstanceControl = Dialog.useDialogControl() ··· 491 498 longer to load and use more bandwidth. 492 499 </Trans> 493 500 </Admonition> 501 + 502 + <Toggle.Item 503 + name="hide_feeds_promo_tab" 504 + label={_(msg`Hide "Feeds ✨" tab when only one feed is selected`)} 505 + value={hideFeedsPromoTab} 506 + onChange={value => setHideFeedsPromoTab(value)} 507 + style={[a.w_full]}> 508 + <Toggle.LabelText style={[a.flex_1]}> 509 + <Trans> 510 + Hide "Feeds ✨" tab when only one feed is selected 511 + </Trans> 512 + </Toggle.LabelText> 513 + <Toggle.Platform /> 514 + </Toggle.Item> 494 515 </SettingsList.Group> 495 516 496 517 <SettingsList.Group contentContainerStyle={[a.gap_sm]}>
+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(), ··· 204 205 hideFollowNotifications: false, 205 206 constellationInstance: 'https://constellation.microcosm.blue/', 206 207 showLinkInHandle: false, 208 + hideFeedsPromoTab: false, 207 209 deerVerification: { 208 210 enabled: false, 209 211 // https://social.daniela.lol/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 + }
+8 -1
src/state/preferences/index.tsx
··· 10 10 import {Provider as ExternalEmbedsProvider} from './external-embeds-prefs' 11 11 import {Provider as GoLinksProvider} from './go-links-enabled' 12 12 import {Provider as HiddenPostsProvider} from './hidden-posts' 13 + import {Provider as HideFeedsPromoTabProvider} from './hide-feeds-promo-tab' 13 14 import {Provider as FollowNotificationsProvider} from './hide-follow-notifications' 14 15 import {Provider as HighQualityImagesProvider} from './high-quality-images' 15 16 import {Provider as InAppBrowserProvider} from './in-app-browser' ··· 36 37 } from './external-embeds-prefs' 37 38 export {useGoLinksEnabled, useSetGoLinksEnabled} from './go-links-enabled' 38 39 export * from './hidden-posts' 40 + export { 41 + useHideFeedsPromoTab, 42 + useSetHideFeedsPromoTab, 43 + } from './hide-feeds-promo-tab' 39 44 export {useLabelDefinitions} from './label-defs' 40 45 export {useLanguagePrefs, useLanguagePrefsApi} from './languages' 41 46 export {useSetSubtitlesEnabled, useSubtitlesEnabled} from './subtitles' ··· 65 70 <TrendingSettingsProvider> 66 71 <RepostCarouselProvider> 67 72 <KawaiiProvider> 68 - {children} 73 + <HideFeedsPromoTabProvider> 74 + {children} 75 + </HideFeedsPromoTabProvider> 69 76 </KawaiiProvider> 70 77 </RepostCarouselProvider> 71 78 </TrendingSettingsProvider>
+16 -4
src/view/com/home/HomeHeader.tsx
··· 2 2 import {useNavigation} from '@react-navigation/native' 3 3 4 4 import {type NavigationProp} from '#/lib/routes/types' 5 + import {useHideFeedsPromoTab} from '#/state/preferences/hide-feeds-promo-tab' 5 6 import {type FeedSourceInfo} from '#/state/queries/feed' 6 7 import {useSession} from '#/state/session' 7 8 import {type RenderTabBarFnProps} from '#/view/com/pager/Pager' ··· 17 18 ) { 18 19 const {feeds, onSelect: onSelectProp} = 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 ( 47 + !hasPinnedCustom && 48 + !hideFeedsPromoTab && 49 + index === items.length - 1 50 + ) { 45 51 onPressFeedsLink() 46 52 } else if (onSelectProp) { 47 53 onSelectProp(index) 48 54 } 49 55 }, 50 - [items.length, onPressFeedsLink, onSelectProp, hasPinnedCustom], 56 + [ 57 + items.length, 58 + onPressFeedsLink, 59 + onSelectProp, 60 + hasPinnedCustom, 61 + hideFeedsPromoTab, 62 + ], 51 63 ) 52 64 53 65 return (