mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import React, {memo, useCallback} from 'react' 2import {View} from 'react-native' 3import {msg, plural, Trans} from '@lingui/macro' 4import {useLingui} from '@lingui/react' 5 6import {POST_CTRL_HITSLOP} from '#/lib/constants' 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 Quote} from '#/components/icons/Quote' 13import {Repost_Stroke2_Corner2_Rounded as Repost} from '#/components/icons/Repost' 14import {Text} from '#/components/Typography' 15import {formatCount} from '../numeric/format' 16 17interface Props { 18 isReposted: boolean 19 repostCount?: number 20 onRepost: () => void 21 onQuote: () => void 22 big?: boolean 23 embeddingDisabled: boolean 24} 25 26let RepostButton = ({ 27 isReposted, 28 repostCount, 29 onRepost, 30 onQuote, 31 big, 32 embeddingDisabled, 33}: Props): React.ReactNode => { 34 const t = useTheme() 35 const {_, i18n} = useLingui() 36 const requireAuth = useRequireAuth() 37 const dialogControl = Dialog.useDialogControl() 38 const playHaptic = useHaptics() 39 const color = React.useMemo( 40 () => ({ 41 color: isReposted ? t.palette.positive_600 : t.palette.contrast_500, 42 }), 43 [t, isReposted], 44 ) 45 return ( 46 <> 47 <Button 48 testID="repostBtn" 49 onPress={() => { 50 playHaptic('Light') 51 requireAuth(() => dialogControl.open()) 52 }} 53 onLongPress={() => { 54 playHaptic('Heavy') 55 requireAuth(() => onQuote()) 56 }} 57 style={[ 58 a.flex_row, 59 a.align_center, 60 a.gap_xs, 61 a.bg_transparent, 62 {padding: 5}, 63 ]} 64 hoverStyle={t.atoms.bg_contrast_25} 65 label={ 66 isReposted 67 ? _( 68 msg`Undo repost (${plural(repostCount || 0, { 69 one: '# repost', 70 other: '# reposts', 71 })})`, 72 ) 73 : _( 74 msg`Repost (${plural(repostCount || 0, { 75 one: '# repost', 76 other: '# reposts', 77 })})`, 78 ) 79 } 80 shape="round" 81 variant="ghost" 82 color="secondary" 83 hitSlop={POST_CTRL_HITSLOP}> 84 <Repost style={color} width={big ? 22 : 18} /> 85 {typeof repostCount !== 'undefined' && repostCount > 0 ? ( 86 <Text 87 testID="repostCount" 88 style={[ 89 color, 90 big ? a.text_md : {fontSize: 15}, 91 isReposted && a.font_bold, 92 ]}> 93 {formatCount(i18n, repostCount)} 94 </Text> 95 ) : undefined} 96 </Button> 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 </> 109 ) 110} 111RepostButton = memo(RepostButton) 112export {RepostButton} 113 114let 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]} 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 <Repost size="lg" fill={t.palette.primary_500} /> 163 <Text style={[a.font_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]} 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 <Quote 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_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 variant="outline" 211 color="primary"> 212 <ButtonText> 213 <Trans>Cancel</Trans> 214 </ButtonText> 215 </Button> 216 </View> 217 </Dialog.ScrollableInner> 218 ) 219} 220RepostButtonDialogInner = memo(RepostButtonDialogInner) 221export {RepostButtonDialogInner}