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