From 3002caf4672e1df039a089b9109e444f8d8caf00 Mon Sep 17 00:00:00 2001 From: Louis Lagrange Date: Mon, 16 Aug 2021 07:23:51 +0800 Subject: [PATCH] feat(dynamic-links): add support for utmParameters (#5593) if you resolve a short link that was built with utm parameters, they will come through now on the returned link Co-authored-by: Mike Hardy --- ...ReactNativeFirebaseDynamicLinksModule.java | 15 +++++++++++---- .../dynamic-links/e2e/dynamicLinks.e2e.js | 2 ++ .../RNFBDynamicLinksAppDelegateInterceptor.h | 1 + .../RNFBDynamicLinksAppDelegateInterceptor.m | 9 +++++++++ .../RNFBDynamicLinks/RNFBDynamicLinksModule.m | 19 +++++++++++++++++++ packages/dynamic-links/lib/index.d.ts | 7 +++++++ 6 files changed, 49 insertions(+), 4 deletions(-) diff --git a/packages/dynamic-links/android/src/main/java/io/invertase/firebase/dynamiclinks/ReactNativeFirebaseDynamicLinksModule.java b/packages/dynamic-links/android/src/main/java/io/invertase/firebase/dynamiclinks/ReactNativeFirebaseDynamicLinksModule.java index 3493c58e74..94e9086f2f 100644 --- a/packages/dynamic-links/android/src/main/java/io/invertase/firebase/dynamiclinks/ReactNativeFirebaseDynamicLinksModule.java +++ b/packages/dynamic-links/android/src/main/java/io/invertase/firebase/dynamiclinks/ReactNativeFirebaseDynamicLinksModule.java @@ -20,6 +20,7 @@ import android.app.Activity; import android.content.Intent; import android.net.Uri; +import android.os.Bundle; import android.util.Log; import com.facebook.react.bridge.*; import com.google.android.gms.tasks.Tasks; @@ -41,6 +42,7 @@ public class ReactNativeFirebaseDynamicLinksModule extends ReactNativeFirebaseMo private String initialLinkUrl = null; private int initialLinkMinimumVersion = 0; + private WritableMap initialLinkUtmParameters = new WritableNativeMap(); /** Ensures calls to getInitialLink only tries to retrieve the link from getDynamicLink once. */ private boolean gotInitialLink = false; @@ -180,6 +182,7 @@ public void getInitialLink(Promise promise) { if (pendingDynamicLinkData != null) { initialLinkUrl = pendingDynamicLinkData.getLink().toString(); initialLinkMinimumVersion = pendingDynamicLinkData.getMinimumAppVersion(); + initialLinkUtmParameters = Arguments.makeNativeMap(pendingDynamicLinkData.getUtmParameters()); } // Guard against the scenario where the app was launched using a dynamic link, @@ -187,7 +190,7 @@ public void getInitialLink(Promise promise) { // Overview (screen). if (initialLinkUrl != null && !launchedFromHistory) { promise.resolve( - dynamicLinkToWritableMap(initialLinkUrl, initialLinkMinimumVersion)); + dynamicLinkToWritableMap(initialLinkUrl, initialLinkMinimumVersion, initialLinkUtmParameters)); } else { promise.resolve(null); } @@ -214,7 +217,8 @@ public void resolveLink(String link, Promise promise) { && linkData.getLink().toString() != null) { String linkUrl = linkData.getLink().toString(); int linkMinimumVersion = linkData.getMinimumAppVersion(); - promise.resolve(dynamicLinkToWritableMap(linkUrl, linkMinimumVersion)); + Bundle linkUtmParameters = linkData.getUtmParameters(); + promise.resolve(dynamicLinkToWritableMap(linkUrl, linkMinimumVersion, Arguments.makeNativeMap(linkUtmParameters))); } else { rejectPromiseWithCodeAndMessage(promise, "not-found", "Dynamic link not found"); } @@ -229,7 +233,7 @@ public void resolveLink(String link, Promise promise) { } } - private WritableMap dynamicLinkToWritableMap(String url, int minVersion) { + private WritableMap dynamicLinkToWritableMap(String url, int minVersion, WritableMap utmParameters) { WritableMap writableMap = Arguments.createMap(); writableMap.putString("url", url); @@ -240,6 +244,8 @@ private WritableMap dynamicLinkToWritableMap(String url, int minVersion) { writableMap.putInt("minimumAppVersion", minVersion); } + writableMap.putMap("utmParameters", utmParameters); + return writableMap; } @@ -435,7 +441,8 @@ public void onNewIntent(Intent intent) { "dynamic_links_link_received", dynamicLinkToWritableMap( pendingDynamicLinkData.getLink().toString(), - pendingDynamicLinkData.getMinimumAppVersion()))); + pendingDynamicLinkData.getMinimumAppVersion(), + Arguments.makeNativeMap(pendingDynamicLinkData.getUtmParameters())))); } } else { Log.e( diff --git a/packages/dynamic-links/e2e/dynamicLinks.e2e.js b/packages/dynamic-links/e2e/dynamicLinks.e2e.js index d7dda7cadf..f1e8c4170c 100644 --- a/packages/dynamic-links/e2e/dynamicLinks.e2e.js +++ b/packages/dynamic-links/e2e/dynamicLinks.e2e.js @@ -155,6 +155,7 @@ describe('dynamicLinks()', function () { dynamicLink.should.be.an.Object(); dynamicLink.url.should.equal('https://rnfirebase.io'); + dynamicLink.utmParameters.should.eql({}); }); }); @@ -172,6 +173,7 @@ describe('dynamicLinks()', function () { spy.getCall(0).args[0].should.be.an.Object(); spy.getCall(0).args[0].url.should.equal('https://invertase.io/hire-us'); + spy.getCall(0).args[0].utmParameters.should.eql({}); }); }); }); diff --git a/packages/dynamic-links/ios/RNFBDynamicLinks/RNFBDynamicLinksAppDelegateInterceptor.h b/packages/dynamic-links/ios/RNFBDynamicLinks/RNFBDynamicLinksAppDelegateInterceptor.h index 79492846b8..7c287acef6 100644 --- a/packages/dynamic-links/ios/RNFBDynamicLinks/RNFBDynamicLinksAppDelegateInterceptor.h +++ b/packages/dynamic-links/ios/RNFBDynamicLinks/RNFBDynamicLinksAppDelegateInterceptor.h @@ -27,6 +27,7 @@ static NSString *const LINK_RECEIVED_EVENT = @"dynamic_links_link_received"; @interface RNFBDynamicLinksAppDelegateInterceptor : NSObject @property(strong, readwrite) NSString *_Nullable initialLinkUrl; @property(strong, readwrite) NSString *_Nullable initialLinkMinimumAppVersion; +@property(strong, readwrite) NSDictionary *_Nonnull initialLinkUtmParametersDictionary; + (instancetype)sharedInstance; diff --git a/packages/dynamic-links/ios/RNFBDynamicLinks/RNFBDynamicLinksAppDelegateInterceptor.m b/packages/dynamic-links/ios/RNFBDynamicLinks/RNFBDynamicLinksAppDelegateInterceptor.m index 02bd007977..806a0bdb27 100644 --- a/packages/dynamic-links/ios/RNFBDynamicLinks/RNFBDynamicLinksAppDelegateInterceptor.m +++ b/packages/dynamic-links/ios/RNFBDynamicLinks/RNFBDynamicLinksAppDelegateInterceptor.m @@ -28,6 +28,7 @@ + (instancetype)sharedInstance { sharedInstance = [[RNFBDynamicLinksAppDelegateInterceptor alloc] init]; sharedInstance.initialLinkUrl = nil; sharedInstance.initialLinkMinimumAppVersion = nil; + sharedInstance.initialLinkUtmParametersDictionary = @{}; [GULAppDelegateSwizzler proxyOriginalDelegate]; [GULAppDelegateSwizzler registerAppDelegateInterceptor:sharedInstance]; }); @@ -64,6 +65,7 @@ - (BOOL)application:(UIApplication *)application if (_initialLinkUrl == nil) { _initialLinkUrl = dynamicLink.url.absoluteString; _initialLinkMinimumAppVersion = dynamicLink.minimumAppVersion; + _initialLinkUtmParametersDictionary = dynamicLink.utmParametersDictionary; } [[RNFBRCTEventEmitter shared] sendEventWithName:LINK_RECEIVED_EVENT @@ -72,6 +74,9 @@ - (BOOL)application:(UIApplication *)application @"minimumAppVersion" : dynamicLink.minimumAppVersion == nil ? [NSNull null] : dynamicLink.minimumAppVersion, + @"utmParameters": dynamicLink.utmParametersDictionary == nil + ? @{} + : dynamicLink.utmParametersDictionary, }]; } @@ -91,6 +96,7 @@ - (BOOL)application:(UIApplication *)application if (_initialLinkUrl == nil) { _initialLinkUrl = dynamicLink.url.absoluteString; _initialLinkMinimumAppVersion = dynamicLink.minimumAppVersion; + _initialLinkUtmParametersDictionary = dynamicLink.utmParametersDictionary; } [[RNFBRCTEventEmitter shared] sendEventWithName:LINK_RECEIVED_EVENT @@ -99,6 +105,9 @@ - (BOOL)application:(UIApplication *)application @"minimumAppVersion" : dynamicLink.minimumAppVersion == nil ? [NSNull null] : dynamicLink.minimumAppVersion, + @"utmParameters": dynamicLink.utmParametersDictionary == nil + ? @{} + : dynamicLink.utmParametersDictionary, }]; } diff --git a/packages/dynamic-links/ios/RNFBDynamicLinks/RNFBDynamicLinksModule.m b/packages/dynamic-links/ios/RNFBDynamicLinks/RNFBDynamicLinksModule.m index aca65793d2..47fae78e81 100644 --- a/packages/dynamic-links/ios/RNFBDynamicLinks/RNFBDynamicLinksModule.m +++ b/packages/dynamic-links/ios/RNFBDynamicLinks/RNFBDynamicLinksModule.m @@ -136,6 +136,8 @@ - (id)init { @"url" : dynamicLink.url.absoluteString, @"minimumAppVersion" : dynamicLink.minimumAppVersion == nil ? [NSNull null] : dynamicLink.minimumAppVersion, + @"utmParameters": dynamicLink.utmParametersDictionary == nil ? @{} + : dynamicLink.utmParametersDictionary, }); } else if ([RNFBDynamicLinksAppDelegateInterceptor sharedInstance].initialLinkUrl != nil) { resolve(@{ @@ -144,6 +146,10 @@ - (id)init { .initialLinkMinimumAppVersion == nil ? [NSNull null] : [RNFBDynamicLinksAppDelegateInterceptor sharedInstance].initialLinkMinimumAppVersion, + @"utmParameters": [RNFBDynamicLinksAppDelegateInterceptor sharedInstance] + .initialLinkUtmParametersDictionary == nil + ? @{} + : [RNFBDynamicLinksAppDelegateInterceptor sharedInstance].initialLinkUtmParametersDictionary, }); } else { resolve([NSNull null]); @@ -166,6 +172,9 @@ - (id)init { @"minimumAppVersion" : dynamicLink.minimumAppVersion == nil ? [NSNull null] : dynamicLink.minimumAppVersion, + @"utmParameters": dynamicLink.utmParametersDictionary == nil + ? @{} + : dynamicLink.utmParametersDictionary, }); } else if (!error && [RNFBDynamicLinksAppDelegateInterceptor sharedInstance].initialLinkUrl != nil) { @@ -176,6 +185,10 @@ - (id)init { ? [NSNull null] : [RNFBDynamicLinksAppDelegateInterceptor sharedInstance] .initialLinkMinimumAppVersion, + @"utmParameters": [RNFBDynamicLinksAppDelegateInterceptor sharedInstance] + .initialLinkUtmParametersDictionary == nil + ? @{} + : [RNFBDynamicLinksAppDelegateInterceptor sharedInstance].initialLinkUtmParametersDictionary, }); } else if (error) { [RNFBSharedUtils rejectPromiseWithUserInfo:reject @@ -201,6 +214,10 @@ - (id)init { .initialLinkMinimumAppVersion == nil ? [NSNull null] : [RNFBDynamicLinksAppDelegateInterceptor sharedInstance].initialLinkMinimumAppVersion, + @"utmParameters": [RNFBDynamicLinksAppDelegateInterceptor sharedInstance] + .initialLinkUtmParametersDictionary == nil + ? @{} + : [RNFBDynamicLinksAppDelegateInterceptor sharedInstance].initialLinkUtmParametersDictionary, }); } else { resolve([NSNull null]); @@ -217,6 +234,8 @@ - (id)init { @"url" : dynamicLink.url.absoluteString, @"minimumAppVersion" : dynamicLink.minimumAppVersion == nil ? [NSNull null] : dynamicLink.minimumAppVersion, + @"utmParameters": dynamicLink.utmParametersDictionary == nil ? @{} + : dynamicLink.utmParametersDictionary, }); } else if (!error || (error && [error.localizedDescription containsString:@"dynamicLinks error 404"])) { diff --git a/packages/dynamic-links/lib/index.d.ts b/packages/dynamic-links/lib/index.d.ts index f1c7c8140d..bc80274c8e 100644 --- a/packages/dynamic-links/lib/index.d.ts +++ b/packages/dynamic-links/lib/index.d.ts @@ -421,6 +421,13 @@ export namespace FirebaseDynamicLinksTypes { * On iOS this returns a string value representing the minimum app version (not the iOS system version). */ minimumAppVersion: number | string | null; + + /** + * The potential UTM parameters linked to this dynamic link + * + * It will only work for short links, not long links + */ + utmParameters: Record; } /**