Bluesky app fork with some witchin' additions ๐Ÿ’ซ witchsky.app
bluesky fork client

Add toggle to hide posts that can't be replied to from feeds #25

merged opened by maxine.puppykitty.racing targeting main

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.

Labels

None yet.

assignee

None yet.

Participants 2
AT URI
at://did:plc:nmc77zslrwafxn75j66mep6o/sh.tangled.repo.pull/3m7inw3wdo322
+112 -7
Diff #0
+25
src/screens/Settings/DeerSettings.tsx
··· 88 useHideSimilarAccountsRecomm, 89 useSetHideSimilarAccountsRecomm, 90 } from '#/state/preferences/hide-similar-accounts-recommendations' 91 import { 92 useHighQualityImages, 93 useSetHighQualityImages, ··· 443 const hideSimilarAccountsRecomm = useHideSimilarAccountsRecomm() 444 const setHideSimilarAccountsRecomm = useSetHideSimilarAccountsRecomm() 445 446 const disableVerifyEmailReminder = useDisableVerifyEmailReminder() 447 const setDisableVerifyEmailReminder = useSetDisableVerifyEmailReminder() 448 ··· 742 <Toggle.Platform /> 743 </Toggle.Item> 744 745 <Toggle.Item 746 name="disable_verify_email_reminder" 747 label={_(msg`Disable verify email reminder`)}
··· 88 useHideSimilarAccountsRecomm, 89 useSetHideSimilarAccountsRecomm, 90 } from '#/state/preferences/hide-similar-accounts-recommendations' 91 + import { 92 + useHideUnreplyablePosts, 93 + useSetHideUnreplyablePosts, 94 + } from '#/state/preferences/hide-unreplyable-posts' 95 import { 96 useHighQualityImages, 97 useSetHighQualityImages, ··· 447 const hideSimilarAccountsRecomm = useHideSimilarAccountsRecomm() 448 const setHideSimilarAccountsRecomm = useSetHideSimilarAccountsRecomm() 449 450 + const hideUnreplyablePosts = useHideUnreplyablePosts() 451 + const setHideUnreplyablePosts = useSetHideUnreplyablePosts() 452 + 453 const disableVerifyEmailReminder = useDisableVerifyEmailReminder() 454 const setDisableVerifyEmailReminder = useSetDisableVerifyEmailReminder() 455 ··· 749 <Toggle.Platform /> 750 </Toggle.Item> 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 + 770 <Toggle.Item 771 name="disable_verify_email_reminder" 772 label={_(msg`Disable verify email reminder`)}
+2
src/state/persisted/schema.ts
··· 166 }) 167 .optional(), 168 highQualityImages: z.boolean().optional(), 169 170 showExternalShareButtons: z.boolean().optional(), 171 ··· 269 ], 270 }, 271 highQualityImages: false, 272 showExternalShareButtons: false, 273 } 274
··· 166 }) 167 .optional(), 168 highQualityImages: z.boolean().optional(), 169 + hideUnreplyablePosts: z.boolean().optional(), 170 171 showExternalShareButtons: z.boolean().optional(), 172 ··· 270 ], 271 }, 272 highQualityImages: false, 273 + hideUnreplyablePosts: false, 274 showExternalShareButtons: false, 275 } 276
+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
··· 26 import {Provider as HiddenPostsProvider} from './hidden-posts' 27 import {Provider as HideFeedsPromoTabProvider} from './hide-feeds-promo-tab' 28 import {Provider as HideSimilarAccountsRecommProvider} from './hide-similar-accounts-recommendations' 29 import {Provider as HighQualityImagesProvider} from './high-quality-images' 30 import {Provider as InAppBrowserProvider} from './in-app-browser' 31 import {Provider as KawaiiProvider} from './kawaii' ··· 96 <DisableFollowedByMetricsProvider> 97 <DisablePostsMetricsProvider> 98 <HideSimilarAccountsRecommProvider> 99 - <EnableSquareAvatarsProvider> 100 - <EnableSquareButtonsProvider> 101 - <DisableVerifyEmailReminderProvider> 102 - {children} 103 - </DisableVerifyEmailReminderProvider> 104 - </EnableSquareButtonsProvider> 105 - </EnableSquareAvatarsProvider> 106 </HideSimilarAccountsRecommProvider> 107 </DisablePostsMetricsProvider> 108 </DisableFollowedByMetricsProvider>
··· 26 import {Provider as HiddenPostsProvider} from './hidden-posts' 27 import {Provider as HideFeedsPromoTabProvider} from './hide-feeds-promo-tab' 28 import {Provider as HideSimilarAccountsRecommProvider} from './hide-similar-accounts-recommendations' 29 + import {Provider as HideUnreplyablePostsProvider} from './hide-unreplyable-posts' 30 import {Provider as HighQualityImagesProvider} from './high-quality-images' 31 import {Provider as InAppBrowserProvider} from './in-app-browser' 32 import {Provider as KawaiiProvider} from './kawaii' ··· 97 <DisableFollowedByMetricsProvider> 98 <DisablePostsMetricsProvider> 99 <HideSimilarAccountsRecommProvider> 100 + <HideUnreplyablePostsProvider> 101 + <EnableSquareAvatarsProvider> 102 + <EnableSquareButtonsProvider> 103 + <DisableVerifyEmailReminderProvider> 104 + {children} 105 + </DisableVerifyEmailReminderProvider> 106 + </EnableSquareButtonsProvider> 107 + </EnableSquareAvatarsProvider> 108 + </HideUnreplyablePostsProvider> 109 </HideSimilarAccountsRecommProvider> 110 </DisablePostsMetricsProvider> 111 </DisableFollowedByMetricsProvider>
+24
src/view/com/posts/PostFeed.tsx
··· 37 import {isIOS, isNative, isWeb} from '#/platform/detection' 38 import {listenPostCreated} from '#/state/events' 39 import {useFeedFeedbackContext} from '#/state/feed-feedback' 40 import {useRepostCarouselEnabled} from '#/state/preferences/repost-carousel-enabled' 41 import {useTrendingSettings} from '#/state/preferences/trending' 42 import {STALE} from '#/state/queries' ··· 426 const {trendingDisabled, trendingVideoDisabled} = useTrendingSettings() 427 428 const repostCarouselEnabled = useRepostCarouselEnabled() 429 430 if (feedType === 'following') { 431 useRepostCarousel = repostCarouselEnabled ··· 546 ? groupReposts(page.slices) 547 : (page.slices as FeedPostSliceOrGroup[]) 548 549 for (const slice of slices) { 550 sliceIndex++ 551 ··· 722 hasPressedShowLessUris, 723 ageAssuranceBannerState, 724 isCurrentFeedAtStartupSelected, 725 ]) 726 727 // events
··· 37 import {isIOS, isNative, isWeb} from '#/platform/detection' 38 import {listenPostCreated} from '#/state/events' 39 import {useFeedFeedbackContext} from '#/state/feed-feedback' 40 + import {useHideUnreplyablePosts} from '#/state/preferences/hide-unreplyable-posts' 41 import {useRepostCarouselEnabled} from '#/state/preferences/repost-carousel-enabled' 42 import {useTrendingSettings} from '#/state/preferences/trending' 43 import {STALE} from '#/state/queries' ··· 427 const {trendingDisabled, trendingVideoDisabled} = useTrendingSettings() 428 429 const repostCarouselEnabled = useRepostCarouselEnabled() 430 + const hideUnreplyablePosts = useHideUnreplyablePosts() 431 432 if (feedType === 'following') { 433 useRepostCarousel = repostCarouselEnabled ··· 548 ? groupReposts(page.slices) 549 : (page.slices as FeedPostSliceOrGroup[]) 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 + 572 for (const slice of slices) { 573 sliceIndex++ 574 ··· 745 hasPressedShowLessUris, 746 ageAssuranceBannerState, 747 isCurrentFeedAtStartupSelected, 748 + hideUnreplyablePosts, 749 ]) 750 751 // events

History

2 rounds 1 comment
sign up or login to add to the discussion
1 commit
expand
71dfc225
feat: hide unreplyable posts
expand 0 comments
pull request successfully merged
1 commit
expand
fa923170
feat: hide unreplyable posts
expand 1 comment

can confirm this works