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 218 lines 6.4 kB view raw
1import {memo, useCallback} from 'react' 2import {View} from 'react-native' 3import {msg, plural} from '@lingui/core/macro' 4import {useLingui} from '@lingui/react' 5import {Trans} from '@lingui/react/macro' 6 7import {useHaptics} from '#/lib/haptics' 8import {useRequireAuth} from '#/state/session' 9import {atoms as a, useTheme} from '#/alf' 10import {Button, ButtonText} from '#/components/Button' 11import * as Dialog from '#/components/Dialog' 12import {CloseQuote_Stroke2_Corner1_Rounded as QuoteIcon} from '#/components/icons/Quote' 13import {Repost_Stroke2_Corner3_Rounded as RepostIcon} from '#/components/icons/Repost' 14import {useFormatPostStatCount} from '#/components/PostControls/util' 15import {Text} from '#/components/Typography' 16import { 17 PostControlButton, 18 PostControlButtonIcon, 19 PostControlButtonText, 20} from './PostControlButton' 21 22interface Props { 23 isReposted: boolean 24 repostCount?: number 25 onRepost: () => void 26 onQuote: () => void 27 onLongPress?: () => void 28 big?: boolean 29 embeddingDisabled: boolean 30} 31 32let RepostButton = ({ 33 isReposted, 34 repostCount, 35 onRepost, 36 onQuote, 37 onLongPress, 38 big, 39 embeddingDisabled, 40}: Props): React.ReactNode => { 41 const t = useTheme() 42 const {_} = useLingui() 43 const requireAuth = useRequireAuth() 44 const dialogControl = Dialog.useDialogControl() 45 const formatPostStatCount = useFormatPostStatCount() 46 47 const onPress = () => requireAuth(() => dialogControl.open()) 48 49 const onDefaultLongPress = () => 50 requireAuth(() => { 51 if (embeddingDisabled) { 52 dialogControl.open() 53 } else { 54 onQuote() 55 } 56 }) 57 58 return ( 59 <View> 60 <PostControlButton 61 testID="repostBtn" 62 active={isReposted} 63 activeColor={t.palette.positive_500} 64 big={big} 65 onPress={onPress} 66 onLongPress={onLongPress ?? onDefaultLongPress} 67 label={ 68 isReposted 69 ? _( 70 msg({ 71 message: `Undo repost (${plural(repostCount || 0, { 72 one: '# repost', 73 other: '# reposts', 74 })})`, 75 comment: 76 'Accessibility label for the repost button when the post has been reposted, verb followed by number of reposts and noun', 77 }), 78 ) 79 : _( 80 msg({ 81 message: `Repost (${plural(repostCount || 0, { 82 one: '# repost', 83 other: '# reposts', 84 })})`, 85 comment: 86 'Accessibility label for the repost button when the post has not been reposted, verb form followed by number of reposts and noun form', 87 }), 88 ) 89 }> 90 <PostControlButtonIcon icon={RepostIcon} /> 91 {typeof repostCount !== 'undefined' && repostCount > 0 && ( 92 <PostControlButtonText testID="repostCount"> 93 {formatPostStatCount(repostCount)} 94 </PostControlButtonText> 95 )} 96 </PostControlButton> 97 <Dialog.Outer 98 control={dialogControl} 99 nativeOptions={{preventExpansion: true}}> 100 <Dialog.Handle /> 101 <RepostButtonDialogInner 102 isReposted={isReposted} 103 onRepost={onRepost} 104 onQuote={onQuote} 105 embeddingDisabled={embeddingDisabled} 106 /> 107 </Dialog.Outer> 108 </View> 109 ) 110} 111RepostButton = memo(RepostButton) 112export {RepostButton} 113 114export const RepostButtonDialogInner = memo(function RepostButtonDialogInner({ 115 isReposted, 116 onRepost, 117 onQuote, 118 embeddingDisabled, 119}: { 120 isReposted: boolean 121 onRepost: () => void 122 onQuote: () => void 123 embeddingDisabled: boolean 124}): React.ReactNode { 125 const t = useTheme() 126 const {_} = useLingui() 127 const playHaptic = useHaptics() 128 const control = Dialog.useDialogContext() 129 130 const onPressRepost = useCallback(() => { 131 if (!isReposted) playHaptic() 132 133 control.close(() => { 134 onRepost() 135 }) 136 }, [control, isReposted, onRepost, playHaptic]) 137 138 const onPressQuote = useCallback(() => { 139 playHaptic() 140 control.close(() => { 141 onQuote() 142 }) 143 }, [control, onQuote, playHaptic]) 144 145 const onPressClose = useCallback(() => control.close(), [control]) 146 147 return ( 148 <Dialog.ScrollableInner label={_(msg`Repost or quote post`)}> 149 <View style={a.gap_xl}> 150 <View style={a.gap_xs}> 151 <Button 152 style={[a.justify_start, a.px_md, a.gap_sm]} 153 label={ 154 isReposted 155 ? _(msg`Remove repost`) 156 : _(msg({message: `Repost`, context: 'action'})) 157 } 158 onPress={onPressRepost} 159 size="large" 160 variant="ghost" 161 color="primary"> 162 <RepostIcon size="lg" fill={t.palette.primary_500} /> 163 <Text style={[a.font_semi_bold, a.text_xl]}> 164 {isReposted ? ( 165 <Trans>Remove repost</Trans> 166 ) : ( 167 <Trans context="action">Repost</Trans> 168 )} 169 </Text> 170 </Button> 171 <Button 172 disabled={embeddingDisabled} 173 testID="quoteBtn" 174 style={[a.justify_start, a.px_md, a.gap_sm]} 175 label={ 176 embeddingDisabled 177 ? _(msg`Quote posts disabled`) 178 : _(msg`Quote post`) 179 } 180 onPress={onPressQuote} 181 size="large" 182 variant="ghost" 183 color="primary"> 184 <QuoteIcon 185 size="lg" 186 fill={ 187 embeddingDisabled 188 ? t.atoms.text_contrast_low.color 189 : t.palette.primary_500 190 } 191 /> 192 <Text 193 style={[ 194 a.font_semi_bold, 195 a.text_xl, 196 embeddingDisabled && t.atoms.text_contrast_low, 197 ]}> 198 {embeddingDisabled ? ( 199 <Trans>Quote posts disabled</Trans> 200 ) : ( 201 <Trans>Quote post</Trans> 202 )} 203 </Text> 204 </Button> 205 </View> 206 <Button 207 label={_(msg`Cancel quote post`)} 208 onPress={onPressClose} 209 size="large" 210 color="secondary"> 211 <ButtonText> 212 <Trans>Cancel</Trans> 213 </ButtonText> 214 </Button> 215 </View> 216 </Dialog.ScrollableInner> 217 ) 218})