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 {logger} from '#/logger'
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 {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 t = useTheme()
50 const {gtMobile} = useBreakpoints()
51
52 const imageUrl = getStarterPackOgCard(starterPack)
53
54 const onShareLink = async () => {
55 if (!link) return
56 shareUrl(link)
57 logger.metric('starterPack:share', {
58 starterPack: starterPack.uri,
59 shareType: 'link',
60 })
61 control.close()
62 }
63
64 const saveImageToAlbum = useSaveImageToMediaLibrary()
65
66 const onSave = async () => {
67 await saveImageToAlbum(imageUrl)
68 }
69
70 return (
71 <>
72 <Dialog.ScrollableInner label={_(msg`Share link dialog`)}>
73 {!imageLoaded || !link ? (
74 <View style={[a.align_center, a.justify_center, {minHeight: 350}]}>
75 <Loader size="xl" />
76 </View>
77 ) : (
78 <View style={[!gtMobile && a.gap_lg]}>
79 <View style={[a.gap_sm, gtMobile && a.pb_lg]}>
80 <Text style={[a.font_semi_bold, a.text_2xl]}>
81 <Trans>Invite people to this starter pack!</Trans>
82 </Text>
83 <Text style={[a.text_md, t.atoms.text_contrast_medium]}>
84 <Trans>
85 Share this starter pack and help people join your community on
86 Bluesky.
87 </Trans>
88 </Text>
89 </View>
90 <Image
91 source={{uri: imageUrl}}
92 style={[
93 a.rounded_sm,
94 a.aspect_card,
95 {
96 transform: [{scale: gtMobile ? 0.85 : 1}],
97 marginTop: gtMobile ? -20 : 0,
98 },
99 ]}
100 accessibilityIgnoresInvertColors={true}
101 />
102 <View
103 style={[
104 a.gap_md,
105 gtMobile && [
106 a.gap_sm,
107 a.justify_center,
108 a.flex_row,
109 a.flex_wrap,
110 ],
111 ]}>
112 <Button
113 label={IS_WEB ? _(msg`Copy link`) : _(msg`Share link`)}
114 color="primary_subtle"
115 size="large"
116 onPress={onShareLink}>
117 <ButtonIcon icon={ChainLinkIcon} />
118 <ButtonText>
119 {IS_WEB ? (
120 <Trans>Copy Link</Trans>
121 ) : (
122 <Trans>Share link</Trans>
123 )}
124 </ButtonText>
125 </Button>
126 <Button
127 label={_(msg`Share QR code`)}
128 color="primary_subtle"
129 size="large"
130 onPress={() => {
131 control.close(() => {
132 qrDialogControl.open()
133 })
134 }}>
135 <ButtonIcon icon={QrCodeIcon} />
136 <ButtonText>
137 <Trans>Share QR code</Trans>
138 </ButtonText>
139 </Button>
140 {IS_NATIVE && (
141 <Button
142 label={_(msg`Save image`)}
143 color="secondary"
144 size="large"
145 onPress={onSave}>
146 <ButtonIcon icon={DownloadIcon} />
147 <ButtonText>
148 <Trans>Save image</Trans>
149 </ButtonText>
150 </Button>
151 )}
152 </View>
153 </View>
154 )}
155 <Dialog.Close />
156 </Dialog.ScrollableInner>
157 </>
158 )
159}