Adds a toggle to hide posts that can't be replied to (e.g they are postgated to you). I have no idea how to test this one.
+25
src/screens/Settings/DeerSettings.tsx
+25
src/screens/Settings/DeerSettings.tsx
···
88
88
useHideSimilarAccountsRecomm,
89
89
useSetHideSimilarAccountsRecomm,
90
90
} from '#/state/preferences/hide-similar-accounts-recommendations'
91
+
import {
92
+
useHideUnreplyablePosts,
93
+
useSetHideUnreplyablePosts,
94
+
} from '#/state/preferences/hide-unreplyable-posts'
91
95
import {
92
96
useHighQualityImages,
93
97
useSetHighQualityImages,
···
443
447
const hideSimilarAccountsRecomm = useHideSimilarAccountsRecomm()
444
448
const setHideSimilarAccountsRecomm = useSetHideSimilarAccountsRecomm()
445
449
450
+
const hideUnreplyablePosts = useHideUnreplyablePosts()
451
+
const setHideUnreplyablePosts = useSetHideUnreplyablePosts()
452
+
446
453
const disableVerifyEmailReminder = useDisableVerifyEmailReminder()
447
454
const setDisableVerifyEmailReminder = useSetDisableVerifyEmailReminder()
448
455
···
742
749
<Toggle.Platform />
743
750
</Toggle.Item>
744
751
752
+
<Toggle.Item
753
+
name="hide_unreplyable_posts"
754
+
label={_(msg`Hide posts that cannot be replied to from feeds`)}
755
+
value={hideUnreplyablePosts}
756
+
onChange={value => setHideUnreplyablePosts(value)}
757
+
style={[a.w_full]}>
758
+
<Toggle.LabelText style={[a.flex_1]}>
759
+
<Trans>Hide posts that cannot be replied to from feeds</Trans>
760
+
</Toggle.LabelText>
761
+
<Toggle.Platform />
762
+
</Toggle.Item>
763
+
<Admonition type="info" style={[a.flex_1]}>
764
+
<Trans>
765
+
Hides posts from feeds where replies are disabled (e.g. due to
766
+
postgates or other restrictions). Does not affect thread views.
767
+
</Trans>
768
+
</Admonition>
769
+
745
770
<Toggle.Item
746
771
name="disable_verify_email_reminder"
747
772
label={_(msg`Disable verify email reminder`)}
+2
src/state/persisted/schema.ts
+2
src/state/persisted/schema.ts
···
166
166
})
167
167
.optional(),
168
168
highQualityImages: z.boolean().optional(),
169
+
hideUnreplyablePosts: z.boolean().optional(),
169
170
170
171
showExternalShareButtons: z.boolean().optional(),
171
172
···
269
270
],
270
271
},
271
272
highQualityImages: false,
273
+
hideUnreplyablePosts: false,
272
274
showExternalShareButtons: false,
273
275
}
274
276
+51
src/state/preferences/hide-unreplyable-posts.tsx
+51
src/state/preferences/hide-unreplyable-posts.tsx
···
1
+
import React from 'react'
2
+
3
+
import * as persisted from '#/state/persisted'
4
+
5
+
type StateContext = persisted.Schema['hideUnreplyablePosts']
6
+
type SetContext = (v: persisted.Schema['hideUnreplyablePosts']) => void
7
+
8
+
const stateContext = React.createContext<StateContext>(
9
+
persisted.defaults.hideUnreplyablePosts,
10
+
)
11
+
const setContext = React.createContext<SetContext>(
12
+
(_: persisted.Schema['hideUnreplyablePosts']) => {},
13
+
)
14
+
15
+
export function Provider({children}: React.PropsWithChildren<{}>) {
16
+
const [state, setState] = React.useState(
17
+
persisted.get('hideUnreplyablePosts'),
18
+
)
19
+
20
+
const setStateWrapped = React.useCallback(
21
+
(hideUnreplyablePosts: persisted.Schema['hideUnreplyablePosts']) => {
22
+
setState(hideUnreplyablePosts)
23
+
persisted.write('hideUnreplyablePosts', hideUnreplyablePosts)
24
+
},
25
+
[setState],
26
+
)
27
+
28
+
React.useEffect(() => {
29
+
return persisted.onUpdate('hideUnreplyablePosts', nextValue => {
30
+
setState(nextValue)
31
+
})
32
+
}, [setStateWrapped])
33
+
34
+
return (
35
+
<stateContext.Provider value={state}>
36
+
<setContext.Provider value={setStateWrapped}>
37
+
{children}
38
+
</setContext.Provider>
39
+
</stateContext.Provider>
40
+
)
41
+
}
42
+
43
+
export function useHideUnreplyablePosts() {
44
+
return (
45
+
React.useContext(stateContext) ?? persisted.defaults.hideUnreplyablePosts
46
+
)
47
+
}
48
+
49
+
export function useSetHideUnreplyablePosts() {
50
+
return React.useContext(setContext)
51
+
}
+10
-7
src/state/preferences/index.tsx
+10
-7
src/state/preferences/index.tsx
···
26
26
import {Provider as HiddenPostsProvider} from './hidden-posts'
27
27
import {Provider as HideFeedsPromoTabProvider} from './hide-feeds-promo-tab'
28
28
import {Provider as HideSimilarAccountsRecommProvider} from './hide-similar-accounts-recommendations'
29
+
import {Provider as HideUnreplyablePostsProvider} from './hide-unreplyable-posts'
29
30
import {Provider as HighQualityImagesProvider} from './high-quality-images'
30
31
import {Provider as InAppBrowserProvider} from './in-app-browser'
31
32
import {Provider as KawaiiProvider} from './kawaii'
···
96
97
<DisableFollowedByMetricsProvider>
97
98
<DisablePostsMetricsProvider>
98
99
<HideSimilarAccountsRecommProvider>
99
-
<EnableSquareAvatarsProvider>
100
-
<EnableSquareButtonsProvider>
101
-
<DisableVerifyEmailReminderProvider>
102
-
{children}
103
-
</DisableVerifyEmailReminderProvider>
104
-
</EnableSquareButtonsProvider>
105
-
</EnableSquareAvatarsProvider>
100
+
<HideUnreplyablePostsProvider>
101
+
<EnableSquareAvatarsProvider>
102
+
<EnableSquareButtonsProvider>
103
+
<DisableVerifyEmailReminderProvider>
104
+
{children}
105
+
</DisableVerifyEmailReminderProvider>
106
+
</EnableSquareButtonsProvider>
107
+
</EnableSquareAvatarsProvider>
108
+
</HideUnreplyablePostsProvider>
106
109
</HideSimilarAccountsRecommProvider>
107
110
</DisablePostsMetricsProvider>
108
111
</DisableFollowedByMetricsProvider>
+24
src/view/com/posts/PostFeed.tsx
+24
src/view/com/posts/PostFeed.tsx
···
37
37
import {isIOS, isNative, isWeb} from '#/platform/detection'
38
38
import {listenPostCreated} from '#/state/events'
39
39
import {useFeedFeedbackContext} from '#/state/feed-feedback'
40
+
import {useHideUnreplyablePosts} from '#/state/preferences/hide-unreplyable-posts'
40
41
import {useRepostCarouselEnabled} from '#/state/preferences/repost-carousel-enabled'
41
42
import {useTrendingSettings} from '#/state/preferences/trending'
42
43
import {STALE} from '#/state/queries'
···
426
427
const {trendingDisabled, trendingVideoDisabled} = useTrendingSettings()
427
428
428
429
const repostCarouselEnabled = useRepostCarouselEnabled()
430
+
const hideUnreplyablePosts = useHideUnreplyablePosts()
429
431
430
432
if (feedType === 'following') {
431
433
useRepostCarousel = repostCarouselEnabled
···
546
548
? groupReposts(page.slices)
547
549
: (page.slices as FeedPostSliceOrGroup[])
548
550
551
+
// Filter out posts that cannot be replied to if the setting is enabled
552
+
if (hideUnreplyablePosts) {
553
+
slices = slices.filter(slice => {
554
+
if (slice.isRepostSlice) {
555
+
// For repost slices, filter the inner slices
556
+
slice.slices = slice.slices.filter(innerSlice => {
557
+
// Check if any item in the slice has replyDisabled
558
+
return !innerSlice.items.some(
559
+
item => item.post.viewer?.replyDisabled === true,
560
+
)
561
+
})
562
+
return slice.slices.length > 0
563
+
} else {
564
+
// For regular slices, check if any item has replyDisabled
565
+
return !slice.items.some(
566
+
item => item.post.viewer?.replyDisabled === true,
567
+
)
568
+
}
569
+
})
570
+
}
571
+
549
572
for (const slice of slices) {
550
573
sliceIndex++
551
574
···
722
745
hasPressedShowLessUris,
723
746
ageAssuranceBannerState,
724
747
isCurrentFeedAtStartupSelected,
748
+
hideUnreplyablePosts,
725
749
])
726
750
727
751
// events