293 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
			
		
		
	
	
			293 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
//
 | 
						|
//  AppDelegate.swift
 | 
						|
//  SodaLive
 | 
						|
//
 | 
						|
//  Created by klaus on 2023/08/09.
 | 
						|
//
 | 
						|
 | 
						|
import UIKit
 | 
						|
import Combine
 | 
						|
 | 
						|
import notifly_sdk
 | 
						|
import AppsFlyerLib
 | 
						|
import FBSDKCoreKit
 | 
						|
import FirebaseCore
 | 
						|
import FirebaseAnalytics
 | 
						|
import FirebaseMessaging
 | 
						|
 | 
						|
class AppDelegate: UIResponder, UIApplicationDelegate {
 | 
						|
    
 | 
						|
    private let gcmMessageIDKey = "gcm.message_id"
 | 
						|
    private let adTrackingRepository = AdTrackingRepository()
 | 
						|
    
 | 
						|
    private var subscription = Set<AnyCancellable>()
 | 
						|
    
 | 
						|
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
 | 
						|
        FirebaseApp.configure()
 | 
						|
        Notifly.initialize(projectId: NOTIFLY_PROJECT_ID, username: NOTIFLY_USERNAME, password: NOTIFLY_PASSWORD)
 | 
						|
        Messaging.messaging().delegate = self
 | 
						|
        setupAppsFlyer()
 | 
						|
        
 | 
						|
        // For iOS 10 display notification (sent via APNS)
 | 
						|
        UNUserNotificationCenter.current().delegate = self
 | 
						|
        
 | 
						|
        let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
 | 
						|
        UNUserNotificationCenter.current().requestAuthorization(
 | 
						|
            options: authOptions,
 | 
						|
            completionHandler: {_, _ in })
 | 
						|
        
 | 
						|
        application.registerForRemoteNotifications()
 | 
						|
        UIApplication.shared.applicationIconBadgeNumber = 0
 | 
						|
        
 | 
						|
        ApplicationDelegate.shared.application(application, didFinishLaunchingWithOptions: launchOptions)
 | 
						|
        AppEvents.shared.activateApp()
 | 
						|
        
 | 
						|
        return true
 | 
						|
    }
 | 
						|
    
 | 
						|
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
 | 
						|
        if let type = userInfo["type"] as? String, type == "POINT_GRANTED" {
 | 
						|
                NotificationCenter.default.post(name: .pointGranted, object: userInfo["message"])
 | 
						|
        } else {
 | 
						|
            Messaging.messaging().appDidReceiveMessage(userInfo)
 | 
						|
            // Print message ID.
 | 
						|
            if let messageID = userInfo[gcmMessageIDKey] {
 | 
						|
                DEBUG_LOG("Message ID: \(messageID)")
 | 
						|
            }
 | 
						|
            
 | 
						|
            // Print full message.
 | 
						|
            DEBUG_LOG("userInfo: \(userInfo)")
 | 
						|
            
 | 
						|
            completionHandler(UIBackgroundFetchResult.newData)
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
 | 
						|
        UserDefaults.set(deviceToken, forKey: .devicePushToken)
 | 
						|
        Messaging.messaging().apnsToken = deviceToken
 | 
						|
        Notifly.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
 | 
						|
    }
 | 
						|
    
 | 
						|
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
 | 
						|
        Notifly.application(application, didFailToRegisterForRemoteNotificationsWithError: error)
 | 
						|
    }
 | 
						|
    
 | 
						|
    func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([any UIUserActivityRestoring]?) -> Void) -> Bool {
 | 
						|
        AppsFlyerLib.shared().continue(userActivity, restorationHandler: nil)
 | 
						|
        return true
 | 
						|
    }
 | 
						|
    
 | 
						|
    private func setupAppsFlyer() {
 | 
						|
        if let infoDic = Bundle.main.infoDictionary, let devKey = infoDic["AppsFlyerDevKey"] as? String, let appId = infoDic["AppsFlyerAppID"] as? String {
 | 
						|
            AppsFlyerLib.shared().appsFlyerDevKey = devKey
 | 
						|
            AppsFlyerLib.shared().appleAppID = appId
 | 
						|
        } else {
 | 
						|
            AppsFlyerLib.shared().appsFlyerDevKey = "tWF2wbJ5nSkya5Ru9mGcPU"
 | 
						|
            AppsFlyerLib.shared().appleAppID = "6461721697"
 | 
						|
        }
 | 
						|
        
 | 
						|
        AppsFlyerLib.shared().waitForATTUserAuthorization(timeoutInterval: 60)
 | 
						|
        
 | 
						|
        AppsFlyerLib.shared().delegate = self
 | 
						|
        AppsFlyerLib.shared().deepLinkDelegate = self
 | 
						|
    }
 | 
						|
    
 | 
						|
    private func logUtmInFirebase() {
 | 
						|
        FirebaseTracking.shared.logUtm()
 | 
						|
    }
 | 
						|
    
 | 
						|
    private func adTrackingAppLaunch(pid: String) {
 | 
						|
        adTrackingRepository.adTrackingAppLaunch(pid: pid)
 | 
						|
            .sink { result in
 | 
						|
                switch result {
 | 
						|
                case .finished:
 | 
						|
                    DEBUG_LOG("finish")
 | 
						|
                case .failure(let error):
 | 
						|
                    ERROR_LOG(error.localizedDescription)
 | 
						|
                }
 | 
						|
            } receiveValue: { _ in
 | 
						|
            }
 | 
						|
            .store(in: &self.subscription)
 | 
						|
        
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
extension AppDelegate: AppsFlyerLibDelegate {
 | 
						|
    func onConversionDataSuccess(_ conversionInfo: [AnyHashable : Any]) {
 | 
						|
        DEBUG_LOG("AppsFlyer Conversion Data: \(conversionInfo)")
 | 
						|
        if let status = conversionInfo["af_status"] as? String, status == "Non-organic" {
 | 
						|
            let pid = conversionInfo["deep_link_sub1"] as? String ?? ""
 | 
						|
            if !pid.isEmpty {
 | 
						|
                UserDefaults.set(pid, forKey: .marketingPid)
 | 
						|
                adTrackingAppLaunch(pid: pid)
 | 
						|
            }
 | 
						|
            
 | 
						|
            if let utmSource = conversionInfo["deep_link_sub2"] as? String {
 | 
						|
                AppState.shared.marketingUtmSource = utmSource
 | 
						|
            }
 | 
						|
            
 | 
						|
            if let utmMedium = conversionInfo["deep_link_sub3"] as? String {
 | 
						|
                AppState.shared.marketingUtmMedium = utmMedium
 | 
						|
            }
 | 
						|
            
 | 
						|
            if let utmCampaign = conversionInfo["deep_link_sub4"] as? String {
 | 
						|
                AppState.shared.marketingUtmCampaign = utmCampaign
 | 
						|
            }
 | 
						|
            
 | 
						|
            let deepLinkValue = conversionInfo["deep_link_value"] as? String ?? ""
 | 
						|
            let deepLinkValueId = Int(conversionInfo["deep_link_sub5"] as? String ?? "") ?? 0
 | 
						|
            
 | 
						|
            if deepLinkValueId > 0 {
 | 
						|
                if deepLinkValue == "series" {
 | 
						|
                    AppState.shared.pushSeriesId = deepLinkValueId
 | 
						|
                } else if deepLinkValue == "content" {
 | 
						|
                    AppState.shared.pushAudioContentId = deepLinkValueId
 | 
						|
                } else if deepLinkValue == "live" {
 | 
						|
                    AppState.shared.pushRoomId = deepLinkValueId
 | 
						|
                } else if deepLinkValue == "channel" {
 | 
						|
                    AppState.shared.pushChannelId = deepLinkValueId
 | 
						|
                }
 | 
						|
            }
 | 
						|
            
 | 
						|
            logUtmInFirebase()
 | 
						|
        }
 | 
						|
    }
 | 
						|
    
 | 
						|
    func onConversionDataFail(_ error: any Error) {
 | 
						|
        DEBUG_LOG("AppsFlyer Conversion Data Failed: \(error.localizedDescription)")
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
extension AppDelegate: DeepLinkDelegate {
 | 
						|
    func didResolveDeepLink(_ result: DeepLinkResult) {
 | 
						|
        switch result.status {
 | 
						|
        case .notFound:
 | 
						|
            DEBUG_LOG("[AFSDK] Deep link not found")
 | 
						|
            return
 | 
						|
        case .failure:
 | 
						|
            DEBUG_LOG("Error \(result.error!)")
 | 
						|
            return
 | 
						|
        case .found:
 | 
						|
            DEBUG_LOG("[AFSDK] Deep link found")
 | 
						|
        }
 | 
						|
        
 | 
						|
        guard let deepLinkObj:DeepLink = result.deepLink else {
 | 
						|
            DEBUG_LOG("[AFSDK] Could not extract deep link object")
 | 
						|
            return
 | 
						|
        }
 | 
						|
        
 | 
						|
        let pid = deepLinkObj.clickEvent["deep_link_sub1"] as? String ?? ""
 | 
						|
        if !pid.isEmpty {
 | 
						|
            UserDefaults.set(pid, forKey: .marketingPid)
 | 
						|
            adTrackingAppLaunch(pid: pid)
 | 
						|
        }
 | 
						|
        
 | 
						|
        if let utmSource = deepLinkObj.clickEvent["deep_link_sub2"] as? String {
 | 
						|
            AppState.shared.marketingUtmSource = utmSource
 | 
						|
        }
 | 
						|
        
 | 
						|
        if let utmMedium = deepLinkObj.clickEvent["deep_link_sub3"] as? String {
 | 
						|
            AppState.shared.marketingUtmMedium = utmMedium
 | 
						|
        }
 | 
						|
        
 | 
						|
        if let utmCampaign = deepLinkObj.clickEvent["deep_link_sub4"] as? String {
 | 
						|
            AppState.shared.marketingUtmCampaign = utmCampaign
 | 
						|
        }
 | 
						|
        
 | 
						|
        let deepLinkValue = deepLinkObj.clickEvent["deep_link_value"] as? String ?? ""
 | 
						|
        let deepLinkValueId = Int(deepLinkObj.clickEvent["deep_link_sub5"] as? String ?? "") ?? 0
 | 
						|
        
 | 
						|
        if deepLinkValueId > 0 {
 | 
						|
            if deepLinkValue == "series" {
 | 
						|
                AppState.shared.pushSeriesId = deepLinkValueId
 | 
						|
            } else if deepLinkValue == "content" {
 | 
						|
                AppState.shared.pushAudioContentId = deepLinkValueId
 | 
						|
            } else if deepLinkValue == "live" {
 | 
						|
                AppState.shared.pushRoomId = deepLinkValueId
 | 
						|
            } else if deepLinkValue == "channel" {
 | 
						|
                AppState.shared.pushChannelId = deepLinkValueId
 | 
						|
            }
 | 
						|
        }
 | 
						|
        
 | 
						|
        logUtmInFirebase()
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
extension AppDelegate: MessagingDelegate {
 | 
						|
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
 | 
						|
        if let fcmToken = fcmToken {
 | 
						|
            DEBUG_LOG("fcmToken: \(fcmToken)")
 | 
						|
            UserDefaults.set(fcmToken, forKey: .pushToken)
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
extension AppDelegate : UNUserNotificationCenterDelegate {
 | 
						|
    
 | 
						|
    // Receive displayed notifications for iOS 10 devices.
 | 
						|
    func userNotificationCenter(
 | 
						|
        _ center: UNUserNotificationCenter,
 | 
						|
        willPresent notification: UNNotification,
 | 
						|
        withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
 | 
						|
    ) {
 | 
						|
        let userInfo = notification.request.content.userInfo
 | 
						|
        
 | 
						|
        // With swizzling disabled you must let Messaging know about the message, for Analytics
 | 
						|
        Messaging.messaging().appDidReceiveMessage(userInfo)
 | 
						|
        
 | 
						|
        Notifly.userNotificationCenter(center, willPresent: notification, withCompletionHandler: completionHandler)
 | 
						|
        
 | 
						|
        // ...
 | 
						|
        
 | 
						|
        // Print full message.
 | 
						|
        DEBUG_LOG("userInfo: \(userInfo)")
 | 
						|
        
 | 
						|
        // Change this to your preferred presentation option
 | 
						|
        completionHandler([.banner, .badge, .sound])
 | 
						|
    }
 | 
						|
    
 | 
						|
    func userNotificationCenter(_ center: UNUserNotificationCenter,
 | 
						|
                                didReceive response: UNNotificationResponse,
 | 
						|
                                withCompletionHandler completionHandler: @escaping () -> Void) {
 | 
						|
        let userInfo = response.notification.request.content.userInfo
 | 
						|
        
 | 
						|
        // With swizzling disabled you must let Messaging know about the message, for Analytics
 | 
						|
        Messaging.messaging().appDidReceiveMessage(userInfo)
 | 
						|
        Notifly.userNotificationCenter(center, didReceive: response)
 | 
						|
        
 | 
						|
        let roomIdString = userInfo["room_id"] as? String
 | 
						|
        let contentIdString = userInfo["content_id"] as? String
 | 
						|
        let channelIdString = userInfo["channel_id"] as? String
 | 
						|
        let messageIdString = userInfo["message_id"] as? String
 | 
						|
        let auditionIdString = userInfo["audition_id"] as? String
 | 
						|
        
 | 
						|
        if let roomIdString = roomIdString, let roomId = Int(roomIdString), roomId > 0 {
 | 
						|
            AppState.shared.pushRoomId = roomId
 | 
						|
        }
 | 
						|
        
 | 
						|
        if let contentIdString = contentIdString, let audioContentId = Int(contentIdString), audioContentId > 0 {
 | 
						|
            AppState.shared.pushAudioContentId = audioContentId
 | 
						|
        }
 | 
						|
        
 | 
						|
        if let channelIdString = channelIdString, let channelId = Int(channelIdString), channelId > 0 {
 | 
						|
            AppState.shared.pushChannelId = channelId
 | 
						|
        }
 | 
						|
        
 | 
						|
        if let messageIdString = messageIdString, let messageId = Int(messageIdString), messageId > 0 {
 | 
						|
            AppState.shared.pushMessageId = messageId
 | 
						|
        }
 | 
						|
        
 | 
						|
        if let auditionIdString = auditionIdString, let auditionId = Int(auditionIdString), auditionId > 0 {
 | 
						|
            AppState.shared.startTab = .audition
 | 
						|
            NotificationCenter.default.post(name: .didReceiveHomeTab, object: HomeViewModel.CurrentTab.audition)
 | 
						|
        }
 | 
						|
        
 | 
						|
        completionHandler()
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
extension Notification.Name {
 | 
						|
    static let pointGranted = Notification.Name("POINT_GRANTED")
 | 
						|
    static let didReceiveHomeTab = Notification.Name("didReceiveHomeTab")
 | 
						|
}
 |