Bluesky app fork with some witchin' additions 馃挮
at feat/tealfm 160 lines 5.0 kB view raw
1import {View} from 'react-native' 2import {Image} from 'expo-image' 3import {type AppBskyGraphDefs} from '@atproto/api' 4import {msg, Trans} from '@lingui/macro' 5import {useLingui} from '@lingui/react' 6 7import {useSaveImageToMediaLibrary} from '#/lib/media/save-image' 8import {shareUrl} from '#/lib/sharing' 9import {getStarterPackOgCard} from '#/lib/strings/starter-pack' 10import {atoms as a, useBreakpoints, useTheme} from '#/alf' 11import {Button, ButtonIcon, ButtonText} from '#/components/Button' 12import {type DialogControlProps} from '#/components/Dialog' 13import * as Dialog from '#/components/Dialog' 14import {ChainLink_Stroke2_Corner0_Rounded as ChainLinkIcon} from '#/components/icons/ChainLink' 15import {Download_Stroke2_Corner0_Rounded as DownloadIcon} from '#/components/icons/Download' 16import {QrCode_Stroke2_Corner0_Rounded as QrCodeIcon} from '#/components/icons/QrCode' 17import {Loader} from '#/components/Loader' 18import {Text} from '#/components/Typography' 19import {useAnalytics} from '#/analytics' 20import {IS_NATIVE, IS_WEB} from '#/env' 21 22interface Props { 23 starterPack: AppBskyGraphDefs.StarterPackView 24 link?: string 25 imageLoaded?: boolean 26 qrDialogControl: DialogControlProps 27 control: DialogControlProps 28} 29 30export function ShareDialog(props: Props) { 31 return ( 32 <Dialog.Outer 33 control={props.control} 34 nativeOptions={{preventExpansion: true}}> 35 <Dialog.Handle /> 36 <ShareDialogInner {...props} /> 37 </Dialog.Outer> 38 ) 39} 40 41function ShareDialogInner({ 42 starterPack, 43 link, 44 imageLoaded, 45 qrDialogControl, 46 control, 47}: Props) { 48 const {_} = useLingui() 49 const ax = useAnalytics() 50 const t = useTheme() 51 const {gtMobile} = useBreakpoints() 52 53 const imageUrl = getStarterPackOgCard(starterPack) 54 55 const onShareLink = async () => { 56 if (!link) return 57 shareUrl(link) 58 ax.metric('starterPack:share', { 59 starterPack: starterPack.uri, 60 shareType: 'link', 61 }) 62 control.close() 63 } 64 65 const saveImageToAlbum = useSaveImageToMediaLibrary() 66 67 const onSave = async () => { 68 await saveImageToAlbum(imageUrl) 69 } 70 71 return ( 72 <> 73 <Dialog.ScrollableInner label={_(msg`Share link dialog`)}> 74 {!imageLoaded || !link ? ( 75 <View style={[a.align_center, a.justify_center, {minHeight: 350}]}> 76 <Loader size="xl" /> 77 </View> 78 ) : ( 79 <View style={[!gtMobile && a.gap_lg]}> 80 <View style={[a.gap_sm, gtMobile && a.pb_lg]}> 81 <Text style={[a.font_semi_bold, a.text_2xl]}> 82 <Trans>Invite people to this starter pack!</Trans> 83 </Text> 84 <Text style={[a.text_md, t.atoms.text_contrast_medium]}> 85 <Trans> 86 Share this starter pack and help people join your community on 87 Bluesky. 88 </Trans> 89 </Text> 90 </View> 91 <Image 92 source={{uri: imageUrl}} 93 style={[ 94 a.rounded_sm, 95 a.aspect_card, 96 { 97 transform: [{scale: gtMobile ? 0.85 : 1}], 98 marginTop: gtMobile ? -20 : 0, 99 }, 100 ]} 101 accessibilityIgnoresInvertColors={true} 102 /> 103 <View 104 style={[ 105 a.gap_md, 106 gtMobile && [ 107 a.gap_sm, 108 a.justify_center, 109 a.flex_row, 110 a.flex_wrap, 111 ], 112 ]}> 113 <Button 114 label={IS_WEB ? _(msg`Copy link`) : _(msg`Share link`)} 115 color="primary_subtle" 116 size="large" 117 onPress={onShareLink}> 118 <ButtonIcon icon={ChainLinkIcon} /> 119 <ButtonText> 120 {IS_WEB ? ( 121 <Trans>Copy Link</Trans> 122 ) : ( 123 <Trans>Share link</Trans> 124 )} 125 </ButtonText> 126 </Button> 127 <Button 128 label={_(msg`Share QR code`)} 129 color="primary_subtle" 130 size="large" 131 onPress={() => { 132 control.close(() => { 133 qrDialogControl.open() 134 }) 135 }}> 136 <ButtonIcon icon={QrCodeIcon} /> 137 <ButtonText> 138 <Trans>Share QR code</Trans> 139 </ButtonText> 140 </Button> 141 {IS_NATIVE && ( 142 <Button 143 label={_(msg`Save image`)} 144 color="secondary" 145 size="large" 146 onPress={onSave}> 147 <ButtonIcon icon={DownloadIcon} /> 148 <ButtonText> 149 <Trans>Save image</Trans> 150 </ButtonText> 151 </Button> 152 )} 153 </View> 154 </View> 155 )} 156 <Dialog.Close /> 157 </Dialog.ScrollableInner> 158 </> 159 ) 160}