handle saving viewshot
This commit is contained in:
@@ -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>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
Reference in New Issue
Block a user