diff --git a/mParticle-Button.xcodeproj/project.pbxproj b/mParticle-Button.xcodeproj/project.pbxproj index 11ac866..87c522e 100644 --- a/mParticle-Button.xcodeproj/project.pbxproj +++ b/mParticle-Button.xcodeproj/project.pbxproj @@ -7,12 +7,10 @@ objects = { /* Begin PBXBuildFile section */ - DB0773DB1DB916610031F3E3 /* mParticle_Button.h in Headers */ = {isa = PBXBuildFile; fileRef = DB0773D91DB916610031F3E3 /* mParticle_Button.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DB0773E31DB916B80031F3E3 /* MPKitButton.h in Headers */ = {isa = PBXBuildFile; fileRef = DB0773E11DB916B80031F3E3 /* MPKitButton.h */; settings = {ATTRIBUTES = (Public, ); }; }; - DB0773E41DB916B80031F3E3 /* MPKitButton.m in Sources */ = {isa = PBXBuildFile; fileRef = DB0773E21DB916B80031F3E3 /* MPKitButton.m */; }; + 83EE014A282CA8B4005F142B /* KitButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83EE0149282CA8B4005F142B /* KitButton.swift */; }; + 83EE014C282D4D01005F142B /* mParticle-ButtonTests-Bridging-Header.h in Headers */ = {isa = PBXBuildFile; fileRef = 83EE014B282D4D01005F142B /* mParticle-ButtonTests-Bridging-Header.h */; }; DE811925214C4CF900AAC951 /* mParticle_Button.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DB0773D61DB916610031F3E3 /* mParticle_Button.framework */; }; DE81192F214C4F5500AAC951 /* mParticle-ButtonTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE81192D214C4F5400AAC951 /* mParticle-ButtonTests.swift */; }; - DEAA37222180E11800915875 /* MPKitButton+ButtonTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DEAA37212180E11800915875 /* MPKitButton+ButtonTests.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -26,18 +24,14 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 83EE0149282CA8B4005F142B /* KitButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KitButton.swift; sourceTree = ""; }; + 83EE014B282D4D01005F142B /* mParticle-ButtonTests-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "mParticle-ButtonTests-Bridging-Header.h"; sourceTree = ""; }; DB0773D61DB916610031F3E3 /* mParticle_Button.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = mParticle_Button.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - DB0773D91DB916610031F3E3 /* mParticle_Button.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = mParticle_Button.h; sourceTree = ""; }; DB0773DA1DB916610031F3E3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - DB0773E11DB916B80031F3E3 /* MPKitButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPKitButton.h; sourceTree = ""; }; - DB0773E21DB916B80031F3E3 /* MPKitButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPKitButton.m; sourceTree = ""; }; DE0F93D12149694E00E0FF7F /* mParticle-Button.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; path = "mParticle-Button.podspec"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; DE811920214C4CF900AAC951 /* mParticle-ButtonTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "mParticle-ButtonTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; DE81192D214C4F5400AAC951 /* mParticle-ButtonTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "mParticle-ButtonTests.swift"; sourceTree = ""; }; DE81192E214C4F5400AAC951 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - DEAA371F2180E11700915875 /* mParticle-ButtonTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "mParticle-ButtonTests-Bridging-Header.h"; sourceTree = ""; }; - DEAA37202180E11800915875 /* MPKitButton+ButtonTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MPKitButton+ButtonTests.h"; sourceTree = ""; }; - DEAA37212180E11800915875 /* MPKitButton+ButtonTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "MPKitButton+ButtonTests.m"; sourceTree = ""; }; DEEEE6A3214C57BF006B5C06 /* ButtonMerchant.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ButtonMerchant.framework; path = Carthage/Build/iOS/ButtonMerchant.framework; sourceTree = ""; }; DEEEE6A4214C57CA006B5C06 /* mParticle_Apple_SDK.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = mParticle_Apple_SDK.framework; path = Carthage/Build/iOS/mParticle_Apple_SDK.framework; sourceTree = ""; }; /* End PBXFileReference section */ @@ -93,10 +87,8 @@ DB0773D81DB916610031F3E3 /* mParticle-Button */ = { isa = PBXGroup; children = ( - DB0773E11DB916B80031F3E3 /* MPKitButton.h */, - DB0773E21DB916B80031F3E3 /* MPKitButton.m */, - DB0773D91DB916610031F3E3 /* mParticle_Button.h */, DB0773DA1DB916610031F3E3 /* Info.plist */, + 83EE0149282CA8B4005F142B /* KitButton.swift */, ); path = "mParticle-Button"; sourceTree = ""; @@ -114,9 +106,7 @@ DEAA37232180E11F00915875 /* Helpers */ = { isa = PBXGroup; children = ( - DEAA371F2180E11700915875 /* mParticle-ButtonTests-Bridging-Header.h */, - DEAA37202180E11800915875 /* MPKitButton+ButtonTests.h */, - DEAA37212180E11800915875 /* MPKitButton+ButtonTests.m */, + 83EE014B282D4D01005F142B /* mParticle-ButtonTests-Bridging-Header.h */, ); path = Helpers; sourceTree = ""; @@ -128,8 +118,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - DB0773E31DB916B80031F3E3 /* MPKitButton.h in Headers */, - DB0773DB1DB916610031F3E3 /* mParticle_Button.h in Headers */, + 83EE014C282D4D01005F142B /* mParticle-ButtonTests-Bridging-Header.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -187,7 +176,7 @@ DB0773D51DB916610031F3E3 = { CreatedOnToolsVersion = 8.0; DevelopmentTeam = 39F27QYP2C; - LastSwiftMigration = 0940; + LastSwiftMigration = 1300; ProvisioningStyle = Automatic; }; DE81191F214C4CF900AAC951 = { @@ -274,7 +263,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - DB0773E41DB916B80031F3E3 /* MPKitButton.m in Sources */, + 83EE014A282CA8B4005F142B /* KitButton.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -283,7 +272,6 @@ buildActionMask = 2147483647; files = ( DE81192F214C4F5500AAC951 /* mParticle-ButtonTests.swift in Sources */, - DEAA37222180E11800915875 /* MPKitButton+ButtonTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -436,7 +424,7 @@ PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; }; name = Debug; }; @@ -463,13 +451,14 @@ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; }; name = Release; }; DE811929214C4CF900AAC951 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = YES; @@ -500,6 +489,7 @@ DE81192A214C4CF900AAC951 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_ENABLE_MODULES = YES; diff --git a/mParticle-Button/KitButton.swift b/mParticle-Button/KitButton.swift new file mode 100644 index 0000000..bbb8ea6 --- /dev/null +++ b/mParticle-Button/KitButton.swift @@ -0,0 +1,173 @@ +// +// KitButton.swift +// mParticle-Button +// +// Created by Osvaldo Rafael Mercado Espinel on 11/05/22. +// Copyright © 2022 mParticle. All rights reserved. +// + +import Foundation +import mParticle_Apple_SDK +import ButtonMerchant + +public class MPIButton { + + public var attributionToken = { + return ButtonMerchant.attributionToken + }() +} + +public let BTNMPKitVersion = "2.0.0" + +public let BTNReferrerTokenDefaultsKey = "com.usebutton.referrer" +public let BTNLinkFetchStatusDefaultsKey = "com.usebutton.link.fetched" + +public let MPKitButtonAttributionResultKey = "mParticle-Button Attribution Result" +public let BTNPostInstallURLKey = "BTNPostInstallURLKey" + +public let MPKitButtonErrorDomain = "com.mparticle.kits.button" +public let MPKitButtonErrorMessageKey = "mParticle-Button Error" +public let MPKitButtonIntegrationAttribution = "com.usebutton.source_token" + +@objc(MPKitButton) +public class KitButton: NSObject, MPKitProtocol { + + public var mParticleInstance: MParticle! = MParticle.sharedInstance() + var button: MPIButton! + var applicationId: String? + public var defaultCenter: NotificationCenter! = NotificationCenter.default + public var started: Bool = false + var configuration: [AnyHashable : Any] = [:] + + public var kitApi: MPKitAPI? + + public var providerKitInstance: Any? { + return started ? button : nil + } + + public static func kitCode() -> NSNumber { + return 1022 + } + + public override init() { + super.init() + let kitRegister = MPKitRegister(name: "Button", className: self.description) + + MParticle.registerExtension(kitRegister!) + } + + func trackIncomingURL(url: URL) { + ButtonMerchant.trackIncomingURL(url) + } + + public func didFinishLaunching(withConfiguration configuration: [AnyHashable : Any]) -> MPKitExecStatus { + var execStatus: MPKitExecStatus! + + self.button = MPIButton() + self.applicationId = configuration["application_id"] as? String + + guard let applicationId = self.applicationId else { + execStatus = MPKitExecStatus(sdkCode: KitButton.kitCode(), returnCode: .requirementsNotMet) + return execStatus + } + + ButtonMerchant.configure(applicationId: applicationId) + + self.defaultCenter.addObserver(self, selector: #selector(observeAttributionTokenDidChangeNotification(_:)), name: ButtonMerchant.AttributionTokenDidChangeNotification as NSNotification.Name, object: nil) + + self.configuration = configuration + self.started = true + + DispatchQueue.main.async { + let userInfo = [mParticleKitInstanceKey: KitButton.kitCode()] + NotificationCenter.default.post(name: .mParticleKitDidBecomeActive, object: nil, userInfo: userInfo) + self.checkForAttribution() + } + + execStatus = MPKitExecStatus(sdkCode: KitButton.kitCode(), returnCode: .success) + return execStatus + } + + public func open(_ url: URL, options: [String : Any]? = nil) -> MPKitExecStatus { + self.trackIncomingURL(url: url) + return MPKitExecStatus(sdkCode: KitButton.kitCode(), returnCode: .success) + } + + public func open(_ url: URL, sourceApplication: String?, annotation: Any?) -> MPKitExecStatus { + self.trackIncomingURL(url: url) + return MPKitExecStatus(sdkCode: KitButton.kitCode(), returnCode: .success) + } + + public func `continue`(_ userActivity: NSUserActivity, restorationHandler: @escaping ([Any]?) -> Void) -> MPKitExecStatus { + guard let url = userActivity.webpageURL else { return MPKitExecStatus() } + self.trackIncomingURL(url: url) + return MPKitExecStatus(sdkCode: KitButton.kitCode(), returnCode: .success) + } + + public func logBaseEvent(_ event: MPBaseEvent) -> MPKitExecStatus { + guard let event = event as? MPCommerceEvent else { + return MPKitExecStatus(sdkCode: KitButton.kitCode(), returnCode: .unavailable) + } + + var code: MPKitReturnCode = .unavailable + let products = self.buttonProducts(from: event.products) + + switch (event.action) { + case .viewDetail: + ButtonMerchant.activity.productViewed(products.first) + code = .success + case .addToCart: + ButtonMerchant.activity.productAddedToCart(products.first) + code = .success + case .checkout: + ButtonMerchant.activity.cartViewed(products) + code = .success + default: break + } + + return MPKitExecStatus(sdkCode: KitButton.kitCode(), returnCode: code) + } + + private func error(with message: String) -> NSError { + let error = NSError(domain: MPKitButtonErrorDomain, code: 0, userInfo: [MPKitButtonErrorMessageKey: message]) + return error + } + + private func checkForAttribution() { + ButtonMerchant.handlePostInstallURL { postInstallURL, error in + if error != nil || postInstallURL == nil { + let attributionError = self.error(with: "No attribution information available.") + self.kitApi?.onAttributionComplete(with: nil, error: attributionError) + } + + let linkInfo = [ BTNPostInstallURLKey: postInstallURL?.absoluteString ?? "" ] + let attributionResult = MPAttributionResult() + attributionResult.linkInfo = linkInfo + + } + } + + @objc + private func observeAttributionTokenDidChangeNotification(_ note: NSNotification) { + if let attributionToken = note.userInfo?[ButtonMerchant.AttributionTokenKey] as? String { + let integrationAttributes = [MPKitButtonIntegrationAttribution: attributionToken] + self.mParticleInstance.setIntegrationAttributes(integrationAttributes, forKit: KitButton.kitCode()) + } + } + + private func buttonProducts(from products: [MPProduct]?) -> [ButtonProduct] { + return products?.map { + let buttonProduct = ButtonProduct() + buttonProduct.name = $0.name + buttonProduct.id = $0.sku + buttonProduct.value = Int(($0.price?.doubleValue ?? 0) * 100) + buttonProduct.quantity = $0.quantity.intValue + if let category = $0.category { + buttonProduct.categories = [category] + } + buttonProduct.attributes = ["btn_product_count": "\(products?.count ?? 0)"] + return buttonProduct + } ?? [] + } + +} diff --git a/mParticle-Button/MPKitButton.h b/mParticle-Button/MPKitButton.h deleted file mode 100644 index a31cb23..0000000 --- a/mParticle-Button/MPKitButton.h +++ /dev/null @@ -1,34 +0,0 @@ -#import -#if defined(__has_include) && __has_include() -#import -#else -#import "mParticle.h" -#endif - -extern NSString * _Nonnull const MPKitButtonErrorDomain; -extern NSString * _Nonnull const MPKitButtonErrorMessageKey; - -/// A key into the linkInfo passed to the onAttributionComplete handler. -/// (Note: This key will be set to the same value as `BTNDeferredDeepLinkURLKey`. -/// We added it later to match the naming convention used by other kits.) -extern NSString * _Nonnull const MPKitButtonAttributionResultKey; - -/// A key into the linkInfo passed to the onAttributionComplete handler. -extern NSString * _Nonnull const BTNPostInstallURLKey; - -#pragma mark - MPIButton -@interface MPIButton : NSObject - -/// Returns the Button referrer token if present (i.e. btn_ref). -@property (nonatomic, copy, readonly, nullable) NSString *attributionToken; - -@end - - -#pragma mark - MPKitButton -@interface MPKitButton : NSObject - -@property (nonatomic, strong, nonnull) NSDictionary *configuration; -@property (nonatomic, unsafe_unretained, readonly) BOOL started; - -@end diff --git a/mParticle-Button/MPKitButton.m b/mParticle-Button/MPKitButton.m deleted file mode 100644 index 2093a6b..0000000 --- a/mParticle-Button/MPKitButton.m +++ /dev/null @@ -1,244 +0,0 @@ -// -// MPKitButton.m -// -// Copyright 2019 Button, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -#import "MPKitButton.h" - -@import ButtonMerchant; - -static NSString * const BTNMPKitVersion = @"2.0.0"; - -static NSString * const BTNReferrerTokenDefaultsKey = @"com.usebutton.referrer"; -static NSString * const BTNLinkFetchStatusDefaultsKey = @"com.usebutton.link.fetched"; - -NSString * const MPKitButtonAttributionResultKey = @"mParticle-Button Attribution Result"; -NSString * const BTNPostInstallURLKey = @"BTNPostInstallURLKey"; - -NSString * const MPKitButtonErrorDomain = @"com.mparticle.kits.button"; -NSString * const MPKitButtonErrorMessageKey = @"mParticle-Button Error"; -NSString * const MPKitButtonIntegrationAttribution = @"com.usebutton.source_token"; - - -#pragma mark - MPIButton - -@implementation MPIButton - -- (instancetype)init { - self = [super init]; - return self; -} - - -- (NSString *)attributionToken { - return ButtonMerchant.attributionToken; -} - - -@end - - -#pragma mark - MPKitButton - -@interface MPKitButton () - -@property (nonatomic, strong) MParticle *mParticleInstance; -@property (nonatomic, strong, nonnull) MPIButton *button; -@property (nonatomic, copy) NSString *applicationId; -@property (nonatomic, strong) NSNotificationCenter *defaultCenter; - -@end - - -@implementation MPKitButton - -@synthesize kitApi = _kitApi; - -+ (NSNumber *)kitCode { - return @1022; -} - - -+ (void)load { - MPKitRegister *kitRegister = [[MPKitRegister alloc] initWithName:@"Button" - className:NSStringFromClass(self)]; - [MParticle registerExtension:kitRegister]; -} - - -- (MParticle *)mParticleInstance { - if (!_mParticleInstance) { - _mParticleInstance = [MParticle sharedInstance]; - } - return _mParticleInstance; -} - - -- (NSNotificationCenter *)defaultCenter { - if (!_defaultCenter) { - _defaultCenter = NSNotificationCenter.defaultCenter; - } - return _defaultCenter; -} - - -- (void)trackIncomingURL:(NSURL *)url { - if (!url) { - return; - } - [ButtonMerchant trackIncomingURL:url]; -} - - -#pragma mark - MPKitInstanceProtocol methods - -- (MPKitExecStatus *)didFinishLaunchingWithConfiguration:(NSDictionary *)configuration { - MPKitExecStatus *execStatus = nil; - _button = [[MPIButton alloc] init]; - _applicationId = [configuration[@"application_id"] copy]; - if (!_applicationId) { - execStatus = [[MPKitExecStatus alloc] initWithSDKCode:[[self class] kitCode] returnCode:MPKitReturnCodeRequirementsNotMet]; - return execStatus; - } - - [ButtonMerchant configureWithApplicationId:_applicationId]; - [self.defaultCenter addObserver:self - selector:@selector(observeAttributionTokenDidChangeNotification:) - name:ButtonMerchant.AttributionTokenDidChangeNotification - object:nil]; - - _configuration = configuration; - _started = YES; - - dispatch_async(dispatch_get_main_queue(), ^{ - NSDictionary *userInfo = @{ mParticleKitInstanceKey: [[self class] kitCode] }; - [[NSNotificationCenter defaultCenter] postNotificationName:mParticleKitDidBecomeActiveNotification object:nil userInfo:userInfo]; - [self checkForAttribution]; - }); - - execStatus = [[MPKitExecStatus alloc] initWithSDKCode:[[self class] kitCode] returnCode:MPKitReturnCodeSuccess]; - - return execStatus; -} - - -- (id)providerKitInstance { - return [self started] ? self.button : nil; -} - - -- (nonnull MPKitExecStatus *)openURL:(nonnull NSURL *)url options:(nullable NSDictionary *)options { - [self trackIncomingURL:url]; - return [[MPKitExecStatus alloc] initWithSDKCode:[[self class] kitCode] - returnCode:MPKitReturnCodeSuccess]; -} - - -- (nonnull MPKitExecStatus *)openURL:(nonnull NSURL *)url sourceApplication:(nullable NSString *)sourceApplication annotation:(nullable id)annotation { - [self trackIncomingURL:url]; - return [[MPKitExecStatus alloc] initWithSDKCode:[[self class] kitCode] - returnCode:MPKitReturnCodeSuccess]; -} - - -- (nonnull MPKitExecStatus *)continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(void(^ _Nonnull)(NSArray * _Nullable restorableObjects))restorationHandler { - [self trackIncomingURL:userActivity.webpageURL]; - return [[MPKitExecStatus alloc] initWithSDKCode:[[self class] kitCode] - returnCode:MPKitReturnCodeSuccess]; -} - - -- (nonnull MPKitExecStatus *)logBaseEvent:(nonnull MPCommerceEvent *)event { - if (![event isKindOfClass:[MPCommerceEvent class]] || !event.products) { - return [[MPKitExecStatus alloc] initWithSDKCode:[[self class] kitCode] - returnCode:MPKitReturnCodeUnavailable]; - } - MPKitReturnCode code = MPKitReturnCodeUnavailable; - - NSArray *products = [self buttonProductsFromProducts:event.products]; - - switch (event.action) { - case MPCommerceEventActionViewDetail: - [ButtonMerchant.activity productViewed:products.firstObject]; - code = MPKitReturnCodeSuccess; - break; - case MPCommerceEventActionAddToCart: - [ButtonMerchant.activity productAddedToCart:products.firstObject]; - code = MPKitReturnCodeSuccess; - break; - case MPCommerceEventActionCheckout: - [ButtonMerchant.activity cartViewed:products]; - code = MPKitReturnCodeSuccess; - break; - default: - break; - } - - return [[MPKitExecStatus alloc] initWithSDKCode:[[self class] kitCode] - returnCode:code]; -} - - -#pragma mark - Private Methods - -- (NSError *)errorWithMessage:(NSString *)message { - NSError *error = [NSError errorWithDomain:MPKitButtonErrorDomain code:0 userInfo:@{MPKitButtonErrorMessageKey: message}]; - return error; -} - - -- (void)checkForAttribution { - [ButtonMerchant handlePostInstallURL:^(NSURL * _Nullable postInstallURL, NSError * _Nullable error) { - if (error || !postInstallURL) { - NSError *attributionError = [self errorWithMessage:@"No attribution information available."]; - [self->_kitApi onAttributionCompleteWithResult:nil error:attributionError]; - return; - } - NSDictionary *linkInfo = @{ BTNPostInstallURLKey: postInstallURL.absoluteString }; - MPAttributionResult *attributionResult = [[MPAttributionResult alloc] init]; - attributionResult.linkInfo = linkInfo; - [self->_kitApi onAttributionCompleteWithResult:attributionResult error:nil]; - }]; -} - - -- (void)observeAttributionTokenDidChangeNotification:(NSNotification *)note { - NSString *attributionToken = note.userInfo[ButtonMerchant.AttributionTokenKey]; - if (attributionToken) { - NSDictionary *integrationAttributes = @{ MPKitButtonIntegrationAttribution: attributionToken }; - [self.mParticleInstance setIntegrationAttributes:integrationAttributes forKit:[[self class] kitCode]]; - } -} - - -- (NSArray *)buttonProductsFromProducts:(NSArray *)products { - NSMutableArray *buttonProducts = [NSMutableArray array]; - for (MPProduct *product in products) { - ButtonProduct *buttonProduct = [ButtonProduct new]; - buttonProduct.name = product.name; - buttonProduct.id = product.sku; - buttonProduct.value = (NSInteger)(product.price.doubleValue * 100); - buttonProduct.quantity = product.quantity.integerValue; - if (product.category) { - buttonProduct.categories = @[product.category]; - } - buttonProduct.attributes = @{@"btn_product_count" : @(products.count).stringValue}; - [buttonProducts addObject:buttonProduct]; - } - return buttonProducts; -} - -@end diff --git a/mParticle-Button/mParticle_Button.h b/mParticle-Button/mParticle_Button.h deleted file mode 100644 index 17d05c2..0000000 --- a/mParticle-Button/mParticle_Button.h +++ /dev/null @@ -1,15 +0,0 @@ -#import - -//! Project version number for mParticle-Button. -FOUNDATION_EXPORT double mParticle_ButtonVersionNumber; - -//! Project version string for mParticle-Button. -FOUNDATION_EXPORT const unsigned char mParticle_ButtonVersionString[]; - -// In this header, you should import all the public headers of your framework using statements like #import - -#if defined(__has_include) && __has_include() -#import -#else -#import "MPKitButton.h" -#endif diff --git a/mParticle-ButtonTests/Helpers/MPKitButton+ButtonTests.h b/mParticle-ButtonTests/Helpers/MPKitButton+ButtonTests.h deleted file mode 100644 index be799fa..0000000 --- a/mParticle-ButtonTests/Helpers/MPKitButton+ButtonTests.h +++ /dev/null @@ -1,8 +0,0 @@ -#import "mParticle_Button.h" - -@interface MPKitButton (ButtonTests) -@property (nonatomic, strong) MParticle *mParticleInstance; -@property (nonatomic, strong) NSNotificationCenter *defaultCenter; -@end - - diff --git a/mParticle-ButtonTests/Helpers/MPKitButton+ButtonTests.m b/mParticle-ButtonTests/Helpers/MPKitButton+ButtonTests.m deleted file mode 100644 index aec7cc7..0000000 --- a/mParticle-ButtonTests/Helpers/MPKitButton+ButtonTests.m +++ /dev/null @@ -1,6 +0,0 @@ -#import "MPKitButton+ButtonTests.h" - -@implementation MPKitButton (ButtonTests) -@dynamic mParticleInstance; -@dynamic defaultCenter; -@end diff --git a/mParticle-ButtonTests/Helpers/mParticle-ButtonTests-Bridging-Header.h b/mParticle-ButtonTests/Helpers/mParticle-ButtonTests-Bridging-Header.h index a397745..8b13789 100644 --- a/mParticle-ButtonTests/Helpers/mParticle-ButtonTests-Bridging-Header.h +++ b/mParticle-ButtonTests/Helpers/mParticle-ButtonTests-Bridging-Header.h @@ -1 +1 @@ -#import "MPKitButton+ButtonTests.h" + diff --git a/mParticle-ButtonTests/mParticle-ButtonTests.swift b/mParticle-ButtonTests/mParticle-ButtonTests.swift index 5a54ca0..6472945 100644 --- a/mParticle-ButtonTests/mParticle-ButtonTests.swift +++ b/mParticle-ButtonTests/mParticle-ButtonTests.swift @@ -1,6 +1,7 @@ import XCTest import ButtonMerchant import mParticle_Button +import mParticle_Apple_SDK class Actual { static var applicationId: String? @@ -65,7 +66,7 @@ class TestMPKitAPI: MPKitAPI { } class TestNotificationCenter: NotificationCenter { - var actualObserver: MPKitButton? + var actualObserver: KitButton? var actualSelector: Selector? var actualName: NSNotification.Name? var actualObject: Any? @@ -73,7 +74,7 @@ class TestNotificationCenter: NotificationCenter { selector aSelector: Selector, name aName: NSNotification.Name?, object anObject: Any?) { - actualObserver = observer as? MPKitButton + actualObserver = observer as? KitButton actualSelector = aSelector actualName = aName actualObject = anObject @@ -83,7 +84,7 @@ class TestNotificationCenter: NotificationCenter { class mParticle_ButtonTests: XCTestCase { var testMParticleInstance: TestMParticle! - var buttonKit: MPKitButton! + var buttonKit: KitButton! var buttonInstance: MPIButton! var applicationId: String = "app-\(arc4random_uniform(10000))" @@ -96,7 +97,7 @@ class mParticle_ButtonTests: XCTestCase { Stub.error = nil // Start the Button kit. - buttonKit = MPKitButton() + buttonKit = KitButton() testMParticleInstance = TestMParticle() buttonKit.mParticleInstance = testMParticleInstance let configuration = ["application_id": applicationId] @@ -105,7 +106,7 @@ class mParticle_ButtonTests: XCTestCase { } func testKitCode() { - XCTAssertEqual(MPKitButton.kitCode(), 1022) + XCTAssertEqual(KitButton.kitCode(), 1022) } func testDidFinishLaunchingWithConfiguration() { @@ -175,7 +176,7 @@ class mParticle_ButtonTests: XCTestCase { func testPostInstallCheckOnAttribution() { // Arrange - buttonKit = MPKitButton() + buttonKit = KitButton() let expectation = self.expectation(description: "post-install-url-check") let configuration = ["application_id": applicationId] let attributionToken = "testtoken-\(arc4random_uniform(10000))" @@ -202,7 +203,7 @@ class mParticle_ButtonTests: XCTestCase { func testPostInstallCheckOnNoAttribution() { // Arrange - buttonKit = MPKitButton() + buttonKit = KitButton() let expectation = self.expectation(description: "post-install-url-check") let configuration = ["application_id": applicationId] let testKitApi = TestMPKitAPI() @@ -227,7 +228,7 @@ class mParticle_ButtonTests: XCTestCase { func testPostInstallCheckOnError() { // Arrange - buttonKit = MPKitButton() + buttonKit = KitButton() let expectation = self.expectation(description: "post-install-url-check") let configuration = ["application_id": applicationId] let testKitApi = TestMPKitAPI() @@ -263,7 +264,7 @@ class mParticle_ButtonTests: XCTestCase { func testLogProductViewedEventInvokesButtonActivity() { // Arrange - buttonKit = MPKitButton() + buttonKit = KitButton() let product = MPProduct(name: "some name", sku: "some sku", quantity: NSNumber(integerLiteral: 2), price: NSNumber(floatLiteral: 1.99)) product.category = "some category" let event = MPCommerceEvent(action: .viewDetail, product: product) @@ -285,7 +286,7 @@ class mParticle_ButtonTests: XCTestCase { func testLogProductAddedToCartEventInvokesButtonActivity() { // Arrange - buttonKit = MPKitButton() + buttonKit = KitButton() let product = MPProduct(name: "some name", sku: "some sku", quantity: NSNumber(integerLiteral: 2), price: NSNumber(floatLiteral: 1.99)) product.category = "some category" let event = MPCommerceEvent(action: .addToCart, product: product) @@ -307,7 +308,7 @@ class mParticle_ButtonTests: XCTestCase { func testLogCheckoutEventInvokesButtonActivity() { // Arrange - buttonKit = MPKitButton() + buttonKit = KitButton() let product = MPProduct(name: "some name", sku: "some sku", quantity: NSNumber(integerLiteral: 2), price: NSNumber(floatLiteral: 1.99)) product.category = "some category" let event = MPCommerceEvent(action: .checkout, product: product)