[iOS] support deferred deeplinks. Don't show whats new on start by deeplink

This commit is contained in:
Aleksey Belouosv 2019-04-25 12:55:03 +03:00 committed by Arsentiy Milchakov
parent faba7a1975
commit 188b21d4b1
33 changed files with 1036 additions and 405 deletions

View file

@ -25,6 +25,7 @@
#import "FacebookNativeAdAdapter.h"
#import "LocalNotificationManager.h"
#import "CoreNotificationWrapper.h"
#import "DeepLinkHelper.h"
#import "MapViewController.h"
#import "MWMActivityIndicator.h"
#import "MWMActivityViewController.h"

View file

@ -434,7 +434,7 @@ extern NSString * const kAlohalyticsTapEventKey;
if (ownerController.navigationController.viewControllers.count > 1)
return;
if (ownerController.isLaunchByDeepLink)
if (DeepLinkHandler.shared.isLaunchedByDeeplink)
return;
if (self.tutorialViewContoller != nil)

View file

@ -0,0 +1,120 @@
fileprivate enum DeeplinkType {
case geo
case file
case common
}
@objc @objcMembers class DeepLinkHandler: NSObject {
static let shared = DeepLinkHandler()
private(set) var isLaunchedByDeeplink = false
private(set) var deeplinkURL: URL?
private var canHandleLink = false
private var deeplinkType: DeeplinkType = .common
private override init() {
super.init()
}
func applicationDidFinishLaunching(_ options: [UIApplication.LaunchOptionsKey : Any]? = nil) {
if let userActivityOptions = options?[.userActivityDictionary] as? [UIApplication.LaunchOptionsKey : Any],
let userActivityType = userActivityOptions[.userActivityType] as? String,
userActivityType == NSUserActivityTypeBrowsingWeb {
isLaunchedByDeeplink = true
}
if let launchDeeplink = options?[UIApplication.LaunchOptionsKey.url] as? URL {
isLaunchedByDeeplink = true
deeplinkURL = launchDeeplink
}
NSLog("deeplink: applicationDidFinishLaunching \(deeplinkURL?.absoluteString ?? "nil")")
}
func applicationDidOpenUrl(_ url: URL) -> Bool {
NSLog("deeplink: applicationDidOpenUrl \(url)")
guard let dlType = deeplinkType(url) else { return false }
deeplinkType = dlType
isLaunchedByDeeplink = true
deeplinkURL = url
return true
}
private func setUniversalLink(_ url: URL) -> Bool {
let dlUrl = convertUniversalLink(url)
guard let dlType = deeplinkType(dlUrl) else { return false }
deeplinkType = dlType
deeplinkURL = dlUrl
if canHandleLink || !isLaunchedByDeeplink {
isLaunchedByDeeplink = true
handleInternal()
}
return true
}
func applicationDidReceiveUniversalLink(_ url: URL) -> Bool {
NSLog("deeplink: applicationDidReceiveUniversalLink \(url)")
var result = false
if let host = url.host, host == "mapsme.onelink.me" {
URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems?.forEach {
if $0.name == "af_dp" {
guard let value = $0.value, let dl = URL(string: value) else { return }
result = setUniversalLink(dl)
}
}
} else {
result = setUniversalLink(url)
}
return result
}
func handleDeeplink() {
if deeplinkURL != nil{
handleInternal()
} else {
canHandleLink = true
}
}
func reset() {
isLaunchedByDeeplink = false
canHandleLink = false
deeplinkURL = nil
}
private func convertUniversalLink(_ universalLink: URL) -> URL {
let convertedLink = String(format: "mapsme://%@?%@", universalLink.path, universalLink.query ?? "")
return URL(string: convertedLink)!
}
private func deeplinkType(_ deeplink: URL) -> DeeplinkType? {
switch deeplink.scheme {
case "geo", "ge0":
return .geo
case "file":
return .file
case "mapswithme", "mapsme", "mwm":
return .common
default:
return nil
}
}
private func handleInternal() {
guard let url = deeplinkURL else {
assertionFailure()
return
}
NSLog("deeplink: handle deeplink \(url)")
switch deeplinkType {
case .geo:
DeepLinkHelper.handleGeoUrl(url)
case .file:
DeepLinkHelper.handleFileUrl(url)
case .common:
DeepLinkHelper.handleCommonUrl(url)
}
reset()
}
}

View file

@ -0,0 +1,13 @@
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface DeepLinkHelper : NSObject
+ (void)handleGeoUrl:(NSURL *)url;
+ (void)handleFileUrl:(NSURL *)url;
+ (void)handleCommonUrl:(NSURL *)url;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,98 @@
#import "DeepLinkHelper.h"
#import <Crashlytics/Crashlytics.h>
#import "Framework.h"
#import "Statistics.h"
#import "MapViewController.h"
#import "MapsAppDelegate.h"
#import "MWMRouter.h"
#import "MWMRoutePoint+CPP.h"
#import "MWMCoreRouterType.h"
#import "MWMMapViewControlsManager.h"
static NSInteger const kSearchInViewportZoom = 16;
@implementation DeepLinkHelper
+ (void)handleGeoUrl:(NSURL *)url {
NSLog(@"deeplink: handleGeoUrl %@", url);
if (GetFramework().ShowMapForURL(url.absoluteString.UTF8String)) {
[Statistics logEvent:kStatEventName(kStatApplication, kStatImport)
withParameters:@{kStatValue : url.scheme}];
[MapsAppDelegate.theApp showMap];
}
}
+ (void)handleFileUrl:(NSURL *)url {
NSLog(@"deeplink: handleFileUrl %@", url);
GetFramework().AddBookmarksFile(url.relativePath.UTF8String, false /* isTemporaryFile */);
}
+ (void)handleCommonUrl:(NSURL *)url {
NSLog(@"deeplink: handleCommonUrl %@", url);
using namespace url_scheme;
Framework &f = GetFramework();
auto const parsingType = f.ParseAndSetApiURL(url.absoluteString.UTF8String);
switch (parsingType) {
case ParsedMapApi::ParsingResult::Incorrect:
LOG(LWARNING, ("Incorrect parsing result for url:", url));
break;
case ParsedMapApi::ParsingResult::Route: {
auto const parsedData = f.GetParsedRoutingData();
auto const points = parsedData.m_points;
if (points.size() == 2) {
auto p1 = [[MWMRoutePoint alloc] initWithURLSchemeRoutePoint:points.front()
type:MWMRoutePointTypeStart
intermediateIndex:0];
auto p2 = [[MWMRoutePoint alloc] initWithURLSchemeRoutePoint:points.back()
type:MWMRoutePointTypeFinish
intermediateIndex:0];
[MWMRouter buildApiRouteWithType:routerType(parsedData.m_type)
startPoint:p1
finishPoint:p2];
} else {
NSError *err = [[NSError alloc] initWithDomain:kMapsmeErrorDomain
code:5
userInfo:@{ @"Description" : @"Invalid number of route points",
@"URL" : url }];
[[Crashlytics sharedInstance] recordError:err];
}
[MapsAppDelegate.theApp showMap];
break;
}
case ParsedMapApi::ParsingResult::Map:
if (f.ShowMapForURL(url.absoluteString.UTF8String))
[MapsAppDelegate.theApp showMap];
break;
case ParsedMapApi::ParsingResult::Search: {
auto const &request = f.GetParsedSearchRequest();
auto query = [@((request.m_query + " ").c_str()) stringByRemovingPercentEncoding];
auto locale = @(request.m_locale.c_str());
if (request.m_isSearchOnMap) {
// Set viewport only when cll parameter was provided in url.
if (request.m_centerLat != 0.0 || request.m_centerLon != 0.0) {
[MapViewController setViewport:request.m_centerLat
lon:request.m_centerLon
zoomLevel:kSearchInViewportZoom];
}
[MWMMapViewControlsManager.manager searchTextOnMap:query forInputLocale:locale];
} else {
[MWMMapViewControlsManager.manager searchText:query forInputLocale:locale];
}
break;
}
case ParsedMapApi::ParsingResult::Catalogue:
[MapViewController.sharedController openCatalogDeeplink:url animated:NO];
break;
case ParsedMapApi::ParsingResult::Lead: break;
}
}
@end

View file

@ -42,6 +42,5 @@
@property(nonatomic, readonly) MWMMapViewControlsManager * controlsManager;
@property(nonatomic) MWMAPIBar * apiBar;
@property(nonatomic) MWMWelcomePageController * welcomePageController;
@property(nonatomic, getter=isLaunchByDeepLink) BOOL launchByDeepLink;
@end

View file

@ -105,10 +105,6 @@ BOOL gIsFirstMyPositionMode = YES;
+ (MapViewController *)sharedController { return [MapsAppDelegate theApp].mapViewController; }
- (BOOL)isLaunchByDeepLink { return [(EAGLView *)self.view isLaunchByDeepLink]; }
- (void)setLaunchByDeepLink:(BOOL)launchByDeepLink { [(EAGLView *)self.view setLaunchByDeepLink:launchByDeepLink]; }
#pragma mark - Map Navigation
- (void)dismissPlacePage { [self.controlsManager dismissPlacePage]; }
@ -119,7 +115,7 @@ BOOL gIsFirstMyPositionMode = YES;
if (!switchFullScreenMode)
return;
if ([MapsAppDelegate theApp].hasApiURL)
if (DeepLinkHandler.shared.isLaunchedByDeeplink)
return;
BOOL const isSearchHidden = ([MWMSearchManager manager].state == MWMSearchManagerStateHidden);
@ -259,7 +255,10 @@ BOOL gIsFirstMyPositionMode = YES;
- (void)viewDidLoad
{
[super viewDidLoad];
[(EAGLView *)self.view setLaunchByDeepLink:DeepLinkHandler.shared.isLaunchedByDeeplink];
[MWMRouter restoreRouteIfNeeded];
self.view.clipsToBounds = YES;
[self processMyPositionStateModeEvent:MWMMyPositionModePendingPosition];
[MWMKeyboard addObserver:self];
@ -272,6 +271,9 @@ BOOL gIsFirstMyPositionMode = YES;
name:UIApplicationDidBecomeActiveNotification
object:nil];
[self.welcomePageController show];
if (!self.welcomePageController) {
[DeepLinkHandler.shared handleDeeplink];
}
}
- (void)didBecomeActive

View file

@ -4,6 +4,8 @@
@class MapViewController;
NS_ASSUME_NONNULL_BEGIN
@interface MapsAppDelegate : UIResponder<UIApplicationDelegate, DownloadIndicatorProtocol>
{
NSInteger m_activeDownloadsCounter;
@ -19,8 +21,6 @@
+ (MapsAppDelegate *)theApp;
- (BOOL)hasApiURL;
- (void)enableStandby;
- (void)disableStandby;
@ -36,3 +36,5 @@
- (NSUInteger)badgeNumber;
@end
NS_ASSUME_NONNULL_END

View file

@ -25,14 +25,10 @@
#import <FBSDKCoreKit/FBSDKCoreKit.h>
#import <UserNotifications/UserNotifications.h>
#ifdef OMIM_PRODUCTION
#import <AppsFlyerLib/AppsFlyerTracker.h>
#import <Crashlytics/Crashlytics.h>
#import <Fabric/Fabric.h>
#endif
#include "Framework.h"
#include "map/framework_light.hpp"
@ -63,8 +59,6 @@ NSString * const kUDAutoNightModeOff = @"AutoNightModeOff";
NSString * const kIOSIDFA = @"IFA";
NSString * const kBundleVersion = @"BundleVersion";
auto const kSearchInViewportZoom = 16;
/// Adds needed localized strings to C++ code
/// @TODO Refactor localization mechanism to make it simpler
void InitLocalizedStrings()
@ -109,31 +103,11 @@ void OverrideUserAgent()
@"(KHTML, like Gecko) Version/10.0 Mobile/14E269 Safari/602.1"
}];
}
void InitMarketingTrackers()
{
#ifdef OMIM_PRODUCTION
NSString * appsFlyerDevKey = @(APPSFLYER_KEY);
NSString * appsFlyerAppIdKey = @(APPSFLYER_APP_ID_IOS);
if (appsFlyerDevKey.length != 0 && appsFlyerAppIdKey.length != 0)
{
[AppsFlyerTracker sharedTracker].appsFlyerDevKey = appsFlyerDevKey;
[AppsFlyerTracker sharedTracker].appleAppID = appsFlyerAppIdKey;
}
#endif
}
void TrackMarketingAppLaunch()
{
#ifdef OMIM_PRODUCTION
[[AppsFlyerTracker sharedTracker] trackAppLaunch];
#endif
}
} // namespace
using namespace osm_auth_ios;
@interface MapsAppDelegate ()<MWMFrameworkStorageObserver, NotificationManagerDelegate>
@interface MapsAppDelegate ()<MWMFrameworkStorageObserver, NotificationManagerDelegate, AppsFlyerTrackerDelegate>
@property(nonatomic) NSInteger standbyCounter;
@property(nonatomic) MWMBackgroundFetchScheduler * backgroundFetchScheduler;
@ -143,14 +117,6 @@ using namespace osm_auth_ios;
@end
@implementation MapsAppDelegate
{
NSString * m_geoURL;
NSString * m_mwmURL;
NSString * m_fileURL;
NSString * m_scheme;
NSString * m_sourceApplication;
}
+ (MapsAppDelegate *)theApp
{
@ -190,133 +156,6 @@ using namespace osm_auth_ios;
return ((EAGLView *)self.mapViewController.view).drapeEngineCreated;
}
- (BOOL)hasApiURL { return m_geoURL || m_mwmURL; }
- (void)handleURLs
{
self.mapViewController.launchByDeepLink = self.hasApiURL;
if (!self.isDrapeEngineCreated)
{
dispatch_async(dispatch_get_main_queue(), ^{
[self handleURLs];
});
return;
}
Framework & f = GetFramework();
if (m_geoURL)
{
if (f.ShowMapForURL(m_geoURL.UTF8String))
{
[Statistics logEvent:kStatEventName(kStatApplication, kStatImport)
withParameters:@{kStatValue : m_scheme}];
[self showMap];
}
}
else if (m_mwmURL)
{
using namespace url_scheme;
string const url = m_mwmURL.UTF8String;
auto const parsingType = f.ParseAndSetApiURL(url);
NSLog(@"Started by url: %@", m_mwmURL);
switch (parsingType)
{
case ParsedMapApi::ParsingResult::Incorrect:
LOG(LWARNING, ("Incorrect parsing result for url:", url));
break;
case ParsedMapApi::ParsingResult::Route:
{
auto const parsedData = f.GetParsedRoutingData();
auto const points = parsedData.m_points;
if (points.size() == 2)
{
auto p1 = [[MWMRoutePoint alloc] initWithURLSchemeRoutePoint:points.front()
type:MWMRoutePointTypeStart
intermediateIndex:0];
auto p2 = [[MWMRoutePoint alloc] initWithURLSchemeRoutePoint:points.back()
type:MWMRoutePointTypeFinish
intermediateIndex:0];
[MWMRouter buildApiRouteWithType:routerType(parsedData.m_type)
startPoint:p1
finishPoint:p2];
}
else
{
#ifdef OMIM_PRODUCTION
auto err = [[NSError alloc] initWithDomain:kMapsmeErrorDomain
code:5
userInfo:@{
@"Description" : @"Invalid number of route points",
@"URL" : m_mwmURL
}];
[[Crashlytics sharedInstance] recordError:err];
#endif
}
[self showMap];
break;
}
case ParsedMapApi::ParsingResult::Map:
if (f.ShowMapForURL(url))
[self showMap];
break;
case ParsedMapApi::ParsingResult::Search:
{
auto const & request = f.GetParsedSearchRequest();
auto manager = [MWMMapViewControlsManager manager];
auto query = [@((request.m_query + " ").c_str()) stringByRemovingPercentEncoding];
auto locale = @(request.m_locale.c_str());
if (request.m_isSearchOnMap)
{
// Set viewport only when cll parameter was provided in url.
if (request.m_centerLat != 0.0 || request.m_centerLon != 0.0)
{
ASSERT([self isDrapeEngineCreated], ());
[MapViewController setViewport:request.m_centerLat
lon:request.m_centerLon
zoomLevel:kSearchInViewportZoom];
}
[manager searchTextOnMap:query forInputLocale:locale];
}
else
{
[manager searchText:query forInputLocale:locale];
}
break;
}
case ParsedMapApi::ParsingResult::Catalogue:
[self.mapViewController openCatalogDeeplink:[[NSURL alloc] initWithString:m_mwmURL] animated:NO];
break;
case ParsedMapApi::ParsingResult::Lead: break;
}
}
else if (m_fileURL)
{
f.AddBookmarksFile(m_fileURL.UTF8String, false /* isTemporaryFile */);
}
else
{
// Take a copy of pasteboard string since it can accidentally become nil while we still use it.
NSString * pasteboard = [[UIPasteboard generalPasteboard].string copy];
if (pasteboard && pasteboard.length)
{
if (f.ShowMapForURL(pasteboard.UTF8String))
{
[self showMap];
[UIPasteboard generalPasteboard].string = @"";
}
}
}
m_geoURL = nil;
m_mwmURL = nil;
m_fileURL = nil;
}
- (NSURL *)convertUniversalLink:(NSURL *)universalLink
{
auto deeplink = [NSString stringWithFormat:@"mapsme://%@?%@", universalLink.path, universalLink.query];
@ -360,11 +199,12 @@ using namespace osm_auth_ios;
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSLog(@"deeplinking: launchOptions %@", launchOptions);
OverrideUserAgent();
InitCrashTrackers();
InitMarketingTrackers();
[self initMarketingTrackers];
// Initialize all 3party engines.
[self initStatistics:application didFinishLaunchingWithOptions:launchOptions];
@ -397,8 +237,6 @@ using namespace osm_auth_ios;
}
[self enableTTSForTheFirstTime];
[MWMRouter restoreRouteIfNeeded];
[GIDSignIn sharedInstance].clientID =
[[NSBundle mainBundle] loadWithPlist:@"GoogleService-Info"][@"CLIENT_ID"];
@ -417,7 +255,9 @@ using namespace osm_auth_ios;
if ([MoPubKit shouldShowConsentDialog])
[MoPubKit grantConsent];
[[DeepLinkHandler shared] applicationDidFinishLaunching:launchOptions];
return YES;
}
@ -524,7 +364,7 @@ using namespace osm_auth_ios;
{
LOG(LINFO, ("applicationWillResignActive - begin"));
[self.mapViewController onGetFocus:NO];
self.mapViewController.launchByDeepLink = NO;
[DeepLinkHandler.shared reset];
auto & f = GetFramework();
// On some devices we have to free all belong-to-graphics memory
// because of new OpenGL driver powered by Metal.
@ -568,8 +408,8 @@ using namespace osm_auth_ios;
{
LOG(LINFO, ("applicationDidBecomeActive - begin"));
TrackMarketingAppLaunch();
[self trackMarketingAppLaunch];
auto & f = GetFramework();
f.EnterForeground();
[self.mapViewController onGetFocus:YES];
@ -604,17 +444,32 @@ continueUserActivity:(NSUserActivity *)userActivity
}
else if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb])
{
auto link = userActivity.webpageURL;
if ([self checkLaunchURL:[self convertUniversalLink:link]])
{
[self handleURLs];
return YES;
}
return [DeepLinkHandler.shared applicationDidReceiveUniversalLink:userActivity.webpageURL];
}
return NO;
}
- (void)initMarketingTrackers
{
NSString * appsFlyerDevKey = @(APPSFLYER_KEY);
NSString * appsFlyerAppIdKey = @(APPSFLYER_APP_ID_IOS);
if (appsFlyerDevKey.length != 0 && appsFlyerAppIdKey.length != 0)
{
[AppsFlyerTracker sharedTracker].appsFlyerDevKey = appsFlyerDevKey;
[AppsFlyerTracker sharedTracker].appleAppID = appsFlyerAppIdKey;
[AppsFlyerTracker sharedTracker].delegate = self;
#if DEBUG
[AppsFlyerTracker sharedTracker].isDebug = YES;
#endif
}
}
- (void)trackMarketingAppLaunch
{
[[AppsFlyerTracker sharedTracker] trackAppLaunch];
}
- (BOOL)initStatistics:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
@ -745,10 +600,8 @@ continueUserActivity:(NSUserActivity *)userActivity
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options
{
m_sourceApplication = options[UIApplicationOpenURLOptionsSourceApplicationKey];
BOOL isGoogleURL = [[GIDSignIn sharedInstance] handleURL:url
sourceApplication:m_sourceApplication
sourceApplication:options[UIApplicationOpenURLOptionsSourceApplicationKey]
annotation:options[UIApplicationOpenURLOptionsAnnotationKey]];
if (isGoogleURL)
return YES;
@ -757,41 +610,7 @@ continueUserActivity:(NSUserActivity *)userActivity
if (isFBURL)
return YES;
for (NSString * host in @[@"dlink.maps.me", @"dlink.mapsme.devmail.ru"])
{
if ([self checkLaunchURL:(url.host.length > 0 && [url.host rangeOfString:host].location != NSNotFound)
? [self convertUniversalLink:url] : url])
{
[self handleURLs];
return YES;
}
}
return NO;
}
- (BOOL)checkLaunchURL:(NSURL *)url
{
NSString * scheme = url.scheme;
m_scheme = scheme;
if ([scheme isEqualToString:@"geo"] || [scheme isEqualToString:@"ge0"])
{
m_geoURL = [url absoluteString];
return YES;
}
else if ([scheme isEqualToString:@"mapswithme"] || [scheme isEqualToString:@"mwm"] ||
[scheme isEqualToString:@"mapsme"])
{
m_mwmURL = [url absoluteString];
return YES;
}
else if ([scheme isEqualToString:@"file"])
{
m_fileURL = [url relativePath];
return YES;
}
NSLog(@"Scheme %@ is not supported", scheme);
return NO;
return [DeepLinkHandler.shared applicationDidOpenUrl:url];
}
- (void)showMap
@ -985,4 +804,20 @@ continueUserActivity:(NSUserActivity *)userActivity
}
}
#pragma mark - AppsFlyerTrackerDelegate
-(void)onConversionDataReceived:(NSDictionary*) installData {
if ([installData[@"is_first_launch"] boolValue]) {
NSString *deeplink = installData[@"af_r"];
NSURL *deeplinkUrl = [NSURL URLWithString:deeplink];
if (deeplinkUrl != nil) {
[[DeepLinkHandler shared] applicationDidReceiveUniversalLink:deeplinkUrl];
}
}
}
-(void)onConversionDataRequestFailure:(NSError *) error {
[Crashlytics.sharedInstance recordError:error];
}
@end

View file

@ -0,0 +1,23 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "img_onboarding_guide.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "img_onboarding_guide@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "img_onboarding_guide@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

View file

@ -400,6 +400,8 @@
4788738F20EE30B300F6826B /* LayersViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4788738D20EE30B300F6826B /* LayersViewController.swift */; };
4788739020EE30B300F6826B /* LayersViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4788738E20EE30B300F6826B /* LayersViewController.xib */; };
4788739220EE326500F6826B /* VerticallyAlignedButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4788739120EE326400F6826B /* VerticallyAlignedButton.swift */; };
4797A4DC226F4B2900D3A984 /* DeepLinkHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4797A4DB226F4B2900D3A984 /* DeepLinkHandler.swift */; };
4797A4E22270997E00D3A984 /* DeepLinkHelper.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4797A4E12270997E00D3A984 /* DeepLinkHelper.mm */; };
47AEF8402231249E00D20538 /* categories_brands.txt in Resources */ = {isa = PBXBuildFile; fileRef = 47AEF83F2231249E00D20538 /* categories_brands.txt */; };
47B06DED21B696C20094CCAD /* GeoTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47B06DEC21B696C20094CCAD /* GeoTracker.swift */; };
47B06DF021B697230094CCAD /* MWMGeoTrackerCore.mm in Sources */ = {isa = PBXBuildFile; fileRef = 47B06DEF21B697230094CCAD /* MWMGeoTrackerCore.mm */; };
@ -412,6 +414,7 @@
47B9065321C7FA400079C85E /* MWMImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 47B9064A21C7FA3C0079C85E /* MWMImageCache.m */; };
47B9065421C7FA400079C85E /* UIImageView+WebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 47B9064F21C7FA3E0079C85E /* UIImageView+WebImage.m */; };
47B9065521C7FA400079C85E /* NSString+MD5.m in Sources */ = {isa = PBXBuildFile; fileRef = 47B9065021C7FA3F0079C85E /* NSString+MD5.m */; };
47C3DB582268CDDB00DF6F91 /* DeeplinkInfoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47C3DB572268CDD800DF6F91 /* DeeplinkInfoViewController.swift */; };
47C7F9732191E15A00C2760C /* InAppBilling.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47C7F9722191E15A00C2760C /* InAppBilling.swift */; };
47C7F97521930F5300C2760C /* IInAppBilling.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47C7F97421930F5300C2760C /* IInAppBilling.swift */; };
47D0026721999DA900F651A2 /* PendingTransactionsHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47D0026621999DA900F651A2 /* PendingTransactionsHandler.swift */; };
@ -1438,6 +1441,9 @@
4788738D20EE30B300F6826B /* LayersViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayersViewController.swift; sourceTree = "<group>"; };
4788738E20EE30B300F6826B /* LayersViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = LayersViewController.xib; sourceTree = "<group>"; };
4788739120EE326400F6826B /* VerticallyAlignedButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VerticallyAlignedButton.swift; sourceTree = "<group>"; };
4797A4DB226F4B2900D3A984 /* DeepLinkHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeepLinkHandler.swift; sourceTree = "<group>"; };
4797A4E02270997E00D3A984 /* DeepLinkHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DeepLinkHelper.h; sourceTree = "<group>"; };
4797A4E12270997E00D3A984 /* DeepLinkHelper.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = DeepLinkHelper.mm; sourceTree = "<group>"; };
47AEF83F2231249E00D20538 /* categories_brands.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = categories_brands.txt; path = ../../data/categories_brands.txt; sourceTree = "<group>"; };
47B06DEC21B696C20094CCAD /* GeoTracker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeoTracker.swift; sourceTree = "<group>"; };
47B06DEE21B697230094CCAD /* MWMGeoTrackerCore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MWMGeoTrackerCore.h; sourceTree = "<group>"; };
@ -1458,6 +1464,7 @@
47B9064F21C7FA3E0079C85E /* UIImageView+WebImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImageView+WebImage.m"; sourceTree = "<group>"; };
47B9065021C7FA3F0079C85E /* NSString+MD5.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+MD5.m"; sourceTree = "<group>"; };
47B9065121C7FA400079C85E /* IMWMImageCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IMWMImageCache.h; sourceTree = "<group>"; };
47C3DB572268CDD800DF6F91 /* DeeplinkInfoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeeplinkInfoViewController.swift; sourceTree = "<group>"; };
47C7F9722191E15A00C2760C /* InAppBilling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InAppBilling.swift; sourceTree = "<group>"; };
47C7F97421930F5300C2760C /* IInAppBilling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IInAppBilling.swift; sourceTree = "<group>"; };
47C7F976219310D800C2760C /* IMWMPurchaseValidation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IMWMPurchaseValidation.h; sourceTree = "<group>"; };
@ -2086,6 +2093,9 @@
340837101B7243B500B5C185 /* Share */,
F6588E291B15C25C00EE1E58 /* TextView */,
34FE4C421BCC013500066718 /* Widgets */,
4797A4DB226F4B2900D3A984 /* DeepLinkHandler.swift */,
4797A4E02270997E00D3A984 /* DeepLinkHelper.h */,
4797A4E12270997E00D3A984 /* DeepLinkHelper.mm */,
);
path = Classes;
sourceTree = "<group>";
@ -2963,6 +2973,7 @@
34D4FA651E265749003F53EF /* WhatsNewController.swift */,
4767CDC020B477BA00BD8166 /* WelcomeViewController.swift */,
47800D1C20BEEE2E00072F42 /* TermsOfUseController.swift */,
47C3DB572268CDD800DF6F91 /* DeeplinkInfoViewController.swift */,
);
path = Welcome;
sourceTree = "<group>";
@ -5079,6 +5090,7 @@
F6E2FE431E097BA00083EBEC /* MWMDirectionView.mm in Sources */,
470F5A5B2181DE7500754295 /* PaidRouteViewController.swift in Sources */,
3486B50D1E27A6DA0069C126 /* MWMPushNotifications.mm in Sources */,
47C3DB582268CDDB00DF6F91 /* DeeplinkInfoViewController.swift in Sources */,
3404F490202898CC0090E401 /* BMCModels.swift in Sources */,
F6E2FD561E097BA00083EBEC /* MWMMapDownloaderButtonTableViewCell.mm in Sources */,
3462258F1DDC5DBA001E8752 /* MWMSearchNoResultsAlert.mm in Sources */,
@ -5124,6 +5136,7 @@
3404754A1E081A4600C92850 /* AppInfo.mm in Sources */,
3358607E217632A2006D11F2 /* BookmarksSharingViewController.swift in Sources */,
34AB662F1FC5AA330078E451 /* RouteManageriPhonePresentationController.swift in Sources */,
4797A4DC226F4B2900D3A984 /* DeepLinkHandler.swift in Sources */,
34AB66201FC5AA330078E451 /* RouteStartButton.swift in Sources */,
34F4072C1E9E1AFF00E57AC0 /* Banner.swift in Sources */,
F660DEE51EAF4F59004DC056 /* MWMLocationManager+SpeedAndAltitude.swift in Sources */,
@ -5320,6 +5333,7 @@
34E50DD81F6FCAB1008EED49 /* UGCSummaryRatingCell.swift in Sources */,
6741AA281BF340DE002C974C /* MWMAlert.mm in Sources */,
F6E2FF571E097BA00083EBEC /* MWMMobileInternetViewController.mm in Sources */,
4797A4E22270997E00D3A984 /* DeepLinkHelper.mm in Sources */,
47B06E0021BAAC270094CCAD /* GeoZoneTracker.swift in Sources */,
3404F4952028A1B80090E401 /* BMCPermissionsCell.swift in Sources */,
340416441E7BED3900E2B6D6 /* PhotosTransitionAnimator.swift in Sources */,

View file

@ -8,9 +8,10 @@ target 'MAPS.ME' do
# Pods for MAPS.ME
pod 'AppsFlyerFramework', '4.8.9'
pod 'AppsFlyerFramework', '4.9.0'
pod 'Pushwoosh', '5.9.0'
pod 'ActionSheetPicker-3.0', '2.3.0'
pod 'FBSDKCoreKit', '4.42.0'
pod 'FBSDKLoginKit', '4.42.0'
end

View file

@ -1,6 +1,6 @@
PODS:
- ActionSheetPicker-3.0 (2.3.0)
- AppsFlyerFramework (4.8.9)
- AppsFlyerFramework (4.9.0)
- Bolts (1.9.0):
- Bolts/AppLinks (= 1.9.0)
- Bolts/Tasks (= 1.9.0)
@ -15,7 +15,8 @@ PODS:
DEPENDENCIES:
- ActionSheetPicker-3.0 (= 2.3.0)
- AppsFlyerFramework (= 4.8.9)
- AppsFlyerFramework (= 4.9.0)
- FBSDKCoreKit (= 4.42.0)
- FBSDKLoginKit (= 4.42.0)
- Pushwoosh (= 5.9.0)
@ -30,12 +31,12 @@ SPEC REPOS:
SPEC CHECKSUMS:
ActionSheetPicker-3.0: eef157d75e151f255c5333d26656c7fbfe905a51
AppsFlyerFramework: 0fc823ec9b77f913e4108caa82c969be033058b1
AppsFlyerFramework: f57e5d590ad3124d3e594a76032a181bc91ec6cd
Bolts: ac6567323eac61e203f6a9763667d0f711be34c8
FBSDKCoreKit: aa42f1c384775f8b075f53a43080474278e9701d
FBSDKLoginKit: 373830c68aa48c9e8f0bfed93a3e32d2ca8963a0
Pushwoosh: 8eda99efebf90e44a53b55976db51c5da9b18deb
PODFILE CHECKSUM: c14eb7e3b15fcc412e5bfd713ad86281c4417a12
PODFILE CHECKSUM: cd2a77eabd1ac707fac07870645088d9d3832bc2
COCOAPODS: 1.6.1

View file

@ -11,15 +11,37 @@
NS_ASSUME_NONNULL_BEGIN
/**
AppsFlyer allows you to track and attribute installs originating
from cross promotion campaigns of your existing apps.
Afterwards, you can optimize on your cross-promotion traffic to get even better results.
*/
@interface AppsFlyerCrossPromotionHelper : NSObject
+ (void) trackCrossPromoteImpression:(nonnull NSString*) appID
campaign:(nullable NSString*) campaign;
+ (void) trackAndOpenStore:(nonnull NSString*) appID
campaign:(nullable NSString *) campaign
paramters:(nullable NSDictionary*) parameters
openStore:(void (^)(NSURLSession *urlSession,NSURL *clickURL))openStoreBlock;
/**
To track an impression use the following API call.
Make sure to use the promoted App ID as it appears within the AppsFlyer dashboard.
@param appID Promoted App ID
@param campaign A campaign name
*/
+ (void)trackCrossPromoteImpression:(nonnull NSString*)appID
campaign:(nullable NSString*)campaign;
/**
iOS allows you to utilize the StoreKit component to open
the App Store while remaining in the context of your app.
More details at https://support.appsflyer.com/hc/en-us/articles/115004481946-Cross-Promotion-Tracking#tracking-cross-promotion-impressions
@param appID Promoted App ID
@param campaign A campaign name
@param parameters Additional params like `@{@"af_sub1": @"val", @"custom_param": @"val2" }`
@param openStoreBlock Contains promoted `clickURL`
*/
+ (void)trackAndOpenStore:(nonnull NSString*)appID
campaign:(nullable NSString *)campaign
paramters:(nullable NSDictionary*)parameters
openStore:(void (^)(NSURLSession *urlSession,NSURL *clickURL))openStoreBlock;
@end
NS_ASSUME_NONNULL_END

View file

@ -10,25 +10,35 @@
NS_ASSUME_NONNULL_BEGIN
/*!
* Payload container for the `generateInviteUrlWithLinkGenerator:completionHandler:` from `AppsFlyerShareInviteHelper`
/**
Payload container for the `generateInviteUrlWithLinkGenerator:completionHandler:` from `AppsFlyerShareInviteHelper`
*/
@interface AppsFlyerLinkGenerator: NSObject
/// Instance initialization is not allowed. Use generated instance
/// from `-[AppsFlyerShareInviteHelper generateInviteUrlWithLinkGenerator:completionHandler]`
- (instancetype)init NS_UNAVAILABLE;
/// Instance initialization is not allowed. Use generated instance
/// from `-[AppsFlyerShareInviteHelper generateInviteUrlWithLinkGenerator:completionHandler]`
+ (instancetype)new NS_UNAVAILABLE;
/// The channel through which the invite was sent (e.g. Facebook/Gmail/etc.). Usage: Recommended
- (void)setChannel :(nonnull NSString *)channel;
/// ReferrerCustomerId setter
- (void)setReferrerCustomerId:(nonnull NSString *)referrerCustomerId;
/// A campaign name. Usage: Optional
- (void)setCampaign :(nonnull NSString *)campaign;
/// ReferrerUID setter
- (void)setReferrerUID :(nonnull NSString *)referrerUID;
/// Referrer name
- (void)setReferrerName :(nonnull NSString *)referrerName;
/// The URL to referrer user avatar. Usage: Optional
- (void)setReferrerImageURL :(nonnull NSString *)referrerImageURL;
/// AppleAppID
- (void)setAppleAppID :(nonnull NSString *)appleAppID;
/// Deeplink path
- (void)setDeeplinkPath :(nonnull NSString *)deeplinkPath;
/// Base deeplink path
- (void)setBaseDeeplink :(nonnull NSString *)baseDeeplink;
/// A single key value custom parameter. Usage: Optional
- (void)addParameterValue :(nonnull NSString *)value forKey:(NSString*)key;

View file

@ -8,12 +8,14 @@
#import <Foundation/Foundation.h>
#import "AppsFlyerLinkGenerator.h"
/**
AppsFlyerShareInviteHelper
*/
@interface AppsFlyerShareInviteHelper : NSObject
NS_ASSUME_NONNULL_BEGIN
/*!
/**
* The AppsFlyerShareInviteHelper class builds the invite URL according to various setter methods
* which allow passing on additional information on the click.
* This information is available through `onConversionDataReceived:` when the user accepts the invite and installs the app.
@ -22,7 +24,7 @@ NS_ASSUME_NONNULL_BEGIN
+ (void) generateInviteUrlWithLinkGenerator:(AppsFlyerLinkGenerator * (^)(AppsFlyerLinkGenerator *generator))generatorCreator
completionHandler:(void (^)(NSURL * _Nullable url))completionHandler;
/*!
/**
* It is recommended to generate an in-app event after the invite is sent to track the invites from the senders' perspective.
* This enables you to find the users that tend most to invite friends, and the media sources that get you these users.
*/

View file

@ -2,8 +2,8 @@
// AppsFlyerTracker.h
// AppsFlyerLib
//
// AppsFlyer iOS SDK 4.8.9 (728)
// Copyright (c) 2013 AppsFlyer Ltd. All rights reserved.
// AppsFlyer iOS SDK 4.9.0 (813)
// Copyright (c) 2019 AppsFlyer Ltd. All rights reserved.
//
#import <Foundation/Foundation.h>
@ -116,9 +116,9 @@
#define AFEventParamHotelScore @"af_hotel_score"
#define AFEventParamPurchaseCurrency @"af_purchase_currency"
#define AFEventParamPreferredStarRatings @"af_preferred_star_ratings" //array of int (basically a tupple (min,max) but we'll use array of int and instruct the developer to use two values)
#define AFEventParamPreferredStarRatings @"af_preferred_star_ratings" //array of int (basically a tuple (min,max) but we'll use array of int and instruct the developer to use two values)
#define AFEventParamPreferredPriceRange @"af_preferred_price_range" //array of int (basically a tupple (min,max) but we'll use array of int and instruct the developer to use two values)
#define AFEventParamPreferredPriceRange @"af_preferred_price_range" //array of int (basically a tuple (min,max) but we'll use array of int and instruct the developer to use two values)
#define AFEventParamPreferredNeighborhoods @"af_preferred_neighborhoods" //array of string
#define AFEventParamPreferredNumStops @"af_preferred_num_stops"
@ -128,9 +128,6 @@
#define AFEventParamAdRevenueAdSize @"af_adrev_ad_size"
#define AFEventParamAdRevenueMediatedNetworkName @"af_adrev_mediated_network_name"
#define kAppsFlyerOneLinkVersion @"oneLinkVersion"
#define kAppsFlyerOneLinkScheme @"oneLinkScheme"
#define kAppsFlyerOneLinkDomain @"oneLinkDomain"
#define kDefaultOneLink @"go.onelink.me"
#define kNoOneLinkFallback @"https://app.appsflyer.com"
#define kINviteAppleAppID @"af_siteid"
@ -138,212 +135,398 @@
/// Mail hashing type
typedef enum {
/// None
EmailCryptTypeNone = 0,
/// SHA1
EmailCryptTypeSHA1 = 1,
/// MD5
EmailCryptTypeMD5 = 2,
/// SHA256
EmailCryptTypeSHA256 = 3
} EmailCryptType;
/*
* This delegate should be use if you want to use AppsFlyer conversion data. See AppsFlyer iOS
/**
Conform and subscribe to this protocol to allow getting data about conversion and
install attribution
*/
@protocol AppsFlyerTrackerDelegate <NSObject>
@optional
- (void) onConversionDataReceived:(NSDictionary*) installData;
- (void) onConversionDataRequestFailure:(NSError *)error;
- (void) onAppOpenAttribution:(NSDictionary*) attributionData;
- (void) onAppOpenAttributionFailure:(NSError *)error;
/**
`installData` contains information about install.
Organic/non-organic, etc.
*/
- (void)onConversionDataReceived:(NSDictionary *)installData;
/**
Any errors that occurred during the conversion request.
*/
- (void)onConversionDataRequestFailure:(NSError *)error;
/**
`attributionData` contains information about OneLink, deeplink.
*/
- (void)onAppOpenAttribution:(NSDictionary *)attributionData;
/**
Any errors that occurred during the attribution request.
*/
- (void)onAppOpenAttributionFailure:(NSError *)error;
@end
/**
You can track installs, app updates, sessions and additional in-app events
(including in-app purchases, game levels, etc.)
to evaluate ROI and user engagement.
The iOS SDK is compatible with all iOS/tvOS devices with iOS version 7 and above.
@see [SDK Integration Validator](https://support.appsflyer.com/hc/en-us/articles/207032066-AppsFlyer-SDK-Integration-iOS)
for more information.
*/
@interface AppsFlyerTracker : NSObject
+(AppsFlyerTracker*) sharedTracker;
/* In case you use your own user ID in your app, you can set this property to that ID. */
@property (nonatomic, strong, setter=setCustomerUserID:) NSString *customerUserID;
/* In case you use Custom data and you want to receive it in the raw reports.*/
@property (nonatomic, strong, setter=setAdditionalData:) NSDictionary *customData;
/* Use this property to set your AppsFlyer's dev key. */
@property (nonatomic, strong, setter=setAppsFlyerDevKey:) NSString *appsFlyerDevKey;
/* Use this property to set your app's Apple ID (taken from the app's page on iTunes Connect) */
@property (nonatomic, strong, setter=setAppleAppID:) NSString *appleAppID;
/*
* In case of in app purchase events, you can set the currency code your user has purchased with.
* The currency code is a 3 letter code according to ISO standards. Example: "USD"
/**
Gets the singleton instance of the AppsFlyerTracker class, creating it if
necessary.
@return The singleton instance of AppsFlyerTracker.
*/
@property (nonatomic, strong) NSString *currencyCode;
+ (AppsFlyerTracker *)sharedTracker;
/*
* AppsFLyer SDK collect Apple's advertisingIdentifier if the AdSupport framework included in the SDK.
* You can disable this behavior by setting the following property to YES.
/**
In case you use your own user ID in your app, you can set this property to that ID.
Enables you to cross-reference your own unique ID with AppsFlyers unique ID and the other devices IDs
*/
@property BOOL disableAppleAdSupportTracking;
@property(nonatomic, strong, setter = setCustomerUserID:) NSString * customerUserID;
/*
* Prints our messages to the log. This property should only be used in DEBUG mode. The default value
* is NO.
/**
In case you use custom data and you want to receive it in the raw reports.
@see [Setting additional custom data](https://support.appsflyer.com/hc/en-us/articles/207032066-AppsFlyer-SDK-Integration-iOS#setting-additional-custom-data) for more information.
*/
@property (nonatomic, setter = setIsDebug:) BOOL isDebug;
@property(nonatomic, strong, setter = setAdditionalData:) NSDictionary * customData;
/*!
* Set this flag to `YES`, to collect the current device name. Default value is `NO`
/**
Use this property to set your AppsFlyer's dev key
*/
@property (nonatomic, setter = setShouldCollectDeviceName:) BOOL shouldCollectDeviceName;
@property(nonatomic, strong, setter = setAppsFlyerDevKey:) NSString * appsFlyerDevKey;
@property (nonatomic, setter = setAppInviteOneLink:) NSString* appInviteOneLinkID;
/*
* Opt-out tracking for specific user
/**
Use this property to set your app's Apple ID(taken from the app's page on iTunes Connect)
*/
@property BOOL deviceTrackingDisabled;
@property(nonatomic, strong, setter = setAppleAppID:) NSString * appleAppID;
/*
* Opt-out tracking for iAd attributions
/**
In case of in app purchase events, you can set the currency code your user has purchased with.
The currency code is a 3 letter code according to ISO standards
Objective-C:
<pre>
[[AppsFlyerTracker sharedTracker] setCurrencyCode:@"USD"];
</pre>
Swift:
<pre>
AppsFlyerTracker.shared().currencyCode = "USD"
</pre>
*/
@property BOOL disableIAdTracking;
@property(nonatomic, strong) NSString *currencyCode;
/*
* AppsFlyer delegate. See AppsFlyerTrackerDelegate abvoe
/**
AppsFlyer SDK collect Apple's `advertisingIdentifier` if the `AdSupport.framework` included in the SDK.
You can disable this behavior by setting the following property to YES
*/
@property (weak, nonatomic) id<AppsFlyerTrackerDelegate> delegate;
@property(atomic) BOOL disableAppleAdSupportTracking;
/*
* In app purchase receipt validation Apple environment (production or sandbox). The default value
* is NO.
/**
Prints SDK messages to the console log. This property should only be used in `DEBUG` mode.
The default value is `NO`
*/
@property (nonatomic, setter = setUseReceiptValidationSandbox:) BOOL useReceiptValidationSandbox;
@property(nonatomic, setter = setIsDebug:) BOOL isDebug;
/*
* Set this flag to test uninstall on Apple environment (production or sandbox). The default value
* is NO.
/**
Set this flag to `YES`, to collect the current device name(e.g. "My iPhone"). Default value is `NO`
*/
@property (nonatomic, setter = setUseUninstallSandbox:) BOOL useUninstallSandbox;
@property(nonatomic, setter = setShouldCollectDeviceName:) BOOL shouldCollectDeviceName;
/*
* Advertising Id (exposed for RemoteDebug)
/**
Set your `OneLink ID` from OneLink configuration. Used in User Invites to generate a OneLink.
*/
@property (nonatomic, strong) NSString *advertiserId;
@property(nonatomic, strong, setter = setAppInviteOneLink:) NSString * appInviteOneLinkID;
/*
* Use this to send the User's emails
/**
Opt-out tracking for specific user
*/
-(void) setUserEmails:(NSArray *) userEmails withCryptType:(EmailCryptType) type;
@property(atomic) BOOL deviceTrackingDisabled;
/* Track application launch*/
- (void) trackAppLaunch;
/*
* Use this method to track events in your app like purchases or user actions.
* Example :
* [[AppsFlyer sharedTracker] trackEvent:@"hotel-booked" withValue:"200"];
/**
Opt-out tracking for Apple Search Ads attributions
*/
- (void) trackEvent:(NSString*)eventName withValue:(NSString*)value __attribute__((deprecated));
@property(atomic) BOOL disableIAdTracking;
/*
* Use this method to track an events with mulitple values. See AppsFlyer's documentation for details.
*
/**
AppsFlyer delegate. See `AppsFlyerTrackerDelegate`
*/
- (void) trackEvent:(NSString *)eventName withValues:(NSDictionary*)values;
@property(weak, nonatomic) id<AppsFlyerTrackerDelegate> delegate;
/*
* To track in app purchases you can call this method from the completeTransaction: method on
* your SKPaymentTransactionObserver.
/**
In app purchase receipt validation Apple environment(production or sandbox). The default value is NO
*/
- (void) validateAndTrackInAppPurchase:(NSString *)productIdentifier
@property(nonatomic, setter = setUseReceiptValidationSandbox:) BOOL useReceiptValidationSandbox;
/**
Set this flag to test uninstall on Apple environment(production or sandbox). The default value is NO
*/
@property(nonatomic, setter = setUseUninstallSandbox:) BOOL useUninstallSandbox;
/**
Advertising Id(exposed for RemoteDebug)
*/
@property(nonatomic, strong) NSString *advertiserId;
/**
For advertisers who wrap OneLink within another Universal Link.
An advertiser will be able to deeplink from a OneLink wrapped within another Universal Link and also track this retargeting conversion.
Objective-C:
<pre>
[[AppsFlyerTracker sharedTracker] setResolveDeepLinkURLs:@[@"domain.com", @"subdomain.domain.com"]];
</pre>
*/
@property(nonatomic) NSArray<NSString *> *resolveDeepLinkURLs;
/**
Use this to send the user's emails
@param userEmails The list of strings that hold mails
@param type Hash algoritm
*/
- (void)setUserEmails:(NSArray *)userEmails withCryptType:(EmailCryptType)type;
/**
Track application launch(session).
Add the following method at the `applicationDidBecomeActive` in AppDelegate class
*/
- (void)trackAppLaunch;
/**
Use this method to track events in your app like purchases or user actions
@param eventName Contains name of event that could be provided from predefined constants in `AppsFlyerTracker.h`
@param value Contains value for handling by backend
<pre>
[[AppsFlyer sharedTracker] trackEvent:AFEventPurchase withValue:"200"];
</pre>
*/
- (void)trackEvent:(NSString *)eventName withValue:(NSString *)value __attribute__((deprecated));
/**
Use this method to track an events with mulitple values. See AppsFlyer's documentation for details.
Objective-C:
<pre>
[[AppsFlyerTracker sharedTracker] trackEvent:AFEventPurchase
withValues: @{AFEventParamRevenue : @200,
AFEventParamCurrency : @"USD",
AFEventParamQuantity : @2,
AFEventParamContentId: @"092",
AFEventParamReceiptId: @"9277"}];
</pre>
Swift:
<pre>
AppsFlyerTracker.shared().trackEvent(AFEventPurchase,
withValues: [AFEventParamRevenue : "1200",
AFEventParamContent : "shoes",
AFEventParamContentId: "123"])
</pre>
@param eventName Contains name of event that could be provided from predefined constants in `AppsFlyerTracker.h`
@param values Contains dictionary of values for handling by backend
*/
- (void)trackEvent:(NSString *)eventName withValues:(NSDictionary *)values;
/**
To track and validate in app purchases you can call this method from the completeTransaction: method on
your `SKPaymentTransactionObserver`.
@param productIdentifier The product identifier
@param price The product price
@param currency The product currency
@param tranactionId The purchase transaction Id
@param params The additional param, which you want to receive it in the raw reports
@param successBlock The success callback
@param failedBlock The failure callback
*/
- (void)validateAndTrackInAppPurchase:(NSString *)productIdentifier
price:(NSString *)price
currency:(NSString *)currency
transactionId:(NSString *) tranactionId
transactionId:(NSString *)tranactionId
additionalParameters:(NSDictionary *)params
success:(void (^)(NSDictionary *response))successBlock
failure:(void (^)(NSError *error, id reponse)) failedBlock NS_AVAILABLE(10_7, 7_0);
failure:(void (^)(NSError *error, id reponse))failedBlock NS_AVAILABLE(10_7, 7_0);
/*
* To Track location for geo-fencing.
*/
- (void) trackLocation:(double) longitude latitude:(double) latitude;
/*
* This method returns AppsFLyer's internal user ID (unique for your app)
/**
To Track location for geo-fencing. Does the same as code below.
<pre>
AppsFlyerTracker.shared().trackEvent(AFEventLocation, withValues: [AFEventParamLong:longitude, AFEventParamLat:latitude])
</pre>
@param longitude The location longitude
@param latitude The location latitude
*/
- (NSString *) getAppsFlyerUID;
- (void)trackLocation:(double)longitude latitude:(double)latitude;
/*
* In case you want to use AppsFlyer tracking data in your app you can use the following method set a
* delegate with callback buttons for the tracking data. See AppsFlyerTrackerDelegate above.
/**
This method returns AppsFlyer's internal id(unique for your app)
@return Internal AppsFlyer Id
*/
- (void) loadConversionDataWithDelegate:(id<AppsFlyerTrackerDelegate>) delegate __attribute__((deprecated));
- (NSString *)getAppsFlyerUID;
/*
* In case you want to track deep linking, call this method from your delegate's openURL method.
/**
In case you want to use AppsFlyer tracking data in your app you can use the following method set a
delegate with callback buttons for the tracking data. See AppsFlyerTrackerDelegate above.
@param delegate The AppsFlyer delegate reference
*/
- (void) handleOpenURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication;
- (void)loadConversionDataWithDelegate:(id<AppsFlyerTrackerDelegate>)delegate __attribute__((deprecated));
/*
* In case you want to track deep linking, call this method from your delegate's openURL method with refferer.
/**
In case you want to track deep linking. Does the same as `-handleOpenURL:sourceApplication:withAnnotation`.
@warning Prefered to use `-handleOpenURL:sourceApplication:withAnnotation`.
@param url The URL that was passed to your AppDelegate.
@param sourceApplication The sourceApplication that passed to your AppDelegate.
*/
- (void) handleOpenURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication withAnnotation:(id) annotation;
- (void)handleOpenURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication;
- (void) handleOpenUrl:(NSURL *) url options:(NSDictionary *)options;
/*
* For Universal links iOS 9
/**
In case you want to track deep linking.
Call this method from inside your AppDelegate `-application:openURL:sourceApplication:annotation:`
@param url The URL that was passed to your AppDelegate.
@param sourceApplication The sourceApplication that passed to your AppDelegate.
@param annotation The annotation that passed to your app delegate.
*/
- (void)handleOpenURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
withAnnotation:(id)annotation;
- (BOOL) continueUserActivity:(NSUserActivity *) userActivity restorationHandler:(void (^)(NSArray *))restorationHandler NS_AVAILABLE_IOS(9_0);
- (void) didUpdateUserActivity:(NSUserActivity *)userActivity NS_AVAILABLE_IOS(9_0);
- (void) handlePushNotification:(NSDictionary *) pushPayload;
/**
Call this method from inside of your AppDelegate `-application:openURL:options:` method.
This method is functionally the same as calling the AppsFlyer method
`-handleOpenURL:sourceApplication:withAnnotation`.
@param url The URL that was passed to your app delegate
@param options The options dictionary that was passed to your AppDelegate.
*/
- (void)handleOpenUrl:(NSURL *)url options:(NSDictionary *)options;
/**
Allow AppsFlyer to handle restoration from an NSUserActivity.
Use this method to track deep links with OneLink.
@param userActivity The NSUserActivity that caused the app to be opened.
*/
- (BOOL)continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray *))restorationHandler NS_AVAILABLE_IOS(9_0);
/**
This method is not used anymore. Exist only for backward compatability. Don't use.
@param userActivity The NSUserActivity param.
*/
- (void)didUpdateUserActivity:(NSUserActivity *)userActivity NS_AVAILABLE_IOS(9_0);
/**
Enable AppsFlyer to handle a push notification.
@see [Learn more here](https://support.appsflyer.com/hc/en-us/articles/207364076-Measuring-Push-Notification-Re-Engagement-Campaigns)
@warning To make it work - set data, related to AppsFlyer under key @"af".
@param pushPayload The `userInfo` from received remote notification. One of root keys should be @"af".
*/
- (void)handlePushNotification:(NSDictionary *)pushPayload;
/*
Register uninstall - you should register for remote notification and provide Appsflyer the push device token.
*/
- (void) registerUninstall:(NSData *) deviceToken;
/**
Register uninstall - you should register for remote notification and provide AppsFlyer the push device token.
@param deviceToken The `deviceToken` from `-application:didRegisterForRemoteNotificationsWithDeviceToken:`
*/
- (void)registerUninstall:(NSData *)deviceToken;
/*
/**
Get SDK version.
*/
- (NSString *) getSDKVersion;
- (void) remoteDebuggingCallWithData:(NSString *) data;
/*!
* @brief This property accepts a string value representing the host name for all enpoints.
* @warning To use `default` SDK endpoint set value to `nil`.
* @code
* Objective-C:
* [[AppsFlyerTracker sharedTracker] setHost:@"example.com"];
* Swift:
* AppsFlyerTracker.shared().host = "example.com"
* @endcode
@return The AppsFlyer SDK version info.
*/
- (NSString *)getSDKVersion;
@property (nonatomic, strong) NSString *host;
/*!
* This property is responsible for timeout between sessions in seconds.
* Default value is 5 seconds.
/**
This is for internal use.
*/
@property (atomic) NSUInteger minTimeBetweenSessions;
- (void)remoteDebuggingCallWithData:(NSString *)data;
/*!
* WARNING! This will disable all requests from AppsFlyer SDK
/**
@brief This property accepts a string value representing the host name for all endpoints.
Can be used to Zero rate your applications data usage. Contact your CSM for more information.
@warning To use `default` SDK endpoint set value to `nil`.
Objective-C:
<pre>
[[AppsFlyerTracker sharedTracker] setHost:@"example.com"];
</pre>
Swift:
<pre>
AppsFlyerTracker.shared().host = "example.com"
</pre>
*/
@property (atomic) BOOL isStopTracking;
@property(nonatomic, strong) NSString *host;
- (void)setHost:(NSString *)host DEPRECATED_MSG_ATTRIBUTE("Use -[AppsFlyerTracker setHost:withHostPrefix:] instead");
/**
* This function set the host name and prefix host name for all the endpoints
**/
- (void)setHost:(NSString *)host withHostPrefix:(NSString *)hostPrefix;
/**
* This property accepts a string value representing the prefix host name for all endpoints.
* for example "test" prefix with default host name will have the address "host.appsflyer.com"
*/
@property(nonatomic, strong, readonly) NSString *hostPrefix;
/**
This property is responsible for timeout between sessions in seconds.
Default value is 5 seconds.
*/
@property(atomic) NSUInteger minTimeBetweenSessions;
/**
API to shut down all SDK activities.
@warning This will disable all requests from AppsFlyer SDK.
*/
@property(atomic) BOOL isStopTracking;
@end

View file

@ -1,6 +1,6 @@
PODS:
- ActionSheetPicker-3.0 (2.3.0)
- AppsFlyerFramework (4.8.9)
- AppsFlyerFramework (4.9.0)
- Bolts (1.9.0):
- Bolts/AppLinks (= 1.9.0)
- Bolts/Tasks (= 1.9.0)
@ -15,7 +15,8 @@ PODS:
DEPENDENCIES:
- ActionSheetPicker-3.0 (= 2.3.0)
- AppsFlyerFramework (= 4.8.9)
- AppsFlyerFramework (= 4.9.0)
- FBSDKCoreKit (= 4.42.0)
- FBSDKLoginKit (= 4.42.0)
- Pushwoosh (= 5.9.0)
@ -30,12 +31,12 @@ SPEC REPOS:
SPEC CHECKSUMS:
ActionSheetPicker-3.0: eef157d75e151f255c5333d26656c7fbfe905a51
AppsFlyerFramework: 0fc823ec9b77f913e4108caa82c969be033058b1
AppsFlyerFramework: f57e5d590ad3124d3e594a76032a181bc91ec6cd
Bolts: ac6567323eac61e203f6a9763667d0f711be34c8
FBSDKCoreKit: aa42f1c384775f8b075f53a43080474278e9701d
FBSDKLoginKit: 373830c68aa48c9e8f0bfed93a3e32d2ca8963a0
Pushwoosh: 8eda99efebf90e44a53b55976db51c5da9b18deb
PODFILE CHECKSUM: c14eb7e3b15fcc412e5bfd713ad86281c4417a12
PODFILE CHECKSUM: cd2a77eabd1ac707fac07870645088d9d3832bc2
COCOAPODS: 1.6.1

View file

@ -1,7 +1,7 @@
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/AppsFlyerFramework
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/AppsFlyerFramework"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
OTHER_LDFLAGS = $(inherited) -framework "AdSupport" -framework "Security" -framework "SystemConfiguration" -framework "iAd"
OTHER_LDFLAGS = $(inherited) -framework "AdSupport" -framework "CoreTelephony" -framework "Security" -framework "SystemConfiguration" -framework "iAd"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}

View file

@ -31,7 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## AppsFlyerFramework
Copyright 2014 AppsFlyer Ltd. All rights reserved.
Copyright 2018 AppsFlyer Ltd. All rights reserved.
## Bolts

View file

@ -48,7 +48,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</dict>
<dict>
<key>FooterText</key>
<string>Copyright 2014 AppsFlyer Ltd. All rights reserved.</string>
<string>Copyright 2018 AppsFlyer Ltd. All rights reserved.</string>
<key>License</key>
<string>Proprietary</string>
<key>Title</key>

View file

@ -2,7 +2,7 @@ FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ActionShe
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ActionSheetPicker-3.0/ActionSheetPicker_3_0.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Bolts/Bolts.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FBSDKCoreKit/FBSDKCoreKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FBSDKLoginKit/FBSDKLoginKit.framework/Headers"
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
OTHER_LDFLAGS = $(inherited) -ObjC -l"stdc++" -l"z" -framework "ActionSheetPicker_3_0" -framework "AdSupport" -framework "AppsFlyerLib" -framework "Bolts" -framework "CoreLocation" -framework "FBSDKCoreKit" -framework "FBSDKLoginKit" -framework "Pushwoosh" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit" -framework "iAd" -weak_framework "Accounts" -weak_framework "AudioToolbox" -weak_framework "CoreGraphics" -weak_framework "CoreLocation" -weak_framework "Foundation" -weak_framework "QuartzCore" -weak_framework "Security" -weak_framework "Social" -weak_framework "UIKit"
OTHER_LDFLAGS = $(inherited) -ObjC -l"stdc++" -l"z" -framework "ActionSheetPicker_3_0" -framework "AdSupport" -framework "AppsFlyerLib" -framework "Bolts" -framework "CoreLocation" -framework "CoreTelephony" -framework "FBSDKCoreKit" -framework "FBSDKLoginKit" -framework "Pushwoosh" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit" -framework "iAd" -weak_framework "Accounts" -weak_framework "AudioToolbox" -weak_framework "CoreGraphics" -weak_framework "CoreLocation" -weak_framework "Foundation" -weak_framework "QuartzCore" -weak_framework "Security" -weak_framework "Social" -weak_framework "UIKit"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.

View file

@ -2,7 +2,7 @@ FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ActionShe
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ActionSheetPicker-3.0/ActionSheetPicker_3_0.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Bolts/Bolts.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FBSDKCoreKit/FBSDKCoreKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FBSDKLoginKit/FBSDKLoginKit.framework/Headers"
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
OTHER_LDFLAGS = $(inherited) -ObjC -l"stdc++" -l"z" -framework "ActionSheetPicker_3_0" -framework "AdSupport" -framework "AppsFlyerLib" -framework "Bolts" -framework "CoreLocation" -framework "FBSDKCoreKit" -framework "FBSDKLoginKit" -framework "Pushwoosh" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit" -framework "iAd" -weak_framework "Accounts" -weak_framework "AudioToolbox" -weak_framework "CoreGraphics" -weak_framework "CoreLocation" -weak_framework "Foundation" -weak_framework "QuartzCore" -weak_framework "Security" -weak_framework "Social" -weak_framework "UIKit"
OTHER_LDFLAGS = $(inherited) -ObjC -l"stdc++" -l"z" -framework "ActionSheetPicker_3_0" -framework "AdSupport" -framework "AppsFlyerLib" -framework "Bolts" -framework "CoreLocation" -framework "CoreTelephony" -framework "FBSDKCoreKit" -framework "FBSDKLoginKit" -framework "Pushwoosh" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit" -framework "iAd" -weak_framework "Accounts" -weak_framework "AudioToolbox" -weak_framework "CoreGraphics" -weak_framework "CoreLocation" -weak_framework "Foundation" -weak_framework "QuartzCore" -weak_framework "Security" -weak_framework "Social" -weak_framework "UIKit"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.

View file

@ -2,7 +2,7 @@ FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ActionShe
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/ActionSheetPicker-3.0/ActionSheetPicker_3_0.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Bolts/Bolts.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FBSDKCoreKit/FBSDKCoreKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/FBSDKLoginKit/FBSDKLoginKit.framework/Headers"
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
OTHER_LDFLAGS = $(inherited) -ObjC -l"stdc++" -l"z" -framework "ActionSheetPicker_3_0" -framework "AdSupport" -framework "AppsFlyerLib" -framework "Bolts" -framework "CoreLocation" -framework "FBSDKCoreKit" -framework "FBSDKLoginKit" -framework "Pushwoosh" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit" -framework "iAd" -weak_framework "Accounts" -weak_framework "AudioToolbox" -weak_framework "CoreGraphics" -weak_framework "CoreLocation" -weak_framework "Foundation" -weak_framework "QuartzCore" -weak_framework "Security" -weak_framework "Social" -weak_framework "UIKit"
OTHER_LDFLAGS = $(inherited) -ObjC -l"stdc++" -l"z" -framework "ActionSheetPicker_3_0" -framework "AdSupport" -framework "AppsFlyerLib" -framework "Bolts" -framework "CoreLocation" -framework "CoreTelephony" -framework "FBSDKCoreKit" -framework "FBSDKLoginKit" -framework "Pushwoosh" -framework "Security" -framework "StoreKit" -framework "SystemConfiguration" -framework "UIKit" -framework "iAd" -weak_framework "Accounts" -weak_framework "AudioToolbox" -weak_framework "CoreGraphics" -weak_framework "CoreLocation" -weak_framework "Foundation" -weak_framework "QuartzCore" -weak_framework "Security" -weak_framework "Social" -weak_framework "UIKit"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.

View file

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@ -895,9 +895,264 @@
</objects>
<point key="canvasLocation" x="1400" y="0.0"/>
</scene>
<!--Deeplink Info View Controller-->
<scene sceneID="ced-lm-4Wu">
<objects>
<viewController storyboardIdentifier="DeeplinkInfoViewController" id="4pY-fl-Dz9" customClass="DeeplinkInfoViewController" customModule="maps_me" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="B2x-4b-K8c" customClass="SolidTouchView">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fPt-NL-c4p" userLabel="Container">
<rect key="frame" x="0.0" y="20" width="375" height="647"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Vmu-m5-5eM">
<rect key="frame" x="280" y="0.0" width="387" height="74.5"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalCompressionResistancePriority="751" text="Путеводитель готов к загрузке" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dUX-Zz-AHo" userLabel="Title">
<rect key="frame" x="48" y="354" width="279" height="48"/>
<fontDescription key="fontDescription" type="system" pointSize="20"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular20"/>
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackPrimaryText"/>
</userDefinedRuntimeAttributes>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" verticalCompressionResistancePriority="749" text="Он отобразится на карте и будет работать без интернета" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsLetterSpacingToFitWidth="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="SfW-Kk-drJ" userLabel="Text">
<rect key="frame" x="48" y="418" width="279" height="33.5"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="0.54304901539999995" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular14"/>
<userDefinedRuntimeAttribute type="string" keyPath="colorName" value="blackSecondaryText"/>
</userDefinedRuntimeAttributes>
</label>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="brc-tf-Zne">
<rect key="frame" x="280" y="213" width="387" height="74"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
<button opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="1Tu-YD-hCq" userLabel="NotNow">
<rect key="frame" x="48" y="559" width="279" height="44"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" identifier="welcome_storyboard.button_next2"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="qvi-2W-H2B"/>
</constraints>
<fontDescription key="fontDescription" name="HelveticaNeue" family="Helvetica Neue" pointSize="17"/>
<state key="normal" title="СКАЧАТЬ И НАЧАТЬ">
<color key="titleColor" red="0.01176470588" green="0.47843137250000001" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="textColorHighlightedName" value="white"/>
<userDefinedRuntimeAttribute type="string" keyPath="fontName" value="regular17"/>
<userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
<integer key="value" value="8"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="string" keyPath="textColorName" value="white"/>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="linkBlue"/>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundHighlightedColorName" value="linkBlueHighlighted"/>
</userDefinedRuntimeAttributes>
<connections>
<action selector="onNextButton:" destination="4pY-fl-Dz9" eventType="touchUpInside" id="1zD-Xu-FZ2"/>
</connections>
</button>
<view contentMode="scaleToFill" verticalCompressionResistancePriority="748" translatesAutoresizingMaskIntoConstraints="NO" id="Vs8-78-5jq">
<rect key="frame" x="0.0" y="459.5" width="375" height="92.5"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
<view contentMode="scaleToFill" verticalCompressionResistancePriority="748" translatesAutoresizingMaskIntoConstraints="NO" id="yaj-fy-JGI">
<rect key="frame" x="0.0" y="0.0" width="375" height="93"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="250" image="img_onboarding_guide" translatesAutoresizingMaskIntoConstraints="NO" id="LzY-8z-2Tx">
<rect key="frame" x="67.5" y="94" width="240" height="240"/>
<constraints>
<constraint firstAttribute="width" constant="240" id="3EI-cj-9ta"/>
<constraint firstAttribute="height" constant="240" id="h73-2y-enu"/>
</constraints>
</imageView>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="LzY-8z-2Tx" firstAttribute="leading" secondItem="fPt-NL-c4p" secondAttribute="leading" constant="40" id="16E-BC-9Pk"/>
<constraint firstItem="SfW-Kk-drJ" firstAttribute="trailing" secondItem="dUX-Zz-AHo" secondAttribute="trailing" id="2Xs-Og-8rc"/>
<constraint firstItem="LzY-8z-2Tx" firstAttribute="top" secondItem="yaj-fy-JGI" secondAttribute="bottom" constant="1" id="3c4-ud-FcW"/>
<constraint firstAttribute="trailing" secondItem="brc-tf-Zne" secondAttribute="trailing" id="4xQ-uF-C0X"/>
<constraint firstItem="yaj-fy-JGI" firstAttribute="top" secondItem="fPt-NL-c4p" secondAttribute="top" id="95S-vV-uqY"/>
<constraint firstItem="dUX-Zz-AHo" firstAttribute="leading" secondItem="fPt-NL-c4p" secondAttribute="leading" constant="48" id="9I7-Ez-rbz"/>
<constraint firstItem="Vs8-78-5jq" firstAttribute="top" secondItem="SfW-Kk-drJ" secondAttribute="bottom" constant="8" id="A6x-f1-0ea"/>
<constraint firstItem="1Tu-YD-hCq" firstAttribute="top" secondItem="Vs8-78-5jq" secondAttribute="bottom" constant="7" id="C9y-JI-Icr"/>
<constraint firstItem="dUX-Zz-AHo" firstAttribute="top" secondItem="Vmu-m5-5eM" secondAttribute="bottom" id="D3l-L9-7cX"/>
<constraint firstItem="Vs8-78-5jq" firstAttribute="leading" secondItem="fPt-NL-c4p" secondAttribute="leading" id="Gef-3g-t0f"/>
<constraint firstItem="SfW-Kk-drJ" firstAttribute="top" secondItem="dUX-Zz-AHo" secondAttribute="bottom" constant="16" id="ItC-CN-mSH"/>
<constraint firstAttribute="trailing" secondItem="Vmu-m5-5eM" secondAttribute="trailing" id="J6A-14-dh4"/>
<constraint firstItem="dUX-Zz-AHo" firstAttribute="leading" secondItem="LzY-8z-2Tx" secondAttribute="trailing" constant="44" id="L1p-jj-JHG"/>
<constraint firstAttribute="trailing" secondItem="1Tu-YD-hCq" secondAttribute="trailing" constant="48" id="LWi-iZ-g07"/>
<constraint firstItem="brc-tf-Zne" firstAttribute="height" secondItem="Vmu-m5-5eM" secondAttribute="height" priority="250" id="Mhx-Fj-7lr"/>
<constraint firstItem="1Tu-YD-hCq" firstAttribute="top" secondItem="brc-tf-Zne" secondAttribute="bottom" id="MkP-F6-7dr"/>
<constraint firstAttribute="height" constant="600" id="PSF-NQ-jhY"/>
<constraint firstAttribute="trailing" secondItem="yaj-fy-JGI" secondAttribute="trailing" id="ReY-2S-wxn"/>
<constraint firstAttribute="trailing" secondItem="dUX-Zz-AHo" secondAttribute="trailing" constant="48" id="XhD-DO-tw5"/>
<constraint firstItem="1Tu-YD-hCq" firstAttribute="top" relation="greaterThanOrEqual" secondItem="SfW-Kk-drJ" secondAttribute="bottom" constant="16" id="Yvl-bK-Mc9"/>
<constraint firstItem="dUX-Zz-AHo" firstAttribute="top" secondItem="LzY-8z-2Tx" secondAttribute="bottom" constant="20" id="cGm-7Y-XAf"/>
<constraint firstItem="yaj-fy-JGI" firstAttribute="leading" secondItem="fPt-NL-c4p" secondAttribute="leading" id="e4E-yW-aX2"/>
<constraint firstItem="1Tu-YD-hCq" firstAttribute="leading" secondItem="fPt-NL-c4p" secondAttribute="leading" constant="48" id="gYP-ti-jUu"/>
<constraint firstItem="LzY-8z-2Tx" firstAttribute="centerX" secondItem="fPt-NL-c4p" secondAttribute="centerX" id="hXe-Ro-12x"/>
<constraint firstItem="brc-tf-Zne" firstAttribute="top" secondItem="SfW-Kk-drJ" secondAttribute="bottom" id="iuc-44-cfq"/>
<constraint firstItem="SfW-Kk-drJ" firstAttribute="leading" secondItem="dUX-Zz-AHo" secondAttribute="leading" id="jp5-5h-Q92"/>
<constraint firstAttribute="trailing" secondItem="Vs8-78-5jq" secondAttribute="trailing" id="lEz-qT-lCl"/>
<constraint firstItem="LzY-8z-2Tx" firstAttribute="centerY" secondItem="fPt-NL-c4p" secondAttribute="centerY" id="lyx-FD-aZu"/>
<constraint firstItem="brc-tf-Zne" firstAttribute="leading" secondItem="LzY-8z-2Tx" secondAttribute="trailing" id="mWr-uB-fJJ"/>
<constraint firstAttribute="bottom" secondItem="1Tu-YD-hCq" secondAttribute="bottom" constant="44" id="p7X-x4-QhO"/>
<constraint firstItem="Vmu-m5-5eM" firstAttribute="leading" secondItem="LzY-8z-2Tx" secondAttribute="trailing" id="sqN-MQ-r8W"/>
<constraint firstAttribute="width" constant="520" id="vJF-1E-P1h"/>
<constraint firstItem="Vmu-m5-5eM" firstAttribute="top" secondItem="fPt-NL-c4p" secondAttribute="top" id="wTp-ha-pbF"/>
<constraint firstItem="1Tu-YD-hCq" firstAttribute="leading" secondItem="LzY-8z-2Tx" secondAttribute="trailing" constant="44" id="yPV-ZS-art"/>
<constraint firstItem="Vs8-78-5jq" firstAttribute="height" secondItem="yaj-fy-JGI" secondAttribute="height" id="z6z-Jp-rUN"/>
</constraints>
<variation key="default">
<mask key="subviews">
<exclude reference="Vmu-m5-5eM"/>
<exclude reference="brc-tf-Zne"/>
<exclude reference="Vs8-78-5jq"/>
<exclude reference="yaj-fy-JGI"/>
</mask>
<mask key="constraints">
<exclude reference="PSF-NQ-jhY"/>
<exclude reference="vJF-1E-P1h"/>
<exclude reference="lyx-FD-aZu"/>
<exclude reference="16E-BC-9Pk"/>
<exclude reference="hXe-Ro-12x"/>
<exclude reference="9I7-Ez-rbz"/>
<exclude reference="L1p-jj-JHG"/>
<exclude reference="cGm-7Y-XAf"/>
<exclude reference="gYP-ti-jUu"/>
<exclude reference="yPV-ZS-art"/>
</mask>
</variation>
<variation key="heightClass=compact-widthClass=compact">
<mask key="subviews">
<include reference="Vmu-m5-5eM"/>
<include reference="brc-tf-Zne"/>
</mask>
<mask key="constraints">
<include reference="lyx-FD-aZu"/>
<include reference="16E-BC-9Pk"/>
<include reference="L1p-jj-JHG"/>
<include reference="yPV-ZS-art"/>
</mask>
</variation>
<variation key="heightClass=compact-widthClass=regular">
<mask key="subviews">
<include reference="Vmu-m5-5eM"/>
<include reference="brc-tf-Zne"/>
</mask>
<mask key="constraints">
<include reference="lyx-FD-aZu"/>
<include reference="16E-BC-9Pk"/>
<include reference="L1p-jj-JHG"/>
<include reference="yPV-ZS-art"/>
</mask>
</variation>
<variation key="heightClass=regular-widthClass=compact">
<mask key="subviews">
<include reference="Vs8-78-5jq"/>
<include reference="yaj-fy-JGI"/>
</mask>
<mask key="constraints">
<include reference="hXe-Ro-12x"/>
<include reference="9I7-Ez-rbz"/>
<include reference="cGm-7Y-XAf"/>
<include reference="gYP-ti-jUu"/>
</mask>
</variation>
<variation key="heightClass=regular-widthClass=regular">
<mask key="subviews">
<include reference="Vs8-78-5jq"/>
<include reference="yaj-fy-JGI"/>
</mask>
<mask key="constraints">
<include reference="PSF-NQ-jhY"/>
<include reference="vJF-1E-P1h"/>
<include reference="hXe-Ro-12x"/>
<include reference="9I7-Ez-rbz"/>
<include reference="cGm-7Y-XAf"/>
<include reference="gYP-ti-jUu"/>
</mask>
</variation>
</view>
</subviews>
<constraints>
<constraint firstItem="fPt-NL-c4p" firstAttribute="top" secondItem="BtC-hg-mH9" secondAttribute="top" id="0C5-3q-vqV"/>
<constraint firstItem="fPt-NL-c4p" firstAttribute="centerX" secondItem="B2x-4b-K8c" secondAttribute="centerX" id="2TV-TS-FvU"/>
<constraint firstItem="BtC-hg-mH9" firstAttribute="bottom" secondItem="fPt-NL-c4p" secondAttribute="bottom" id="CVZ-iW-3Hs"/>
<constraint firstItem="fPt-NL-c4p" firstAttribute="centerY" secondItem="B2x-4b-K8c" secondAttribute="centerY" id="YnI-ls-f7f"/>
<constraint firstItem="fPt-NL-c4p" firstAttribute="trailing" secondItem="BtC-hg-mH9" secondAttribute="trailing" id="ZEG-Fv-Afz"/>
<constraint firstItem="BtC-hg-mH9" firstAttribute="leading" secondItem="fPt-NL-c4p" secondAttribute="leading" id="avT-oa-Xw4"/>
</constraints>
<viewLayoutGuide key="safeArea" id="BtC-hg-mH9"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="string" keyPath="backgroundColorName" value="white"/>
</userDefinedRuntimeAttributes>
<variation key="default">
<mask key="constraints">
<exclude reference="avT-oa-Xw4"/>
<exclude reference="CVZ-iW-3Hs"/>
<exclude reference="0C5-3q-vqV"/>
<exclude reference="2TV-TS-FvU"/>
<exclude reference="ZEG-Fv-Afz"/>
<exclude reference="YnI-ls-f7f"/>
</mask>
</variation>
<variation key="heightClass=compact-widthClass=compact">
<mask key="constraints">
<include reference="avT-oa-Xw4"/>
<include reference="CVZ-iW-3Hs"/>
<include reference="0C5-3q-vqV"/>
<include reference="ZEG-Fv-Afz"/>
</mask>
</variation>
<variation key="heightClass=compact-widthClass=regular">
<mask key="constraints">
<include reference="avT-oa-Xw4"/>
<include reference="CVZ-iW-3Hs"/>
<include reference="0C5-3q-vqV"/>
<include reference="ZEG-Fv-Afz"/>
</mask>
</variation>
<variation key="heightClass=regular-widthClass=compact">
<mask key="constraints">
<include reference="avT-oa-Xw4"/>
<include reference="CVZ-iW-3Hs"/>
<include reference="0C5-3q-vqV"/>
<include reference="ZEG-Fv-Afz"/>
</mask>
</variation>
<variation key="heightClass=regular-widthClass=regular">
<mask key="constraints">
<include reference="2TV-TS-FvU"/>
<include reference="YnI-ls-f7f"/>
</mask>
</variation>
</view>
<connections>
<outlet property="alertText" destination="SfW-Kk-drJ" id="aQe-EA-2RC"/>
<outlet property="alertTitle" destination="dUX-Zz-AHo" id="SyU-fD-irX"/>
<outlet property="image" destination="LzY-8z-2Tx" id="4Xh-kF-fiY"/>
<outlet property="nextPageButton" destination="1Tu-YD-hCq" id="9IE-Jd-ecb"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="gcD-kn-d2C" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="2066" y="0.0"/>
</scene>
</scenes>
<resources>
<image name="ic_placeholder" width="240" height="240"/>
<image name="img_onboarding_guide" width="240" height="240"/>
<image name="radioBtnOff" width="22" height="22"/>
<image name="radioBtnOn" width="22" height="22"/>
</resources>

View file

@ -0,0 +1,35 @@
protocol DeeplinkInfoViewControllerDelegate: AnyObject {
func deeplinkInfoViewControllerDidFinish(_ viewController: DeeplinkInfoViewController)
}
class DeeplinkInfoViewController: UIViewController {
@IBOutlet weak var image: UIImageView!
@IBOutlet weak var alertTitle: UILabel!
@IBOutlet weak var alertText: UILabel!
@IBOutlet weak var nextPageButton: UIButton!
var deeplinkURL: URL?
var delegate: DeeplinkInfoViewControllerDelegate?
override func viewDidLoad() {
super.viewDidLoad()
guard let dlUrl = deeplinkURL else { return }
switch dlUrl.path {
case "/guides_page":
alertTitle.text = L("onboarding_guide_direct_download_title")
alertText.text = L("onboarding_guide_direct_download_subtitle")
nextPageButton.setTitle(L("onboarding_guide_direct_download_button"), for: .normal)
case "/catalogue":
alertTitle.text = L("onboarding_bydeeplink_guide_title")
alertText.text = L("onboarding_bydeeplink_guide_subtitle")
nextPageButton.setTitle(L("current_location_unknown_continue_button"), for: .normal)
default:
break
}
}
@IBAction func onNextButton(_ sender: UIButton) {
delegate?.deeplinkInfoViewControllerDidFinish(self)
}
}

View file

@ -45,7 +45,8 @@ final class WelcomePageController: UIPageViewController {
controllersToShow.append(TermsOfUseController.controller())
controllersToShow.append(contentsOf: FirstLaunchController.controllers())
} else {
if (WhatsNewController.shouldShowWhatsNew) {
NSLog("deeplinking: whats new check")
if (WhatsNewController.shouldShowWhatsNew && !DeepLinkHandler.shared.isLaunchedByDeeplink) {
controllersToShow.append(contentsOf: WhatsNewController.controllers())
}
}
@ -155,7 +156,16 @@ extension WelcomePageController: WelcomeViewControllerDelegate {
if index + 1 < controllers.count {
nextPage()
} else {
close()
if DeepLinkHandler.shared.isLaunchedByDeeplink {
let sb = UIStoryboard.instance(.welcome)
let vc = sb.instantiateViewController(withIdentifier: "DeeplinkInfoViewController") as! DeeplinkInfoViewController
vc.delegate = self
vc.deeplinkURL = DeepLinkHandler.shared.deeplinkURL
controllers.append(vc)
nextPage()
} else {
close()
}
}
}
@ -163,3 +173,10 @@ extension WelcomePageController: WelcomeViewControllerDelegate {
close()
}
}
extension WelcomePageController: DeeplinkInfoViewControllerDelegate {
func deeplinkInfoViewControllerDidFinish(_ viewController: DeeplinkInfoViewController) {
close()
DeepLinkHandler.shared.handleDeeplink()
}
}

View file

@ -23,10 +23,6 @@ class WelcomeViewController: MWMViewController {
class var key: String { return "" }
static func controllers(firstSession: Bool) -> [WelcomeViewController]? {
return firstSession ? FirstLaunchController.controllers() : WhatsNewController.controllers()
}
override func viewDidLoad() {
super.viewDidLoad()
configInternal()

View file

@ -8,6 +8,7 @@
<array>
<string>applinks:dlink.maps.me</string>
<string>applinks:dlink.mapsme.devmail.ru</string>
<string>applinks:mapsme.onelink.me</string>
</array>
</dict>
</plist>