Skip to content

Commit

Permalink
Release 1.44.0
Browse files Browse the repository at this point in the history
- SDK-1658 Added Support for VIEW_AD, INITIATE_STREAM, COMPLETE_STREAM and all V2 Events as Standard events
- SDK-1480 [iOS 16] Added UIPaste Support for NativeLink Flow
  • Loading branch information
NidhiDixit09 committed Oct 19, 2022
1 parent 2a430f2 commit e235ec8
Show file tree
Hide file tree
Showing 29 changed files with 573 additions and 88 deletions.
2 changes: 1 addition & 1 deletion Branch-SDK/BNCConfig.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@
NSString * const BNC_API_BASE_URL = @"https://api2.branch.io";
NSString * const BNC_API_VERSION = @"v1";
NSString * const BNC_LINK_URL = @"https://bnc.lt";
NSString * const BNC_SDK_VERSION = @"1.43.2";
NSString * const BNC_SDK_VERSION = @"1.44.0";
5 changes: 3 additions & 2 deletions Branch-SDK/BNCPreferenceHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ NSURL* /* _Nonnull */ BNCURLForBranchDirectory(void);
@property (copy, nonatomic) NSString *sessionID;
@property (copy, nonatomic) NSString *linkClickIdentifier;
@property (copy, nonatomic) NSString *spotlightIdentifier;
@property (copy, nonatomic) NSString *universalLinkUrl;
@property (copy, nonatomic) NSString *initialReferrer;
@property (copy, nonatomic) NSString *universalLinkUrl;
@property (copy, nonatomic) NSString *initialReferrer;
@property (copy, nonatomic) NSString *userUrl;
@property (copy, nonatomic) NSString *localUrl;
@property (copy, nonatomic) NSString *userIdentity;
@property (copy, nonatomic) NSString *sessionParams;
@property (copy, nonatomic) NSString *installParams;
Expand Down
10 changes: 10 additions & 0 deletions Branch-SDK/BNCPreferenceHelper.m
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
static NSString * const BRANCH_PREFS_KEY_LINK_CLICK_IDENTIFIER = @"bnc_link_click_identifier";
static NSString * const BRANCH_PREFS_KEY_SPOTLIGHT_IDENTIFIER = @"bnc_spotlight_identifier";
static NSString * const BRANCH_PREFS_KEY_UNIVERSAL_LINK_URL = @"bnc_universal_link_url";
static NSString * const BRANCH_PREFS_KEY_LOCAL_URL = @"bnc_local_url";
static NSString * const BRANCH_PREFS_KEY_INITIAL_REFERRER = @"bnc_initial_referrer";
static NSString * const BRANCH_PREFS_KEY_SESSION_PARAMS = @"bnc_session_params";
static NSString * const BRANCH_PREFS_KEY_INSTALL_PARAMS = @"bnc_install_params";
Expand Down Expand Up @@ -80,6 +81,7 @@ @implementation BNCPreferenceHelper
installParams = _installParams,
universalLinkUrl = _universalLinkUrl,
initialReferrer = _initialReferrer,
localUrl = _localUrl,
externalIntentURI = _externalIntentURI,
isDebug = _isDebug,
retryCount = _retryCount,
Expand Down Expand Up @@ -325,6 +327,14 @@ - (void)setUniversalLinkUrl:(NSString *)universalLinkUrl {
[self writeObjectToDefaults:BRANCH_PREFS_KEY_UNIVERSAL_LINK_URL value:universalLinkUrl];
}

- (NSString *)localUrl {
return [self readStringFromDefaults:BRANCH_PREFS_KEY_LOCAL_URL];
}

- (void)setLocalUrl:(NSString *)localURL {
[self writeObjectToDefaults:BRANCH_PREFS_KEY_LOCAL_URL value:localURL];
}

- (NSString *)initialReferrer {
return [self readStringFromDefaults:BRANCH_REQUEST_KEY_INITIAL_REFERRER];
}
Expand Down
11 changes: 11 additions & 0 deletions Branch-SDK/Branch.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
@import Foundation;
#else
#import <Foundation/Foundation.h>
#import <UniformTypeIdentifiers/UniformTypeIdentifiers.h>
#endif

#import "BNCCallbacks.h"
Expand Down Expand Up @@ -1838,6 +1839,16 @@ typedef NS_ENUM(NSUInteger, BranchCreditHistoryOrder) {
// Read-only property exposed for unit testing.
@property (strong, readonly) BNCServerInterface* serverInterface;
- (void) clearNetworkQueue;

#if !TARGET_OS_TV
#pragma mark - UIPasteControl Support
/**
This method is used to pass paste board items to Branch SDK when user implements UIPasteControl at their end. SDK retrives URL from these item providers if any to support native link functionality.
@param itemProviders - an array of item providers collected from pasteboard.
@warning This function works with iOS 16 or above.
*/
- (void)passPasteItemProviders:(NSArray<NSItemProvider *> *)itemProviders API_AVAILABLE(ios(16));
#endif
@end

NS_ASSUME_NONNULL_END
25 changes: 24 additions & 1 deletion Branch-SDK/Branch.m
Original file line number Diff line number Diff line change
Expand Up @@ -1592,6 +1592,30 @@ - (void)removeAllPrivateContentFromSpotLightWithCallback:(void (^)(NSError * err
}
#endif

#if !TARGET_OS_TV
#pragma mark - UIPasteControl Support methods

- (void)passPasteItemProviders:(NSArray<NSItemProvider *> *)itemProviders {

// 1. Extract URL from NSItemProvider arrary
for (NSItemProvider* item in itemProviders){
if ( [item hasItemConformingToTypeIdentifier: UTTypeURL.identifier] ) {
// 2. Check if URL is branch URL and if yes -> store it.
[item loadItemForTypeIdentifier:UTTypeURL.identifier options:NULL completionHandler:^(NSURL *url, NSError * _Null_unspecified error) {
if (error) {
BNCLogError([NSString stringWithFormat:@"%@", error]);
}
else if ([Branch isBranchLink:url.absoluteString]) {
[self.preferenceHelper setLocalUrl:[url absoluteString]];
// 3. Send Open Event
[[Branch getInstance] handleDeepLink:url];
}
}];
}
}
}
#endif

#pragma mark - Private methods

+ (Branch *)getInstanceInternal:(NSString *)key {
Expand Down Expand Up @@ -2124,7 +2148,6 @@ - (void)initUserSessionAndCallCallback:(BOOL)callCallback sceneIdentifier:(NSStr

// callback on main, this is generally what the client expects and maintains our previous behavior
dispatch_async(dispatch_get_main_queue(), ^ {

if (self.sceneSessionInitWithCallback) {
BNCInitSessionResponse *response = [BNCInitSessionResponse new];
response.params = [self getLatestReferringParams];
Expand Down
3 changes: 3 additions & 0 deletions Branch-SDK/BranchEvent.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ FOUNDATION_EXPORT BranchStandardEvent _Nonnull BranchStandardEventViewItem;
FOUNDATION_EXPORT BranchStandardEvent _Nonnull BranchStandardEventViewItems;
FOUNDATION_EXPORT BranchStandardEvent _Nonnull BranchStandardEventRate;
FOUNDATION_EXPORT BranchStandardEvent _Nonnull BranchStandardEventShare;
FOUNDATION_EXPORT BranchStandardEvent _Nonnull BranchStandardEventInitiateStream;
FOUNDATION_EXPORT BranchStandardEvent _Nonnull BranchStandardEventCompleteStream;


///@name User Lifecycle Events

Expand Down
4 changes: 4 additions & 0 deletions Branch-SDK/BranchEvent.m
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
BranchStandardEvent BranchStandardEventViewItems = @"VIEW_ITEMS";
BranchStandardEvent BranchStandardEventRate = @"RATE";
BranchStandardEvent BranchStandardEventShare = @"SHARE";
BranchStandardEvent BranchStandardEventInitiateStream = @"INITIATE_STREAM";
BranchStandardEvent BranchStandardEventCompleteStream = @"COMPLETE_STREAM";

// User Lifecycle Events

Expand Down Expand Up @@ -245,6 +247,8 @@ - (NSDictionary*) dictionary {
BranchStandardEventViewAd,
BranchStandardEventOptOut,
BranchStandardEventOptIn,
BranchStandardEventInitiateStream,
BranchStandardEventCompleteStream
];
}

Expand Down
15 changes: 14 additions & 1 deletion Branch-SDK/BranchInstallRequest.m
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ - (id)initWithCallback:(callbackWithStatus)callback {
- (void)makeRequest:(BNCServerInterface *)serverInterface key:(NSString *)key callback:(BNCServerCallback)callback {
BNCPreferenceHelper *preferenceHelper = [BNCPreferenceHelper sharedInstance];
NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
super.clearLocalURL = FALSE;

[self safeSetValue:[BNCSystemObserver getBundleID] forKey:BRANCH_REQUEST_KEY_BUNDLE_ID onDict:params];
[self safeSetValue:[BNCSystemObserver getTeamIdentifier] forKey:BRANCH_REQUEST_KEY_TEAM_ID onDict:params];
Expand Down Expand Up @@ -69,7 +70,19 @@ - (void)makeRequest:(BNCServerInterface *)serverInterface key:(NSString *)key ca
}

if ([BNCPasteboard sharedInstance].checkOnInstall) {
NSURL *pasteboardURL = [[BNCPasteboard sharedInstance] checkForBranchLink];
NSURL *pasteboardURL = nil;
if (@available(iOS 16.0, *)) {
NSString *localURLString = [[BNCPreferenceHelper sharedInstance] localUrl];
if(localURLString){
pasteboardURL = [[NSURL alloc] initWithString:localURLString];
super.clearLocalURL = TRUE;
} else {
pasteboardURL = [[BNCPasteboard sharedInstance] checkForBranchLink];
}
} else {
pasteboardURL = [[BNCPasteboard sharedInstance] checkForBranchLink];
}

if (pasteboardURL) {
[self safeSetValue:pasteboardURL.absoluteString forKey:BRANCH_REQUEST_KEY_LOCAL_URL onDict:params];
}
Expand Down
1 change: 1 addition & 0 deletions Branch-SDK/BranchOpenRequest.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
@interface BranchOpenRequest : BNCServerRequest

@property (nonatomic, copy) callbackWithStatus callback;
@property (assign, nonatomic) BOOL clearLocalURL;

+ (void) waitForOpenResponseLock;
+ (void) releaseOpenResponseLock;
Expand Down
19 changes: 19 additions & 0 deletions Branch-SDK/BranchOpenRequest.m
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ - (id)initWithCallback:(callbackWithStatus)callback isInstall:(BOOL)isInstall {
}

- (void)makeRequest:(BNCServerInterface *)serverInterface key:(NSString *)key callback:(BNCServerCallback)callback {
self.clearLocalURL = FALSE;
NSMutableDictionary *params = [[NSMutableDictionary alloc] init];

BNCPreferenceHelper *preferenceHelper = [BNCPreferenceHelper sharedInstance];
Expand Down Expand Up @@ -100,6 +101,17 @@ - (void)makeRequest:(BNCServerInterface *)serverInterface key:(NSString *)key ca
if (partnerParameters.count > 0) {
[self safeSetValue:partnerParameters forKey:BRANCH_REQUEST_KEY_PARTNER_PARAMETERS onDict:params];
}

if (@available(iOS 16.0, *)) {
NSString *localURLString = [[BNCPreferenceHelper sharedInstance] localUrl];
if(localURLString){
NSURL *localURL = [[NSURL alloc] initWithString:localURLString];
if (localURL) {
[self safeSetValue:localURL.absoluteString forKey:BRANCH_REQUEST_KEY_LOCAL_URL onDict:params];
self.clearLocalURL = TRUE;
}
}
}

BNCApplication *application = [BNCApplication currentApplication];
params[@"lastest_update_time"] = BNCWireFormatFromDate(application.currentBuildDate);
Expand Down Expand Up @@ -269,6 +281,13 @@ - (void)processResponse:(BNCServerResponse *)response error:(NSError *)error {
preferenceHelper.randomizedBundleToken = string;
}

if (self.clearLocalURL) {
preferenceHelper.localUrl = nil;
#if !TARGET_OS_TV
UIPasteboard.generalPasteboard.URL = nil;
#endif
}

[BranchOpenRequest releaseOpenResponseLock];

BranchContentDiscoveryManifest *cdManifest = [BranchContentDiscoveryManifest getInstance];
Expand Down
25 changes: 25 additions & 0 deletions Branch-SDK/BranchPasteControl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// BranchPasteControl.h
// Branch
//
// Created by Nidhi Dixit on 9/26/22.
// Copyright © 2022 Branch, Inc. All rights reserved.
//

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 160000
API_AVAILABLE(ios(16.0))
@interface BranchPasteControl : UIView <UIPasteConfigurationSupporting>

// This is designated initializer. All other initializers are blocked.
- (instancetype)initWithFrame:(CGRect)frame AndConfiguration:( UIPasteControlConfiguration * _Nullable) config NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
- (instancetype)initWithCoder:(NSCoder *)coder NS_UNAVAILABLE;

@end
#endif
NS_ASSUME_NONNULL_END
55 changes: 55 additions & 0 deletions Branch-SDK/BranchPasteControl.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//
// BranchPasteControl.m
// Branch
//
// Created by Nidhi Dixit on 9/26/22.
// Copyright © 2022 Branch, Inc. All rights reserved.
//

#import "BranchPasteControl.h"
#import "Branch.h"

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 160000

@implementation BranchPasteControl

@synthesize pasteConfiguration;

// Make it designated initializer and block all others.
- (instancetype)initWithFrame:(CGRect)frame AndConfiguration:( UIPasteControlConfiguration * _Nullable) config {

self = [super initWithFrame:frame];
if(self){
// 1. Create a UIPasteControl with dimensions = frame or with given configuration // 2. add it as subview to current view
UIPasteControl *pc;
CGRect rect = CGRectMake(0, 0, frame.size.width, frame.size.height);

if(config){
pc = [[UIPasteControl alloc] initWithConfiguration:config];
pc.frame = rect;
} else {

pc = [[UIPasteControl alloc] initWithFrame:rect];
}
[self addSubview:pc];

// 3. Setup pasteConfiguration
pasteConfiguration = [[UIPasteConfiguration alloc] initWithAcceptableTypeIdentifiers:@[UTTypeURL.identifier]];
pc.target = self;
}
return self;
}

- (void)pasteItemProviders:(NSArray<NSItemProvider *> *)itemProviders {
[[Branch getInstance] passPasteItemProviders:itemProviders];
}

- (BOOL)canPasteItemProviders:(NSArray<NSItemProvider *> *)itemProviders {
for (NSItemProvider* item in itemProviders)
if ( [item hasItemConformingToTypeIdentifier: UTTypeURL.identifier] )
return true;
return false;
}

@end
#endif
25 changes: 25 additions & 0 deletions Branch-TestBed/Branch-SDK-Tests/BNCPasteboardTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#import <XCTest/XCTest.h>
#import "BNCPasteboard.h"
#import "Branch.h"

@interface BNCPasteboardTests : XCTestCase

Expand Down Expand Up @@ -152,4 +153,28 @@ - (void)testCheckForBranchLink_noLink {
[self clearPasteboard];
}


- (void) testPassPasteControl {
#if !TARGET_OS_TV
if (@available(iOS 16.0, *)) {

long long timeStamp = ([[NSDate date] timeIntervalSince1970] - 5*60)*1000; // 5 minute earlier timestamp
NSString *urlString = [NSString stringWithFormat:@"https://bnctestbed-alternate.app.link/9R7MbTmnRtb?__branch_flow_type=viewapp&__branch_flow_id=1105940563590163783&__branch_mobile_deepview_type=1&nl_opt_in=1&_cpts=%lld", timeStamp];
NSURL *testURL = [[NSURL alloc] initWithString:urlString];

NSArray<NSItemProvider *> *itemProviders = @[[[NSItemProvider alloc] initWithItem:testURL typeIdentifier:UTTypeURL.identifier]];
XCTestExpectation *openExpectation = [self expectationWithDescription:@"Test open"];

[[Branch getInstance] initSessionWithLaunchOptions:@{} andRegisterDeepLinkHandler:^(NSDictionary *params, NSError *error) {
[openExpectation fulfill];
XCTAssertNil(error);
}];

[[Branch getInstance] passPasteItemProviders:itemProviders];
[self waitForExpectationsWithTimeout:5.0 handler:NULL];

}
#endif
}

@end
45 changes: 45 additions & 0 deletions Branch-TestBed/Branch-SDK-Tests/BranchEvent.Test.m
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,51 @@ - (void)testCustomOptOutEvent {
XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]);
}


- (void)testStandardInitiateStreamEvent {
BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventInitiateStream];

NSDictionary *eventDictionary = [event buildEventDictionary];
XCTAssertNotNil(eventDictionary);
XCTAssert([eventDictionary[@"name"] isEqualToString:@"INITIATE_STREAM"]);

BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary];
XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]);
}

- (void)testCustomInitiateStreamEvent {
BranchEvent *event = [BranchEvent customEventWithName:@"INITIATE_STREAM"];

NSDictionary *eventDictionary = [event buildEventDictionary];
XCTAssertNotNil(eventDictionary);
XCTAssert([eventDictionary[@"name"] isEqualToString:@"INITIATE_STREAM"]);

BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary];
XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]);
}

- (void)testStandardCompleteStreamEvent {
BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventCompleteStream];

NSDictionary *eventDictionary = [event buildEventDictionary];
XCTAssertNotNil(eventDictionary);
XCTAssert([eventDictionary[@"name"] isEqualToString:@"COMPLETE_STREAM"]);

BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary];
XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]);
}

- (void)testCustomCompleteStreamEvent {
BranchEvent *event = [BranchEvent customEventWithName:@"COMPLETE_STREAM"];

NSDictionary *eventDictionary = [event buildEventDictionary];
XCTAssertNotNil(eventDictionary);
XCTAssert([eventDictionary[@"name"] isEqualToString:@"COMPLETE_STREAM"]);

BranchEventRequest *request = [event buildRequestWithEventDictionary:eventDictionary];
XCTAssert([request.serverURL.absoluteString containsString:@"branch.io/v2/event/standard"]);
}

- (void)testJsonStringForAdTypeNone {
BranchEvent *event = [BranchEvent standardEvent:BranchStandardEventViewAd];
XCTAssertNil([event jsonStringForAdType:BranchEventAdTypeNone]);
Expand Down
Loading

0 comments on commit e235ec8

Please sign in to comment.