Bluesky app fork with some witchin' additions 💫

remove hide follow notification deer tweak

+42 -151
-26
src/screens/Settings/DeerSettings.tsx
··· 38 38 useSetHideFeedsPromoTab, 39 39 } from '#/state/preferences/hide-feeds-promo-tab' 40 40 import { 41 - useHideFollowNotifications, 42 - useSetHideFollowNotifications, 43 - } from '#/state/preferences/hide-follow-notifications' 44 - import { 45 41 useHighQualityImages, 46 42 useSetHighQualityImages, 47 43 } from '#/state/preferences/high-quality-images' ··· 70 66 import * as Dialog from '#/components/Dialog' 71 67 import * as Toggle from '#/components/forms/Toggle' 72 68 import {Atom_Stroke2_Corner0_Rounded as DeerIcon} from '#/components/icons/Atom' 73 - import {Bell_Stroke2_Corner0_Rounded as BellIcon} from '#/components/icons/Bell' 74 69 import {Eye_Stroke2_Corner0_Rounded as VisibilityIcon} from '#/components/icons/Eye' 75 70 import {Lab_Stroke2_Corner0_Rounded as BeakerIcon} from '#/components/icons/Lab' 76 71 import {PaintRoller_Stroke2_Corner2_Rounded as PaintRollerIcon} from '#/components/icons/PaintRoller' ··· 228 223 229 224 const highQualityImages = useHighQualityImages() 230 225 const setHighQualityImages = useSetHighQualityImages() 231 - 232 - const hideFollowNotifications = useHideFollowNotifications() 233 - const setHideFollowNotifications = useSetHideFollowNotifications() 234 226 235 227 const hideFeedsPromoTab = useHideFeedsPromoTab() 236 228 const setHideFeedsPromoTab = useSetHideFeedsPromoTab() ··· 509 501 <Trans> 510 502 Hide "Feeds ✨" tab when only one feed is selected 511 503 </Trans> 512 - </Toggle.LabelText> 513 - <Toggle.Platform /> 514 - </Toggle.Item> 515 - </SettingsList.Group> 516 - 517 - <SettingsList.Group contentContainerStyle={[a.gap_sm]}> 518 - <SettingsList.ItemIcon icon={BellIcon} /> 519 - <SettingsList.ItemText> 520 - <Trans>Notification Filters</Trans> 521 - </SettingsList.ItemText> 522 - <Toggle.Item 523 - name="hide_follow_notifications" 524 - label={_(msg`Hide follow notifications`)} 525 - value={hideFollowNotifications ?? false} 526 - onChange={value => setHideFollowNotifications(value)} 527 - style={[a.w_full]}> 528 - <Toggle.LabelText style={[a.flex_1]}> 529 - <Trans>Hide follow notifications</Trans> 530 504 </Toggle.LabelText> 531 505 <Toggle.Platform /> 532 506 </Toggle.Item>
-2
src/state/persisted/schema.ts
··· 131 131 noAppLabelers: z.boolean().optional(), 132 132 noDiscoverFallback: z.boolean().optional(), 133 133 repostCarouselEnabled: z.boolean().optional(), 134 - hideFollowNotifications: z.boolean().optional(), 135 134 constellationInstance: z.string().optional(), 136 135 showLinkInHandle: z.boolean().optional(), 137 136 hideFeedsPromoTab: z.boolean().optional(), ··· 202 201 noAppLabelers: false, 203 202 noDiscoverFallback: false, 204 203 repostCarouselEnabled: false, 205 - hideFollowNotifications: false, 206 204 constellationInstance: 'https://constellation.microcosm.blue/', 207 205 showLinkInHandle: false, 208 206 hideFeedsPromoTab: false,
-52
src/state/preferences/hide-follow-notifications.tsx
··· 1 - import React from 'react' 2 - 3 - import * as persisted from '#/state/persisted' 4 - 5 - type StateContext = persisted.Schema['hideFollowNotifications'] 6 - type SetContext = (v: persisted.Schema['hideFollowNotifications']) => void 7 - 8 - const stateContext = React.createContext<StateContext>( 9 - persisted.defaults.hideFollowNotifications, 10 - ) 11 - const setContext = React.createContext<SetContext>( 12 - (_: persisted.Schema['hideFollowNotifications']) => {}, 13 - ) 14 - 15 - export function Provider({children}: React.PropsWithChildren<{}>) { 16 - const [state, setState] = React.useState( 17 - persisted.get('hideFollowNotifications'), 18 - ) 19 - 20 - const setStateWrapped = React.useCallback( 21 - (hideFollowNotifications: persisted.Schema['hideFollowNotifications']) => { 22 - setState(hideFollowNotifications) 23 - persisted.write('hideFollowNotifications', hideFollowNotifications) 24 - }, 25 - [setState], 26 - ) 27 - 28 - React.useEffect(() => { 29 - return persisted.onUpdate( 30 - 'hideFollowNotifications', 31 - nextHideFollowNotifications => { 32 - setState(nextHideFollowNotifications) 33 - }, 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 useHideFollowNotifications() { 47 - return React.useContext(stateContext) 48 - } 49 - 50 - export function useSetHideFollowNotifications() { 51 - return React.useContext(setContext) 52 - }
+39 -42
src/state/preferences/index.tsx
··· 11 11 import {Provider as GoLinksProvider} from './go-links-enabled' 12 12 import {Provider as HiddenPostsProvider} from './hidden-posts' 13 13 import {Provider as HideFeedsPromoTabProvider} from './hide-feeds-promo-tab' 14 - import {Provider as FollowNotificationsProvider} from './hide-follow-notifications' 15 14 import {Provider as HighQualityImagesProvider} from './high-quality-images' 16 15 import {Provider as InAppBrowserProvider} from './in-app-browser' 17 16 import {Provider as KawaiiProvider} from './kawaii' ··· 51 50 <AltTextRequiredProvider> 52 51 <GoLinksProvider> 53 52 <NoAppLabelersProvider> 54 - <FollowNotificationsProvider> 55 - <DirectFetchRecordsProvider> 56 - <ConstellationProvider> 57 - <ConstellationInstanceProvider> 58 - <DeerVerificationProvider> 59 - <NoDiscoverProvider> 60 - <ShowLinkInHandleProvider> 61 - <LargeAltBadgeProvider> 62 - <ExternalEmbedsProvider> 63 - <HiddenPostsProvider> 64 - <HighQualityImagesProvider> 65 - <InAppBrowserProvider> 66 - <DisableHapticsProvider> 67 - <AutoplayProvider> 68 - <UsedStarterPacksProvider> 69 - <SubtitlesProvider> 70 - <TrendingSettingsProvider> 71 - <RepostCarouselProvider> 72 - <KawaiiProvider> 73 - <HideFeedsPromoTabProvider> 74 - {children} 75 - </HideFeedsPromoTabProvider> 76 - </KawaiiProvider> 77 - </RepostCarouselProvider> 78 - </TrendingSettingsProvider> 79 - </SubtitlesProvider> 80 - </UsedStarterPacksProvider> 81 - </AutoplayProvider> 82 - </DisableHapticsProvider> 83 - </InAppBrowserProvider> 84 - </HighQualityImagesProvider> 85 - </HiddenPostsProvider> 86 - </ExternalEmbedsProvider> 87 - </LargeAltBadgeProvider> 88 - </ShowLinkInHandleProvider> 89 - </NoDiscoverProvider> 90 - </DeerVerificationProvider> 91 - </ConstellationInstanceProvider> 92 - </ConstellationProvider> 93 - </DirectFetchRecordsProvider> 94 - </FollowNotificationsProvider> 53 + <DirectFetchRecordsProvider> 54 + <ConstellationProvider> 55 + <ConstellationInstanceProvider> 56 + <DeerVerificationProvider> 57 + <NoDiscoverProvider> 58 + <ShowLinkInHandleProvider> 59 + <LargeAltBadgeProvider> 60 + <ExternalEmbedsProvider> 61 + <HiddenPostsProvider> 62 + <HighQualityImagesProvider> 63 + <InAppBrowserProvider> 64 + <DisableHapticsProvider> 65 + <AutoplayProvider> 66 + <UsedStarterPacksProvider> 67 + <SubtitlesProvider> 68 + <TrendingSettingsProvider> 69 + <RepostCarouselProvider> 70 + <KawaiiProvider> 71 + <HideFeedsPromoTabProvider> 72 + {children} 73 + </HideFeedsPromoTabProvider> 74 + </KawaiiProvider> 75 + </RepostCarouselProvider> 76 + </TrendingSettingsProvider> 77 + </SubtitlesProvider> 78 + </UsedStarterPacksProvider> 79 + </AutoplayProvider> 80 + </DisableHapticsProvider> 81 + </InAppBrowserProvider> 82 + </HighQualityImagesProvider> 83 + </HiddenPostsProvider> 84 + </ExternalEmbedsProvider> 85 + </LargeAltBadgeProvider> 86 + </ShowLinkInHandleProvider> 87 + </NoDiscoverProvider> 88 + </DeerVerificationProvider> 89 + </ConstellationInstanceProvider> 90 + </ConstellationProvider> 91 + </DirectFetchRecordsProvider> 95 92 </NoAppLabelersProvider> 96 93 </GoLinksProvider> 97 94 </AltTextRequiredProvider>
-3
src/state/queries/notifications/feed.ts
··· 32 32 useQueryClient, 33 33 } from '@tanstack/react-query' 34 34 35 - import {useHideFollowNotifications} from '#/state/preferences/hide-follow-notifications' 36 35 import {useModerationOpts} from '#/state/preferences/moderation-opts' 37 36 import {STALE} from '#/state/queries' 38 37 import {useAgent} from '#/state/session' ··· 64 63 const agent = useAgent() 65 64 const queryClient = useQueryClient() 66 65 const moderationOpts = useModerationOpts() 67 - const hideFollowNotifications = useHideFollowNotifications() 68 66 const unreads = useUnreadNotificationsApi() 69 67 const enabled = opts.enabled !== false 70 68 const filter = opts.filter ··· 113 111 cursor: pageParam, 114 112 queryClient, 115 113 moderationOpts, 116 - hideFollowNotifications, 117 114 fetchAdditionalData: true, 118 115 reasons, 119 116 })
+1 -10
src/state/queries/notifications/unread.tsx
··· 10 10 import BroadcastChannel from '#/lib/broadcast' 11 11 import {resetBadgeCount} from '#/lib/notifications/notifications' 12 12 import {logger} from '#/logger' 13 - import {useHideFollowNotifications} from '#/state/preferences/hide-follow-notifications' 14 13 import {useAgent, useSession} from '#/state/session' 15 14 import {useModerationOpts} from '../../preferences/moderation-opts' 16 15 import {truncateAndInvalidate} from '../util' ··· 50 49 const agent = useAgent() 51 50 const queryClient = useQueryClient() 52 51 const moderationOpts = useModerationOpts() 53 - const hideFollowNotifications = useHideFollowNotifications() 54 52 55 53 const [numUnread, setNumUnread] = React.useState('') 56 54 ··· 157 155 limit: 40, 158 156 queryClient, 159 157 moderationOpts, 160 - hideFollowNotifications, 161 158 reasons: [], 162 159 163 160 // only fetch subjects when the page is going to be used ··· 206 203 } 207 204 }, 208 205 } 209 - }, [ 210 - setNumUnread, 211 - queryClient, 212 - moderationOpts, 213 - hideFollowNotifications, 214 - agent, 215 - ]) 206 + }, [setNumUnread, queryClient, moderationOpts, agent]) 216 207 checkUnreadRef.current = api.checkUnread 217 208 218 209 return (
+1 -7
src/state/queries/notifications/util.ts
··· 43 43 limit, 44 44 queryClient, 45 45 moderationOpts, 46 - hideFollowNotifications, 47 46 fetchAdditionalData, 48 47 reasons, 49 48 }: { ··· 52 51 limit: number 53 52 queryClient: QueryClient 54 53 moderationOpts: ModerationOpts | undefined 55 - hideFollowNotifications: boolean | undefined 56 54 fetchAdditionalData: boolean 57 55 reasons: string[] 58 56 }): Promise<{ ··· 69 67 70 68 // filter out notifs by mod rules 71 69 const notifs = res.data.notifications.filter( 72 - notif => !shouldFilterNotif(notif, moderationOpts, hideFollowNotifications), 70 + notif => !shouldFilterNotif(notif, moderationOpts), 73 71 ) 74 72 75 73 // group notifications which are essentially similar (follows, likes on a post) ··· 120 118 export function shouldFilterNotif( 121 119 notif: AppBskyNotificationListNotifications.Notification, 122 120 moderationOpts: ModerationOpts | undefined, 123 - hideFollowNotifications: boolean | undefined, 124 121 ): boolean { 125 122 const containsImperative = !!notif.author.labels?.some(labelIsHideableOffense) 126 123 if (containsImperative) { 127 - return true 128 - } 129 - if (hideFollowNotifications && notif.reason == 'follow') { 130 124 return true 131 125 } 132 126 if (!moderationOpts) {
+1 -9
src/view/screens/DebugMod.tsx
··· 24 24 type CommonNavigatorParams, 25 25 type NativeStackScreenProps, 26 26 } from '#/lib/routes/types' 27 - import {useHideFollowNotifications} from '#/state/preferences/hide-follow-notifications' 28 27 import {useModerationOpts} from '#/state/preferences/moderation-opts' 29 28 import {moderationOptsOverrideContext} from '#/state/preferences/moderation-opts' 30 29 import {type FeedNotification} from '#/state/queries/notifications/types' ··· 878 877 moderationOpts: ModerationOpts 879 878 }) { 880 879 const t = useTheme() 881 - const hideFollowNotifications = useHideFollowNotifications() 882 - if ( 883 - shouldFilterNotif( 884 - notif.notification, 885 - moderationOpts, 886 - hideFollowNotifications, 887 - ) 888 - ) { 880 + if (shouldFilterNotif(notif.notification, moderationOpts)) { 889 881 return ( 890 882 <P style={[t.atoms.bg_contrast_25, a.px_lg, a.py_md]}> 891 883 Filtered from the feed