forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
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}