mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
at utm-source 211 lines 5.9 kB view raw
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 ? _(msg`Undo repost`) 68 : _(msg({message: 'Repost', context: 'action'})) 69 } (${plural(repostCount || 0, {one: '# repost', other: '# reposts'})})`} 70 shape="round" 71 variant="ghost" 72 color="secondary" 73 hitSlop={POST_CTRL_HITSLOP}> 74 <Repost style={color} width={big ? 22 : 18} /> 75 {typeof repostCount !== 'undefined' && repostCount > 0 ? ( 76 <Text 77 testID="repostCount" 78 style={[ 79 color, 80 big ? a.text_md : {fontSize: 15}, 81 isReposted && a.font_bold, 82 ]}> 83 {formatCount(i18n, repostCount)} 84 </Text> 85 ) : undefined} 86 </Button> 87 <Dialog.Outer 88 control={dialogControl} 89 nativeOptions={{preventExpansion: true}}> 90 <Dialog.Handle /> 91 <RepostButtonDialogInner 92 isReposted={isReposted} 93 onRepost={onRepost} 94 onQuote={onQuote} 95 embeddingDisabled={embeddingDisabled} 96 /> 97 </Dialog.Outer> 98 </> 99 ) 100} 101RepostButton = memo(RepostButton) 102export {RepostButton} 103 104let RepostButtonDialogInner = ({ 105 isReposted, 106 onRepost, 107 onQuote, 108 embeddingDisabled, 109}: { 110 isReposted: boolean 111 onRepost: () => void 112 onQuote: () => void 113 embeddingDisabled: boolean 114}): React.ReactNode => { 115 const t = useTheme() 116 const {_} = useLingui() 117 const playHaptic = useHaptics() 118 const control = Dialog.useDialogContext() 119 120 const onPressRepost = useCallback(() => { 121 if (!isReposted) playHaptic() 122 123 control.close(() => { 124 onRepost() 125 }) 126 }, [control, isReposted, onRepost, playHaptic]) 127 128 const onPressQuote = useCallback(() => { 129 playHaptic() 130 control.close(() => { 131 onQuote() 132 }) 133 }, [control, onQuote, playHaptic]) 134 135 const onPressClose = useCallback(() => control.close(), [control]) 136 137 return ( 138 <Dialog.ScrollableInner label={_(msg`Repost or quote post`)}> 139 <View style={a.gap_xl}> 140 <View style={a.gap_xs}> 141 <Button 142 style={[a.justify_start, a.px_md]} 143 label={ 144 isReposted 145 ? _(msg`Remove repost`) 146 : _(msg({message: `Repost`, context: 'action'})) 147 } 148 onPress={onPressRepost} 149 size="large" 150 variant="ghost" 151 color="primary"> 152 <Repost size="lg" fill={t.palette.primary_500} /> 153 <Text style={[a.font_bold, a.text_xl]}> 154 {isReposted ? ( 155 <Trans>Remove repost</Trans> 156 ) : ( 157 <Trans context="action">Repost</Trans> 158 )} 159 </Text> 160 </Button> 161 <Button 162 disabled={embeddingDisabled} 163 testID="quoteBtn" 164 style={[a.justify_start, a.px_md]} 165 label={ 166 embeddingDisabled 167 ? _(msg`Quote posts disabled`) 168 : _(msg`Quote post`) 169 } 170 onPress={onPressQuote} 171 size="large" 172 variant="ghost" 173 color="primary"> 174 <Quote 175 size="lg" 176 fill={ 177 embeddingDisabled 178 ? t.atoms.text_contrast_low.color 179 : t.palette.primary_500 180 } 181 /> 182 <Text 183 style={[ 184 a.font_bold, 185 a.text_xl, 186 embeddingDisabled && t.atoms.text_contrast_low, 187 ]}> 188 {embeddingDisabled ? ( 189 <Trans>Quote posts disabled</Trans> 190 ) : ( 191 <Trans>Quote post</Trans> 192 )} 193 </Text> 194 </Button> 195 </View> 196 <Button 197 label={_(msg`Cancel quote post`)} 198 onPress={onPressClose} 199 size="large" 200 variant="outline" 201 color="primary"> 202 <ButtonText> 203 <Trans>Cancel</Trans> 204 </ButtonText> 205 </Button> 206 </View> 207 </Dialog.ScrollableInner> 208 ) 209} 210RepostButtonDialogInner = memo(RepostButtonDialogInner) 211export {RepostButtonDialogInner}