diff --git a/native/ios/Podfile.lock b/native/ios/Podfile.lock --- a/native/ios/Podfile.lock +++ b/native/ios/Podfile.lock @@ -4,7 +4,7 @@ - boost (1.76.0) - DoubleConversion (1.1.6) - DVAssetLoaderDelegate (0.3.3) - - EXApplication (5.0.1): + - EXApplication (5.1.1): - ExpoModulesCore - EXConstants (14.0.2): - ExpoModulesCore @@ -841,7 +841,7 @@ boost: a7c83b31436843459a1961bfd74b96033dc77234 DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 DVAssetLoaderDelegate: 0caec20e4e08b8560b691131539e9180024d4bce - EXApplication: 034b1c40a8e9fe1bff76a1e511ee90dff64ad834 + EXApplication: d8f53a7eee90a870a75656280e8d4b85726ea903 EXConstants: 3c86653c422dd77e40d10cbbabb3025003977415 EXFileSystem: 60602b6eefa6873f97172c684b7537c9760b50d6 EXFont: 319606bfe48c33b5b5063fb0994afdc496befe80 diff --git a/native/navigation/invite-link-handler.react.js b/native/navigation/invite-link-handler.react.js --- a/native/navigation/invite-link-handler.react.js +++ b/native/navigation/invite-link-handler.react.js @@ -1,8 +1,9 @@ // @flow import { useNavigation } from '@react-navigation/native'; +import * as Application from 'expo-application'; import * as React from 'react'; -import { Linking } from 'react-native'; +import { Linking, Platform } from 'react-native'; import { verifyInviteLink, @@ -16,6 +17,7 @@ import { InviteLinkModalRouteName } from './route-names.js'; import { useSelector } from '../redux/redux-utils.js'; +import { useOnFirstLaunchEffect } from '../utils/hooks.js'; function InviteLinkHandler(): null { const [currentLink, setCurrentLink] = React.useState(null); @@ -41,6 +43,21 @@ }; }, []); + const checkInstallReferrer = React.useCallback(async () => { + if (Platform.OS !== 'android') { + return; + } + const installReferrer = await Application.getInstallReferrerAsync(); + if (!installReferrer) { + return; + } + const linkSecret = parseInstallReferrer(installReferrer); + if (linkSecret) { + setCurrentLink(linkSecret); + } + }, []); + useOnFirstLaunchEffect('ANDROID_REFERRER', checkInstallReferrer); + const loggedIn = useSelector(isLoggedIn); const dispatchActionPromise = useDispatchActionPromise(); const validateLink = useServerCall(verifyInviteLink); @@ -85,4 +102,10 @@ return match?.[1]; } +const referrerRegex = /utm_source=(invite\/(\S+))$/; +function parseInstallReferrer(referrer: string) { + const match = referrerRegex.exec(referrer); + return match?.[1]; +} + export default InviteLinkHandler; diff --git a/native/package.json b/native/package.json --- a/native/package.json +++ b/native/package.json @@ -71,6 +71,7 @@ "base-64": "^0.1.0", "ethers": "^5.7.2", "expo": "47.0.14", + "expo-application": "^5.1.1", "expo-dev-client": "~2.0.1", "expo-font": "~11.0.1", "expo-haptics": "~12.0.1", diff --git a/native/utils/crash-utils.js b/native/utils/crash-utils.js --- a/native/utils/crash-utils.js +++ b/native/utils/crash-utils.js @@ -12,6 +12,7 @@ await Promise.all([ getPersistor().purge(), __DEV__ ? AsyncStorage.removeItem(navStateAsyncStorageKey) : null, + AsyncStorage.removeItem('ANDROID_REFERRER'), ]); await sleep(50); commCoreModule.terminate(); diff --git a/yarn.lock b/yarn.lock --- a/yarn.lock +++ b/yarn.lock @@ -11000,6 +11000,11 @@ resolved "https://registry.yarnpkg.com/expirymanager/-/expirymanager-0.9.4.tgz#dc9f2dfc2a8160dc88c24fe0bca8c085908bd322" integrity sha512-bKcLuZPTs9mFxQ2VJPYJCMuGVAM9Ah6KfezbDA3IegbGeqR39WdPi+T7GgDGVuBPjYDFsSP/va5csiNVCGT1Mw== +expo-application@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/expo-application/-/expo-application-5.1.1.tgz#5206bf0cf89cb0e32d1f5037a0481e5c86b951ab" + integrity sha512-aDatTcTTCdTbHw8h4/Tq2ilc6InM5ntF9xWCJdOcnUEcglxxGphVI/lzJKBaBF6mJECA8mEOjpVg2EGxOctTwg== + expo-application@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/expo-application/-/expo-application-5.0.1.tgz#628aeee74697d7aa39d0c0173dbf9383e06e53e9"