Bluesky app fork with some witchin' additions 馃挮
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at cope-settings-sync 173 lines 5.5 kB view raw
1import {type StyleProp, Text as RNText, type TextStyle} from 'react-native' 2import {msg} from '@lingui/core/macro' 3import {useLingui} from '@lingui/react' 4import {Trans} from '@lingui/react/macro' 5import {useNavigation} from '@react-navigation/native' 6 7import {type NavigationProp} from '#/lib/routes/types' 8import {isInvalidHandle} from '#/lib/strings/handles' 9import { 10 usePreferencesQuery, 11 useRemoveMutedWordsMutation, 12 useUpsertMutedWordsMutation, 13} from '#/state/queries/preferences' 14import {MagnifyingGlass_Stroke2_Corner0_Rounded as Search} from '#/components/icons/MagnifyingGlass' 15import {Mute_Stroke2_Corner0_Rounded as Mute} from '#/components/icons/Mute' 16import {Person_Stroke2_Corner0_Rounded as Person} from '#/components/icons/Person' 17import { 18 createStaticClick, 19 createStaticClickIfUnmodified, 20 InlineLinkText, 21} from '#/components/Link' 22import {Loader} from '#/components/Loader' 23import * as Menu from '#/components/Menu' 24import {IS_NATIVE, IS_WEB} from '#/env' 25 26export function RichTextTag({ 27 tag, 28 display, 29 authorHandle, 30 textStyle, 31}: { 32 tag: string 33 display: string 34 authorHandle?: string 35 textStyle: StyleProp<TextStyle> 36}) { 37 const {_} = useLingui() 38 const {isLoading: isPreferencesLoading, data: preferences} = 39 usePreferencesQuery() 40 const { 41 mutateAsync: upsertMutedWord, 42 variables: optimisticUpsert, 43 reset: resetUpsert, 44 } = useUpsertMutedWordsMutation() 45 const { 46 mutateAsync: removeMutedWords, 47 variables: optimisticRemove, 48 reset: resetRemove, 49 } = useRemoveMutedWordsMutation() 50 const navigation = useNavigation<NavigationProp>() 51 const isCashtag = tag.startsWith('$') 52 const label = isCashtag ? _(msg`Cashtag ${tag}`) : _(msg`Hashtag ${tag}`) 53 const hint = IS_NATIVE 54 ? _(msg`Long press to open tag menu for ${isCashtag ? tag : `#${tag}`}`) 55 : _(msg`Click to open tag menu for ${isCashtag ? tag : `#${tag}`}`) 56 57 const isMuted = Boolean( 58 (preferences?.moderationPrefs.mutedWords?.find( 59 m => m.value === tag && m.targets.includes('tag'), 60 ) ?? 61 optimisticUpsert?.find( 62 m => m.value === tag && m.targets.includes('tag'), 63 )) && 64 !optimisticRemove?.find(m => m?.value === tag), 65 ) 66 67 /* 68 * Mute word records that exactly match the tag in question. 69 */ 70 const removeableMuteWords = 71 preferences?.moderationPrefs.mutedWords?.filter(word => { 72 return word.value === tag 73 }) || [] 74 75 return ( 76 <Menu.Root> 77 <Menu.Trigger label={label} hint={hint}> 78 {({props: menuProps}) => ( 79 <InlineLinkText 80 to={{ 81 screen: 'Hashtag', 82 params: {tag: encodeURIComponent(tag)}, 83 }} 84 {...menuProps} 85 onPress={e => { 86 if (IS_WEB) { 87 return createStaticClickIfUnmodified(() => { 88 if (!IS_NATIVE) { 89 menuProps.onPress() 90 } 91 }).onPress(e) 92 } 93 }} 94 onLongPress={createStaticClick(menuProps.onPress).onPress} 95 accessibilityHint={hint} 96 label={label} 97 style={textStyle} 98 emoji> 99 {IS_NATIVE ? ( 100 display 101 ) : ( 102 <RNText ref={menuProps.ref}>{display}</RNText> 103 )} 104 </InlineLinkText> 105 )} 106 </Menu.Trigger> 107 <Menu.Outer> 108 <Menu.Group> 109 <Menu.Item 110 label={_(msg`See ${isCashtag ? tag : `#${tag}`} posts`)} 111 onPress={() => { 112 navigation.push('Hashtag', { 113 tag: encodeURIComponent(tag), 114 }) 115 }}> 116 <Menu.ItemText> 117 {isCashtag ? ( 118 <Trans>See {tag} posts</Trans> 119 ) : ( 120 <Trans>See #{tag} posts</Trans> 121 )} 122 </Menu.ItemText> 123 <Menu.ItemIcon icon={Search} /> 124 </Menu.Item> 125 {authorHandle && !isInvalidHandle(authorHandle) && ( 126 <Menu.Item 127 label={_(msg`See ${isCashtag ? tag : `#${tag}`} posts by user`)} 128 onPress={() => { 129 navigation.push('Hashtag', { 130 tag: encodeURIComponent(tag), 131 author: authorHandle, 132 }) 133 }}> 134 <Menu.ItemText> 135 {isCashtag ? ( 136 <Trans>See {tag} posts by user</Trans> 137 ) : ( 138 <Trans>See #{tag} posts by user</Trans> 139 )} 140 </Menu.ItemText> 141 <Menu.ItemIcon icon={Person} /> 142 </Menu.Item> 143 )} 144 </Menu.Group> 145 <Menu.Divider /> 146 <Menu.Item 147 label={ 148 isMuted 149 ? _(msg`Unmute ${isCashtag ? tag : `#${tag}`}`) 150 : _(msg`Mute ${isCashtag ? tag : `#${tag}`}`) 151 } 152 onPress={() => { 153 if (isMuted) { 154 resetUpsert() 155 removeMutedWords(removeableMuteWords) 156 } else { 157 resetRemove() 158 upsertMutedWord([ 159 {value: tag, targets: ['tag'], actorTarget: 'all'}, 160 ]) 161 } 162 }}> 163 <Menu.ItemText> 164 {isMuted 165 ? _(msg`Unmute ${isCashtag ? tag : `#${tag}`}`) 166 : _(msg`Mute ${isCashtag ? tag : `#${tag}`}`)} 167 </Menu.ItemText> 168 <Menu.ItemIcon icon={isPreferencesLoading ? Loader : Mute} /> 169 </Menu.Item> 170 </Menu.Outer> 171 </Menu.Root> 172 ) 173}