11import * as Clipboard from "expo-clipboard" ;
2- import { useEffect , useState } from "react" ;
2+ import { useEffect , useMemo , useState } from "react" ;
33import { ActivityIndicator , Pressable , Share , Text , View } from "react-native" ;
44import QRCode from "qrcode" ;
55import { SvgXml } from "react-native-svg" ;
@@ -8,28 +8,52 @@ import Toast from "react-native-toast-message";
88import { BottomSheet } from "@/components/ui/bottom-sheet" ;
99import { useHaptics } from "@/hooks/use-haptics" ;
1010import { useT } from "@/lib/i18n" ;
11- import { QR_SAFE_BYTE_LIMIT , utf8ByteLength } from "@/lib/scan" ;
11+ import {
12+ QR_SAFE_BYTE_LIMIT ,
13+ type ScanEnvelope ,
14+ utf8ByteLength ,
15+ } from "@/lib/scan" ;
16+ import { buildShareArtifacts , resolveShortLink } from "@/lib/share" ;
1217
13- export function ScanCodeSheet ( {
18+ export function ShareSheet ( {
1419 visible,
1520 onClose,
1621 title,
1722 description,
18- qrValue,
19- shareValue,
23+ envelope,
2024} : Readonly < {
2125 visible : boolean ;
2226 onClose : ( ) => void ;
2327 title : string ;
2428 description : string ;
25- qrValue : string ;
26- shareValue ?: string ;
29+ envelope : ScanEnvelope ;
2730} > ) {
2831 const t = useT ( ) ;
2932 const haptic = useHaptics ( ) ;
30- const link = shareValue ?? qrValue ;
33+
34+ const { qrValue, deepLink } = useMemo (
35+ ( ) => buildShareArtifacts ( envelope ) ,
36+ [ envelope ] ,
37+ ) ;
3138 const tooLarge = utf8ByteLength ( qrValue ) > QR_SAFE_BYTE_LIMIT ;
3239
40+ const [ shortLink , setShortLink ] = useState < string | null > ( null ) ;
41+ const link = shortLink ?? deepLink ;
42+
43+ useEffect ( ( ) => {
44+ if ( ! visible ) return ;
45+ let cancelled = false ;
46+ setShortLink ( null ) ;
47+ resolveShortLink ( envelope )
48+ . then ( ( url ) => {
49+ if ( ! cancelled ) setShortLink ( url ) ;
50+ } )
51+ . catch ( ( ) => { } ) ;
52+ return ( ) => {
53+ cancelled = true ;
54+ } ;
55+ } , [ envelope , visible ] ) ;
56+
3357 const [ qrResult , setQrResult ] = useState < {
3458 value : string ;
3559 svg : string | null ;
@@ -69,7 +93,7 @@ export function ScanCodeSheet({
6993 await Clipboard . setStringAsync ( link ) ;
7094 Toast . show ( {
7195 type : "success" ,
72- text1 : t ( "scan .codeCopied" ) ,
96+ text1 : t ( "share .codeCopied" ) ,
7397 position : "bottom" ,
7498 } ) ;
7599 } ;
@@ -89,13 +113,13 @@ export function ScanCodeSheet({
89113 < View className = "h-64 w-64 items-center justify-center rounded-2xl bg-white p-3" >
90114 { tooLarge ? (
91115 < Text className = "px-2 text-center text-sm leading-5 text-neutral-500" >
92- { t ( "scan .codeTooLarge" ) }
116+ { t ( "share .codeTooLarge" ) }
93117 </ Text >
94118 ) : qrSvg ? (
95119 < SvgXml xml = { qrSvg } width = { 232 } height = { 232 } />
96120 ) : failed ? (
97121 < Text className = "text-center text-sm text-red-500" >
98- { t ( "scan .codeRenderFailed" ) }
122+ { t ( "share .codeRenderFailed" ) }
99123 </ Text >
100124 ) : (
101125 < ActivityIndicator />
@@ -109,15 +133,15 @@ export function ScanCodeSheet({
109133 onPress = { copy }
110134 >
111135 < Text className = "text-base font-medium text-neutral-600 dark:text-neutral-300" >
112- { t ( "scan .copyCode" ) }
136+ { t ( "share .copyCode" ) }
113137 </ Text >
114138 </ Pressable >
115139 < Pressable
116140 className = "flex-1 items-center rounded-xl bg-blue-500 py-3 active:bg-blue-600"
117141 onPress = { share }
118142 >
119143 < Text className = "text-base font-medium text-white" >
120- { t ( "scan .shareCode" ) }
144+ { t ( "share .shareCode" ) }
121145 </ Text >
122146 </ Pressable >
123147 </ View >
0 commit comments