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 disable top-of-feed button

+96 -6
+18
src/screens/Settings/RunesSettings/UsabilitySettings.tsx
··· 6 6 useSetDisableComposerPrompt, 7 7 } from '#/state/preferences/disable-composer-prompt' 8 8 import { 9 + useDisableTopOfFeedButton, 10 + useSetDisableTopOfFeedButton, 11 + } from '#/state/preferences/disable-top-of-feed-button' 12 + import { 9 13 useDisableVerifyEmailReminder, 10 14 useSetDisableVerifyEmailReminder, 11 15 } from '#/state/preferences/disable-verify-email-reminder' ··· 52 56 53 57 const disableComposerPrompt = useDisableComposerPrompt() 54 58 const setDisableComposerPrompt = useSetDisableComposerPrompt() 59 + 60 + const disableTopOfFeedButton = useDisableTopOfFeedButton() 61 + const setDisableTopOfFeedButton = useSetDisableTopOfFeedButton() 55 62 56 63 const disableVerifyEmailReminder = useDisableVerifyEmailReminder() 57 64 const setDisableVerifyEmailReminder = useSetDisableVerifyEmailReminder() ··· 132 139 style={[a.w_full]}> 133 140 <Toggle.LabelText style={[a.flex_1]}> 134 141 <Trans>Disable composer prompt</Trans> 142 + </Toggle.LabelText> 143 + <Toggle.Platform /> 144 + </Toggle.Item> 145 + <Toggle.Item 146 + name="disable_top_of_feed_button" 147 + label={l`Disable top-of-feed button`} 148 + value={disableTopOfFeedButton ?? false} 149 + onChange={value => setDisableTopOfFeedButton(value)} 150 + style={[a.w_full]}> 151 + <Toggle.LabelText style={[a.flex_1]}> 152 + <Trans>Disable top-of-feed button</Trans> 135 153 </Toggle.LabelText> 136 154 <Toggle.Platform /> 137 155 </Toggle.Item>
+2
src/state/persisted/schema.ts
··· 175 175 hideFeedsPromoTab: z.boolean().optional(), 176 176 disableViaRepostNotification: z.boolean().optional(), 177 177 disableComposerPrompt: z.boolean().optional(), 178 + disableTopOfFeedButton: z.boolean().optional(), 178 179 disableLikesMetrics: z.boolean().optional(), 179 180 disableRepostsMetrics: z.boolean().optional(), 180 181 disableQuotesMetrics: z.boolean().optional(), ··· 300 301 hideFeedsPromoTab: false, 301 302 disableViaRepostNotification: false, 302 303 disableComposerPrompt: true, 304 + disableTopOfFeedButton: false, 303 305 disableLikesMetrics: false, 304 306 disableRepostsMetrics: false, 305 307 disableQuotesMetrics: false,
+57
src/state/preferences/disable-top-of-feed-button.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['disableTopOfFeedButton'] 13 + type SetContext = (v: persisted.Schema['disableTopOfFeedButton']) => void 14 + 15 + const stateContext = createContext<StateContext>( 16 + persisted.defaults.disableTopOfFeedButton, 17 + ) 18 + const setContext = createContext<SetContext>( 19 + (_: persisted.Schema['disableTopOfFeedButton']) => {}, 20 + ) 21 + 22 + export function Provider({children}: PropsWithChildren<{}>) { 23 + const [state, setState] = useState(persisted.get('disableTopOfFeedButton')) 24 + 25 + const setStateWrapped = useCallback( 26 + (disableTopOfFeedButton: persisted.Schema['disableTopOfFeedButton']) => { 27 + setState(disableTopOfFeedButton) 28 + persisted.write('disableTopOfFeedButton', disableTopOfFeedButton) 29 + }, 30 + [setState], 31 + ) 32 + 33 + useEffect(() => { 34 + return persisted.onUpdate( 35 + 'disableTopOfFeedButton', 36 + nextDisableTopOfFeedButton => { 37 + setState(nextDisableTopOfFeedButton) 38 + }, 39 + ) 40 + }, [setStateWrapped]) 41 + 42 + return ( 43 + <stateContext.Provider value={state}> 44 + <setContext.Provider value={setStateWrapped}> 45 + {children} 46 + </setContext.Provider> 47 + </stateContext.Provider> 48 + ) 49 + } 50 + 51 + export function useDisableTopOfFeedButton() { 52 + return useContext(stateContext) 53 + } 54 + 55 + export function useSetDisableTopOfFeedButton() { 56 + return useContext(setContext) 57 + }
+13 -6
src/state/preferences/index.tsx
··· 1 - import type {PropsWithChildren} from 'react' 1 + import {type PropsWithChildren} from 'react' 2 2 3 3 import {Provider as AltTextRequiredProvider} from './alt-text-required' 4 4 import {Provider as AutoLikeOnRepostProvider} from './auto-like-on-repost' ··· 18 18 import {Provider as DisableReplyMetricsProvider} from './disable-reply-metrics' 19 19 import {Provider as DisableRepostsMetricsProvider} from './disable-reposts-metrics' 20 20 import {Provider as DisableSavesMetricsProvider} from './disable-saves-metrics' 21 + import {Provider as DisableTopOfFeedButtonProvider} from './disable-top-of-feed-button' 21 22 import {Provider as DisableVerifyEmailReminderProvider} from './disable-verify-email-reminder' 22 23 import {Provider as DisableViaRepostNotificationProvider} from './disable-via-repost-notification' 23 24 import {Provider as DiscoverContextEnabledProvider} from './discover-context-enabled' ··· 63 64 useSetDisableComposerPrompt, 64 65 } from './disable-composer-prompt' 65 66 export {useHapticsDisabled, useSetHapticsDisabled} from './disable-haptics' 67 + export { 68 + useDisableTopOfFeedButton, 69 + useSetDisableTopOfFeedButton, 70 + } from './disable-top-of-feed-button' 66 71 export { 67 72 useDiscoverContextEnabled, 68 73 useSetDiscoverContextEnabled, ··· 152 157 <TranslationServicePreferenceProvider> 153 158 <OpenRouterProvider> 154 159 <DisableComposerPromptProvider> 155 - <DiscoverContextEnabledProvider> 156 - { 157 - children 158 - } 159 - </DiscoverContextEnabledProvider> 160 + <DisableTopOfFeedButtonProvider> 161 + <DiscoverContextEnabledProvider> 162 + { 163 + children 164 + } 165 + </DiscoverContextEnabledProvider> 166 + </DisableTopOfFeedButtonProvider> 160 167 </DisableComposerPromptProvider> 161 168 </OpenRouterProvider> 162 169 </TranslationServicePreferenceProvider>
+6
src/view/com/util/load-latest/LoadLatestBtn.tsx
··· 8 8 import {useMinimalShellFabTransform} from '#/lib/hooks/useMinimalShellTransform' 9 9 import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' 10 10 import {clamp} from '#/lib/numbers' 11 + import {useDisableTopOfFeedButton} from '#/state/preferences/disable-top-of-feed-button' 11 12 import {useEnableSquareButtons} from '#/state/preferences/enable-square-buttons' 12 13 import {useSession} from '#/state/session' 13 14 import {atoms as a, useLayoutBreakpoints, useTheme, web} from '#/alf' ··· 31 32 const fabMinimalShellTransform = useMinimalShellFabTransform() 32 33 const insets = useSafeAreaInsets() 33 34 const t = useTheme() 35 + const disableTopOfFeedButton = useDisableTopOfFeedButton() 34 36 const enableSquareButtons = useEnableSquareButtons() 35 37 const { 36 38 state: hovered, ··· 48 50 const bottomPosition = isTablet 49 51 ? {bottom: 50} 50 52 : {bottom: clamp(insets.bottom, 15, 60) + 15} 53 + 54 + if (disableTopOfFeedButton) { 55 + return null 56 + } 51 57 52 58 return ( 53 59 <Animated.View