Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: branch sdk integration #283

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions Core/Core.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -126,12 +126,13 @@
07DDFCBD29A780BB00572595 /* UINavigationController+Animation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07DDFCBC29A780BB00572595 /* UINavigationController+Animation.swift */; };
07E0939F2B308D2800F1E4B2 /* Data_Certificate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07E0939E2B308D2800F1E4B2 /* Data_Certificate.swift */; };
141F1D302B7328D4009E81EB /* WebviewCookiesUpdateProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 141F1D2F2B7328D4009E81EB /* WebviewCookiesUpdateProtocol.swift */; };
142EDD6C2B831D1400F9F320 /* BranchSDK in Frameworks */ = {isa = PBXBuildFile; productRef = 142EDD6B2B831D1400F9F320 /* BranchSDK */; };
A53A32352B233DEC005FE38A /* ThemeConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = A53A32342B233DEC005FE38A /* ThemeConfig.swift */; };
A595689B2B6173DF00ED4F90 /* BranchConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = A595689A2B6173DF00ED4F90 /* BranchConfig.swift */; };
A5F4E7B52B61544A00ACD166 /* BrazeConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5F4E7B42B61544A00ACD166 /* BrazeConfig.swift */; };
BA30427F2B20B320009B64B7 /* SocialAuthError.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA30427D2B20B299009B64B7 /* SocialAuthError.swift */; };
BA4AFB442B6A5AF100A21367 /* CheckBoxView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA4AFB432B6A5AF100A21367 /* CheckBoxView.swift */; };
BA4AFB422B5A7A0900A21367 /* VideoDownloadQualityView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA4AFB412B5A7A0900A21367 /* VideoDownloadQualityView.swift */; };
BA4AFB442B6A5AF100A21367 /* CheckBoxView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA4AFB432B6A5AF100A21367 /* CheckBoxView.swift */; };
BA593F1C2AF8E498009ADB51 /* ScrollSlidingTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA593F1B2AF8E498009ADB51 /* ScrollSlidingTabBar.swift */; };
BA593F1E2AF8E4A0009ADB51 /* FrameReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA593F1D2AF8E4A0009ADB51 /* FrameReader.swift */; };
BA76135C2B21BC7300B599B7 /* SocialAuthResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA76135B2B21BC7300B599B7 /* SocialAuthResponse.swift */; };
Expand Down Expand Up @@ -307,8 +308,8 @@
A595689A2B6173DF00ED4F90 /* BranchConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BranchConfig.swift; sourceTree = "<group>"; };
A5F4E7B42B61544A00ACD166 /* BrazeConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BrazeConfig.swift; sourceTree = "<group>"; };
BA30427D2B20B299009B64B7 /* SocialAuthError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SocialAuthError.swift; sourceTree = "<group>"; };
BA4AFB432B6A5AF100A21367 /* CheckBoxView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckBoxView.swift; sourceTree = "<group>"; };
BA4AFB412B5A7A0900A21367 /* VideoDownloadQualityView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoDownloadQualityView.swift; sourceTree = "<group>"; };
BA4AFB432B6A5AF100A21367 /* CheckBoxView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckBoxView.swift; sourceTree = "<group>"; };
BA593F1B2AF8E498009ADB51 /* ScrollSlidingTabBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScrollSlidingTabBar.swift; sourceTree = "<group>"; };
BA593F1D2AF8E4A0009ADB51 /* FrameReader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FrameReader.swift; sourceTree = "<group>"; };
BA76135B2B21BC7300B599B7 /* SocialAuthResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocialAuthResponse.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -355,6 +356,7 @@
BAF0D4CB2AD6AE14007AC334 /* FacebookLogin in Frameworks */,
025EF2F62971740000B838AB /* YouTubePlayerKit in Frameworks */,
C8C446EF233F81B9FABB77D2 /* Pods_App_Core.framework in Frameworks */,
142EDD6C2B831D1400F9F320 /* BranchSDK in Frameworks */,
BA8FA66C2AD59BBC00EA029A /* GoogleSignIn in Frameworks */,
E055A5392B18DC95008D9E5E /* Theme.framework in Frameworks */,
);
Expand Down Expand Up @@ -870,6 +872,7 @@
025EF2F52971740000B838AB /* YouTubePlayerKit */,
BA8FA66B2AD59BBC00EA029A /* GoogleSignIn */,
BAF0D4CA2AD6AE14007AC334 /* FacebookLogin */,
142EDD6B2B831D1400F9F320 /* BranchSDK */,
);
productName = Core;
productReference = 0770DE0828D07831006D8A5D /* Core.framework */;
Expand Down Expand Up @@ -909,6 +912,7 @@
025EF2F42971740000B838AB /* XCRemoteSwiftPackageReference "YouTubePlayerKit" */,
BA8FA65E2AD574D700EA029A /* XCRemoteSwiftPackageReference "GoogleSignIn-iOS" */,
BA8FA6712AD6ABA300EA029A /* XCRemoteSwiftPackageReference "facebook-ios-sdk" */,
142EDD6A2B831D1400F9F320 /* XCRemoteSwiftPackageReference "ios-branch-sdk-spm" */,
);
productRefGroup = 0770DE0928D07831006D8A5D /* Products */;
projectDirPath = "";
Expand Down Expand Up @@ -2164,6 +2168,14 @@
minimumVersion = 1.5.0;
};
};
142EDD6A2B831D1400F9F320 /* XCRemoteSwiftPackageReference "ios-branch-sdk-spm" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/BranchMetrics/ios-branch-sdk-spm";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 3.2.0;
};
};
BA8FA65E2AD574D700EA029A /* XCRemoteSwiftPackageReference "GoogleSignIn-iOS" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/google/GoogleSignIn-iOS";
Expand All @@ -2188,6 +2200,11 @@
package = 025EF2F42971740000B838AB /* XCRemoteSwiftPackageReference "YouTubePlayerKit" */;
productName = YouTubePlayerKit;
};
142EDD6B2B831D1400F9F320 /* BranchSDK */ = {
isa = XCSwiftPackageProductDependency;
package = 142EDD6A2B831D1400F9F320 /* XCRemoteSwiftPackageReference "ios-branch-sdk-spm" */;
productName = BranchSDK;
};
BA8FA66B2AD59BBC00EA029A /* GoogleSignIn */ = {
isa = XCSwiftPackageProductDependency;
package = BA8FA65E2AD574D700EA029A /* XCRemoteSwiftPackageReference "GoogleSignIn-iOS" */;
Expand Down
3 changes: 2 additions & 1 deletion Core/Core/Configuration/Config/BranchConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ public final class BranchConfig: NSObject {

init(dictionary: [String: AnyObject]) {
super.init()
enabled = dictionary[BranchKeys.enabled] as? Bool == true
key = dictionary[BranchKeys.key] as? String
enabled = dictionary[BranchKeys.enabled] as? Bool ?? false && key?.isEmpty == false

}
}

Expand Down
6 changes: 6 additions & 0 deletions OpenEdX.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ALLOW_ENTITLEMENTS_MODIFICATION = YES;
CODE_SIGN_ENTITLEMENTS = OpenEdX/OpenEdX.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
Expand Down Expand Up @@ -727,6 +728,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ALLOW_ENTITLEMENTS_MODIFICATION = YES;
CODE_SIGN_ENTITLEMENTS = OpenEdX/OpenEdX.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
Expand Down Expand Up @@ -821,6 +823,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ALLOW_ENTITLEMENTS_MODIFICATION = YES;
CODE_SIGN_ENTITLEMENTS = OpenEdX/OpenEdX.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
Expand Down Expand Up @@ -909,6 +912,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ALLOW_ENTITLEMENTS_MODIFICATION = YES;
CODE_SIGN_ENTITLEMENTS = OpenEdX/OpenEdX.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
Expand Down Expand Up @@ -1057,6 +1061,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ALLOW_ENTITLEMENTS_MODIFICATION = YES;
CODE_SIGN_ENTITLEMENTS = OpenEdX/OpenEdX.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
Expand Down Expand Up @@ -1091,6 +1096,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ALLOW_ENTITLEMENTS_MODIFICATION = YES;
CODE_SIGN_ENTITLEMENTS = OpenEdX/OpenEdX.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
Expand Down
27 changes: 20 additions & 7 deletions OpenEdX/Managers/DeepLinkManager/DeepLinkManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,25 @@ import Core
import UIKit

public protocol DeepLinkService {
func configureWith(launchOptions: [UIApplication.LaunchOptionsKey: Any]?)
func handledURLWith(app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any]) -> Bool
func configureWith(
manager: DeepLinkManager,
config: ConfigProtocol,
launchOptions: [UIApplication.LaunchOptionsKey: Any]?
)

func handledURLWith(
app: UIApplication,
open url: URL,
options: [UIApplication.OpenURLOptionsKey: Any]
) -> Bool
}

class DeepLinkManager {
public class DeepLinkManager {
private var services: [DeepLinkService] = []
private let config: ConfigProtocol

// Init manager
public init(config: ConfigProtocol) {
self.config = config
services = servicesFor(config: config)
}

Expand All @@ -39,7 +49,7 @@ class DeepLinkManager {
// Configure services
func configureDeepLinkService(launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
for service in services {
service.configureWith(launchOptions: launchOptions)
service.configureWith(manager: self, config: config, launchOptions: launchOptions)
}
}

Expand All @@ -61,8 +71,11 @@ class DeepLinkManager {
}

// This method process the deep link with response parameters
func processDeepLink(with params: [String: Any]) {
if anyServiceEnabled {
func processDeepLink(with params: [AnyHashable: Any]?) {
guard let params = params else { return }

let deeplink = DeepLink(dictionary: params)
if anyServiceEnabled && deeplink.type != .none {
// redirect if possible
}
}
Expand Down
48 changes: 46 additions & 2 deletions OpenEdX/Managers/DeepLinkManager/Link/DeepLink.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,57 @@
//

import Foundation
import Core

enum DeepLinkType: String {
case courseDashboard = "course_dashboard"
case courseVideos = "course_videos"
case discussions = "course_discussion"
case courseDates = "course_dates"
case courseHandout = "course_handout"
case courseComponent = "course_component"
case courseAnnouncement = "course_announcement"
case discussionTopic = "discussion_topic"
case discussionPost = "discussion_post"
case discussionComment = "discussion_comment"
case discovery = "discovery"
case discoveryCourseDetail = "discovery_course_detail"
case discoveryProgramDetail = "discovery_program_detail"
case program = "program"
case programDetail = "program_detail"
case userProfile = "user_profile"
case profile = "profile"
case none
}

private enum DeepLinkKeys: String, RawStringExtractable {
case courseID = "course_id"
case pathID = "path_id"
case screenName = "screen_name"
case topicID = "topic_id"
case threadID = "thread_id"
case commentID = "comment_id"
case componentID = "component_id"
}

public class DeepLink {
init(dictionary: [String: Any]) {

let courseID: String?
let screenName: String?
let pathID: String?
let topicID: String?
let threadID: String?
let commentID: String?
let componentID: String?
var type: DeepLinkType

init(dictionary: [AnyHashable: Any]) {
courseID = dictionary[DeepLinkKeys.courseID] as? String
screenName = dictionary[DeepLinkKeys.screenName] as? String
pathID = dictionary[DeepLinkKeys.pathID] as? String
topicID = dictionary[DeepLinkKeys.topicID] as? String
threadID = dictionary[DeepLinkKeys.threadID] as? String
commentID = dictionary[DeepLinkKeys.commentID] as? String
componentID = dictionary[DeepLinkKeys.componentID] as? String
type = DeepLinkType(rawValue: screenName ?? DeepLinkType.none.rawValue) ?? .none
}
}
13 changes: 7 additions & 6 deletions OpenEdX/Managers/DeepLinkManager/Link/PushLink.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
//

import Foundation
import Core

enum DataKeys: String {
enum DataKeys: String, RawStringExtractable {
case title
case body
case aps
Expand All @@ -19,11 +20,11 @@ public class PushLink: DeepLink {
let title: String?
let body: String?

override init(dictionary: [String: Any]) {
let aps = dictionary[DataKeys.aps.rawValue] as? [String: Any]
let alert = aps?[DataKeys.alert.rawValue] as? [String: Any]
title = alert?[DataKeys.title.rawValue] as? String
body = alert?[DataKeys.body.rawValue] as? String
override init(dictionary: [AnyHashable: Any]) {
let aps = dictionary[DataKeys.aps] as? [String: Any]
let alert = aps?[DataKeys.alert] as? [String: Any]
title = alert?[DataKeys.title] as? String
body = alert?[DataKeys.body] as? String

super.init(dictionary: dictionary)
}
Expand Down
19 changes: 17 additions & 2 deletions OpenEdX/Managers/DeepLinkManager/Services/BranchService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,26 @@

import Foundation
import UIKit
import Core
import BranchSDK

class BranchService: DeepLinkService {
// configure service
func configureWith(launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
func configureWith(
manager: DeepLinkManager,
config: ConfigProtocol,
launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) {
guard let key = config.branch.key, config.branch.enabled else { return }
Branch.setBranchKey(key)

if Branch.branchKey() != nil {
Branch.getInstance().initSession(launchOptions: launchOptions) { params, error in
guard let params = params, error == nil else { return }

manager.processDeepLink(with: params)
}
}
}

// handle url and call DeepLinkanager.processDeepLink() with params
Expand All @@ -20,6 +35,6 @@ class BranchService: DeepLinkService {
open url: URL,
options: [UIApplication.OpenURLOptionsKey: Any]
) -> Bool {
false
return Branch.getInstance().application(app, open: url, options: options)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ protocol PushNotificationsListener {

extension PushNotificationsListener {
func didReceiveRemoteNotification(userInfo: [AnyHashable: Any]) {
guard let dictionary = userInfo as? [String: Any],
guard let dictionary = userInfo as? [String: AnyHashable],
shouldListenNotification(userinfo: userInfo),
let deepLinkManager = Container.shared.resolve(DeepLinkManager.self)
else { return }
Expand Down
7 changes: 7 additions & 0 deletions OpenEdX/OpenEdX.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,12 @@
<array>
<string>Default</string>
</array>
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:edx.app.link</string>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this should be moved to whitelabel script too? Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We/community can add this capability to the whitelabel script to modify the entitlements if needed. But I think we can use edx as a placeholder in the codebase. Thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please let's move it to the config file if possible.
It will be much clearer for the community to configure everything from the configuration file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@volodymyr-chekyrta @rnr I've also made the Associated Domains configurable and it will be added when Branch is enabled and will also configure values as per DEEPLINK_PREFIX

Copy link
Contributor Author

@saeedbashir saeedbashir Feb 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@volodymyr-chekyrta @rnr I've added the default values as well. The scene of info.plist and entitlements is different. The info.plist is baked into the IPA file so the updated file is directly modified inside the IPA, hence to trackable change is there.

But in the case of entitlements, the changes are directly applied to the entitlements file and they are git trackable if there will be any change because of prefix. That's why I've added edx as a placeholder value so that for edX and openedX the change will not appear in the changeset. Otherwise, we have to remove the changes of this file before committing any changes and we can't even add it to git ignore because in the future more entitlements can be added.

<string>applinks:edx-alternate.app.link</string>
<string>applinks:edx.test-app.link</string>
<string>applinks:edx-alternate.test-app.link</string>
</array>
</dict>
</plist>
2 changes: 1 addition & 1 deletion Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -182,4 +182,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: 544edab2f9ecc4ac18973fb8865f1d0613ec8a28

COCOAPODS: 1.15.0
COCOAPODS: 1.15.2
Loading
Loading