From cc94d94d593f81de2dd305c55a4843f00dc820f1 Mon Sep 17 00:00:00 2001 From: "xan.lol" Date: Sat, 25 Apr 2026 00:16:43 -0700 Subject: [PATCH] feat: toggle to disable top-of-feed button --- .../RunesSettings/UsabilitySettings.tsx | 18 ++++++ src/state/persisted/schema.ts | 2 + .../disable-top-of-feed-button.tsx | 57 +++++++++++++++++++ src/state/preferences/index.tsx | 19 +++++-- .../com/util/load-latest/LoadLatestBtn.tsx | 6 ++ 5 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 src/state/preferences/disable-top-of-feed-button.tsx diff --git a/src/screens/Settings/RunesSettings/UsabilitySettings.tsx b/src/screens/Settings/RunesSettings/UsabilitySettings.tsx index 5ee852009..e2204d1a3 100644 --- a/src/screens/Settings/RunesSettings/UsabilitySettings.tsx +++ b/src/screens/Settings/RunesSettings/UsabilitySettings.tsx @@ -5,6 +5,10 @@ import { useDisableComposerPrompt, useSetDisableComposerPrompt, } from '#/state/preferences/disable-composer-prompt' +import { + useDisableTopOfFeedButton, + useSetDisableTopOfFeedButton, +} from '#/state/preferences/disable-top-of-feed-button' import { useDisableVerifyEmailReminder, useSetDisableVerifyEmailReminder, @@ -53,6 +57,9 @@ export function RunesUsabilitySettingsScreen() { const disableComposerPrompt = useDisableComposerPrompt() const setDisableComposerPrompt = useSetDisableComposerPrompt() + const disableTopOfFeedButton = useDisableTopOfFeedButton() + const setDisableTopOfFeedButton = useSetDisableTopOfFeedButton() + const disableVerifyEmailReminder = useDisableVerifyEmailReminder() const setDisableVerifyEmailReminder = useSetDisableVerifyEmailReminder() @@ -135,6 +142,17 @@ export function RunesUsabilitySettingsScreen() { + setDisableTopOfFeedButton(value)} + style={[a.w_full]}> + + Disable top-of-feed button + + + void + +const stateContext = createContext( + persisted.defaults.disableTopOfFeedButton, +) +const setContext = createContext( + (_: persisted.Schema['disableTopOfFeedButton']) => {}, +) + +export function Provider({children}: PropsWithChildren<{}>) { + const [state, setState] = useState(persisted.get('disableTopOfFeedButton')) + + const setStateWrapped = useCallback( + (disableTopOfFeedButton: persisted.Schema['disableTopOfFeedButton']) => { + setState(disableTopOfFeedButton) + persisted.write('disableTopOfFeedButton', disableTopOfFeedButton) + }, + [setState], + ) + + useEffect(() => { + return persisted.onUpdate( + 'disableTopOfFeedButton', + nextDisableTopOfFeedButton => { + setState(nextDisableTopOfFeedButton) + }, + ) + }, [setStateWrapped]) + + return ( + + + {children} + + + ) +} + +export function useDisableTopOfFeedButton() { + return useContext(stateContext) +} + +export function useSetDisableTopOfFeedButton() { + return useContext(setContext) +} diff --git a/src/state/preferences/index.tsx b/src/state/preferences/index.tsx index 1c907446b..09e96572e 100644 --- a/src/state/preferences/index.tsx +++ b/src/state/preferences/index.tsx @@ -1,4 +1,4 @@ -import type {PropsWithChildren} from 'react' +import {type PropsWithChildren} from 'react' import {Provider as AltTextRequiredProvider} from './alt-text-required' import {Provider as AutoLikeOnRepostProvider} from './auto-like-on-repost' @@ -18,6 +18,7 @@ import {Provider as DisableQuotesMetricsProvider} from './disable-quotes-metrics import {Provider as DisableReplyMetricsProvider} from './disable-reply-metrics' import {Provider as DisableRepostsMetricsProvider} from './disable-reposts-metrics' import {Provider as DisableSavesMetricsProvider} from './disable-saves-metrics' +import {Provider as DisableTopOfFeedButtonProvider} from './disable-top-of-feed-button' import {Provider as DisableVerifyEmailReminderProvider} from './disable-verify-email-reminder' import {Provider as DisableViaRepostNotificationProvider} from './disable-via-repost-notification' import {Provider as DiscoverContextEnabledProvider} from './discover-context-enabled' @@ -63,6 +64,10 @@ export { useSetDisableComposerPrompt, } from './disable-composer-prompt' export {useHapticsDisabled, useSetHapticsDisabled} from './disable-haptics' +export { + useDisableTopOfFeedButton, + useSetDisableTopOfFeedButton, +} from './disable-top-of-feed-button' export { useDiscoverContextEnabled, useSetDiscoverContextEnabled, @@ -152,11 +157,13 @@ export function Provider({children}: PropsWithChildren<{}>) { - - { - children - } - + + + { + children + } + + diff --git a/src/view/com/util/load-latest/LoadLatestBtn.tsx b/src/view/com/util/load-latest/LoadLatestBtn.tsx index 2e0c0a438..a506dc140 100644 --- a/src/view/com/util/load-latest/LoadLatestBtn.tsx +++ b/src/view/com/util/load-latest/LoadLatestBtn.tsx @@ -8,6 +8,7 @@ import {PressableScale} from '#/lib/custom-animations/PressableScale' import {useMinimalShellFabTransform} from '#/lib/hooks/useMinimalShellTransform' import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' import {clamp} from '#/lib/numbers' +import {useDisableTopOfFeedButton} from '#/state/preferences/disable-top-of-feed-button' import {useEnableSquareButtons} from '#/state/preferences/enable-square-buttons' import {useSession} from '#/state/session' import {atoms as a, useLayoutBreakpoints, useTheme, web} from '#/alf' @@ -31,6 +32,7 @@ export function LoadLatestBtn({ const fabMinimalShellTransform = useMinimalShellFabTransform() const insets = useSafeAreaInsets() const t = useTheme() + const disableTopOfFeedButton = useDisableTopOfFeedButton() const enableSquareButtons = useEnableSquareButtons() const { state: hovered, @@ -49,6 +51,10 @@ export function LoadLatestBtn({ ? {bottom: 50} : {bottom: clamp(insets.bottom, 15, 60) + 15} + if (disableTopOfFeedButton) { + return null + } + return (