handle saving viewshot

This commit is contained in:
Hailey
2024-06-11 22:25:43 -07:00
parent ad1c34e7be
commit 23de3d754e
2 changed files with 55 additions and 87 deletions
+45 -76
View File
@@ -12,11 +12,14 @@ import {useTheme} from '#/alf'
import {atoms as a} from '#/alf' import {atoms as a} from '#/alf'
import {Text} from '#/components/Typography' import {Text} from '#/components/Typography'
export function QrCode({ interface Props {
starterPack,
}: {
starterPack: AppBskyGraphDefs.StarterPackView starterPack: AppBskyGraphDefs.StarterPackView
}) { }
export const QrCode = React.forwardRef<ViewShot, Props>(function QrCode(
{starterPack},
ref,
) {
const t = useTheme() const t = useTheme()
const {record} = starterPack const {record} = starterPack
@@ -30,50 +33,18 @@ export function QrCode({
} }
return ( return (
<ViewShot> <ViewShot ref={ref}>
<LinearGradient <LinearGradient
colors={gradient} colors={gradient}
style={[ style={[
{width: 300, height: 440}, //😎 {width: 300, height: 440},
a.align_center, a.align_center,
a.px_sm, a.px_sm,
a.py_5xl, a.py_xl,
a.rounded_sm, a.rounded_sm,
a.justify_between, a.justify_between,
a.gap_md,
]}> ]}>
<View
style={[
a.absolute,
a.z_20,
{
top: 0,
left: 'auto',
right: 'auto',
height: 24,
width: 48,
borderBottomLeftRadius: 100,
borderBottomRightRadius: 100,
backgroundColor: 'transparent',
},
]}
/>
<View
style={[
a.absolute,
a.z_20,
{
bottom: 0,
left: 'auto',
right: 'auto',
height: 24,
width: 48,
borderTopLeftRadius: 100,
borderTopRightRadius: 100,
backgroundColor: 'transparent',
},
]}
/>
<View style={[a.gap_sm]}> <View style={[a.gap_sm]}>
<Text <Text
style={[a.font_bold, a.text_3xl, a.text_center, {color: 'white'}]}> style={[a.font_bold, a.text_3xl, a.text_center, {color: 'white'}]}>
@@ -84,7 +55,7 @@ export function QrCode({
style={[a.font_bold, a.text_center, {color: 'white', fontSize: 18}]}> style={[a.font_bold, a.text_center, {color: 'white', fontSize: 18}]}>
<Trans>Join the conversation</Trans> <Trans>Join the conversation</Trans>
</Text> </Text>
<View style={[]}> <View style={[a.rounded_sm, a.overflow_hidden]}>
<QrCodeInner url="https://bsky.app" /> <QrCodeInner url="https://bsky.app" />
</View> </View>
@@ -107,45 +78,43 @@ export function QrCode({
</LinearGradient> </LinearGradient>
</ViewShot> </ViewShot>
) )
} })
export function QrCodeInner({url}: {url: string}) { export function QrCodeInner({url}: {url: string}) {
const t = useTheme() const t = useTheme()
return ( return (
<View style={[a.flex_shrink, a.rounded_md]}> <QRCode
<QRCode data={url}
data={url} style={[
style={[ a.rounded_sm,
a.rounded_sm, {height: 200, width: 200, backgroundColor: '#f3f3f3'},
{height: 200, width: 200, backgroundColor: '#f3f3f3'}, ]}
]} pieceSize={8}
pieceSize={8} padding={20}
padding={20} // pieceLiquidRadius={2}
// pieceLiquidRadius={2} pieceBorderRadius={4.5}
pieceBorderRadius={4.5} outerEyesOptions={{
outerEyesOptions={{ topLeft: {
topLeft: { borderRadius: [12, 12, 0, 12],
borderRadius: [12, 12, 0, 12], color: t.palette.primary_500,
color: t.palette.primary_500, },
}, topRight: {
topRight: { borderRadius: [12, 12, 12, 0],
borderRadius: [12, 12, 12, 0], color: t.palette.primary_500,
color: t.palette.primary_500, },
}, bottomLeft: {
bottomLeft: { borderRadius: [12, 0, 12, 12],
borderRadius: [12, 0, 12, 12], color: t.palette.primary_500,
color: t.palette.primary_500, },
}, }}
}} innerEyesOptions={{borderRadius: 3}}
innerEyesOptions={{borderRadius: 3}} logo={{
logo={{ href: require('../../../assets/logo.png'),
href: require('../../../assets/logo.png'), scale: 1.2,
scale: 1.2, padding: 2,
padding: 2, hidePieces: true,
hidePieces: true, }}
}} />
/>
</View>
) )
} }
+10 -11
View File
@@ -1,5 +1,6 @@
import React from 'react' import React from 'react'
import {View} from 'react-native' import {View} from 'react-native'
import ViewShot from 'react-native-view-shot'
import * as FS from 'expo-file-system' import * as FS from 'expo-file-system'
import {AppBskyGraphDefs} from '@atproto/api' import {AppBskyGraphDefs} from '@atproto/api'
import {msg, Trans} from '@lingui/macro' import {msg, Trans} from '@lingui/macro'
@@ -24,23 +25,21 @@ export function QrCodeDialog({
}) { }) {
const {_} = useLingui() const {_} = useLingui()
// No types for this const ref = React.useRef<ViewShot>(null)
// See https://github.com/tokkozhin/react-native-qrcode-styled/blob/main/example/src/examples/DownloadQR.tsx for usage
const qrCodeRef = React.useRef<any>()
const onSavePress = () => { const onSavePress = () => {
qrCodeRef.current?.toDataURL(async (base64Code: string) => { ref.current?.capture?.().then(async (uri: string) => {
const filename = `${FS.cacheDirectory}/${nanoid(12)}.png` const filename = `${FS.cacheDirectory}/${nanoid(12)}.png`
await FS.writeAsStringAsync(filename, base64Code, { await FS.copyAsync({from: uri, to: filename})
encoding: FS.EncodingType.Base64,
})
await saveImageToMediaLibrary({uri: filename}) await saveImageToMediaLibrary({uri: filename})
control.close(() => { await FS.deleteAsync(filename)
Toast.show(_(msg`QR code saved to your camera roll!`)) Toast.show(_(msg`QR code saved to your camera roll!`))
})
control.close()
}) })
} }
return ( return (
<Dialog.Outer control={control}> <Dialog.Outer control={control}>
<Dialog.Handle /> <Dialog.Handle />
@@ -50,7 +49,7 @@ export function QrCodeDialog({
<Text style={[a.font_bold, a.text_xl, a.text_center]}> <Text style={[a.font_bold, a.text_xl, a.text_center]}>
Share this starter pack with friends! Share this starter pack with friends!
</Text> </Text>
<QrCode starterPack={starterPack} /> <QrCode starterPack={starterPack} ref={ref} />
<Button <Button
label={_(msg`Save QR code`)} label={_(msg`Save QR code`)}
variant="solid" variant="solid"