mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-05 07:18:39 +09:00
Dactyloidae iOS initial commit
This commit is contained in:
parent
daa6179d22
commit
7154a0497e
2123 changed files with 197052 additions and 0 deletions
195
mobile/ios/Client/Application/AdjustIntegration.swift
Normal file
195
mobile/ios/Client/Application/AdjustIntegration.swift
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import Foundation
|
||||
import Shared
|
||||
import AdjustSdk
|
||||
|
||||
private let AdjustIntegrationErrorDomain = "org.mozilla.ios.Firefox.AdjustIntegrationErrorDomain"
|
||||
|
||||
private let AdjustAttributionFileName = "AdjustAttribution.json"
|
||||
|
||||
private let AdjustAppTokenKey = "AdjustAppToken"
|
||||
private let AdjustEnvironmentKey = "AdjustEnvironment"
|
||||
|
||||
private let AdjustSandboxEnvironment = "sandbox"
|
||||
private let AdjustProductionEnvironment = "production"
|
||||
|
||||
private enum AdjustEnvironment: String {
|
||||
case Sandbox = "sandbox"
|
||||
case Production = "production"
|
||||
}
|
||||
|
||||
private struct AdjustSettings {
|
||||
var appToken: String
|
||||
var environment: AdjustEnvironment
|
||||
}
|
||||
|
||||
/// Simple (singleton) object to contain all code related to Adjust. The idea is to capture all logic
|
||||
/// here so that we have one single place where we can see what Adjust is doing. Ideally you only call
|
||||
/// functions in this object from other parts of the application.
|
||||
|
||||
class AdjustIntegration: NSObject {
|
||||
let profile: Profile
|
||||
|
||||
init(profile: Profile) {
|
||||
self.profile = profile
|
||||
}
|
||||
|
||||
/// Return an ADJConfig object if Adjust has been enabled. It is determined from the values in
|
||||
/// the Info.plist file if Adjust should be enabled, and if so, what its application token and
|
||||
/// environment are. If those keys are either missing or empty in the Info.plist then it is
|
||||
/// assumed that Adjust is not enabled for this build.
|
||||
|
||||
fileprivate func getConfig() -> ADJConfig? {
|
||||
guard let settings = getSettings() else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let config = ADJConfig(appToken: settings.appToken, environment: settings.environment.rawValue)
|
||||
if settings.environment == .Sandbox {
|
||||
config?.logLevel = ADJLogLevelDebug
|
||||
}
|
||||
config?.delegate = self
|
||||
return config
|
||||
}
|
||||
|
||||
/// Returns the Adjust settings from our Info.plist. If the settings are missing or invalid, such as an unknown
|
||||
/// environment, then it will return nil.
|
||||
|
||||
fileprivate func getSettings() -> AdjustSettings? {
|
||||
let bundle = Bundle.main
|
||||
guard let adjustAppToken = bundle.object(forInfoDictionaryKey: AdjustAppTokenKey) as? String,
|
||||
let adjustEnvironment = bundle.object(forInfoDictionaryKey: AdjustEnvironmentKey) as? String else {
|
||||
return nil
|
||||
}
|
||||
guard !adjustAppToken.isEmpty && !adjustEnvironment.isEmpty else {
|
||||
return nil
|
||||
}
|
||||
guard let environment = AdjustEnvironment(rawValue: adjustEnvironment) else {
|
||||
Logger.browserLogger.error("Adjust - Invalid environment provided: \(adjustEnvironment)")
|
||||
return nil
|
||||
}
|
||||
return AdjustSettings(appToken: adjustAppToken, environment: environment)
|
||||
}
|
||||
|
||||
/// Returns true if the attribution file is present.
|
||||
|
||||
fileprivate func hasAttribution() throws -> Bool {
|
||||
return FileManager.default.fileExists(atPath: try getAttributionPath())
|
||||
}
|
||||
|
||||
/// Save an `ADJAttribution` instance to a JSON file. Throws an error if the file could not be written. The file
|
||||
/// written is a JSON file with a single dictionary in it. We add one extra item to it that contains the current
|
||||
/// timestamp in seconds since the UNIX epoch.
|
||||
|
||||
fileprivate func saveAttribution(_ attribution: ADJAttribution) throws {
|
||||
if let attributionDictionary = attribution.dictionary() {
|
||||
let dictionary = NSMutableDictionary(dictionary: attributionDictionary)
|
||||
dictionary["_timestamp"] = NSNumber(value: Int64(Date().timeIntervalSince1970) as Int64)
|
||||
let data = try JSONSerialization.data(withJSONObject: dictionary, options: [JSONSerialization.WritingOptions.prettyPrinted])
|
||||
try data.write(to: URL(fileURLWithPath: try getAttributionPath()), options: [])
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the path to the `AdjustAttribution.json` file. Throws an `NSError` if we could not build the path.
|
||||
|
||||
fileprivate func getAttributionPath() throws -> String {
|
||||
guard let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
|
||||
throw NSError(domain: AdjustIntegrationErrorDomain, code: -1,
|
||||
userInfo: [NSLocalizedDescriptionKey: "Could not build \(AdjustAttributionFileName) path"])
|
||||
}
|
||||
|
||||
return url.appendingPathComponent(AdjustAttributionFileName).path
|
||||
}
|
||||
|
||||
/// Return true if Adjust should be enabled. If the user has disabled the Send Anonymous Usage Data then we immediately
|
||||
/// return false. Otherwise we only do one ping, which means we only enable it if we have not seen the attributiond
|
||||
/// data yet.
|
||||
|
||||
fileprivate func shouldEnable() throws -> Bool {
|
||||
if profile.prefs.boolForKey(AppConstants.PrefSendUsageData) ?? true {
|
||||
return true
|
||||
}
|
||||
return try hasAttribution() == false
|
||||
}
|
||||
|
||||
/// Return true if retention (session) tracking should be enabled. This follows the Send Anonymous Usage Data
|
||||
/// setting.
|
||||
|
||||
fileprivate func shouldTrackRetention() -> Bool {
|
||||
return profile.prefs.boolForKey(AppConstants.PrefSendUsageData) ?? true
|
||||
}
|
||||
}
|
||||
|
||||
extension AdjustIntegration: AdjustDelegate {
|
||||
/// This is called as part of `UIApplication.didFinishLaunchingWithOptions()`. We always initialize the
|
||||
/// Adjust SDK. We always let it send the initial attribution ping. Session tracking is only enabled if
|
||||
/// the Send Anonymous Usage Data setting is turned on.
|
||||
|
||||
func triggerApplicationDidFinishLaunchingWithOptions(_ launchOptions: [AnyHashable: Any]?) {
|
||||
do {
|
||||
if let config = getConfig() {
|
||||
// Always initialize Adjust - otherwise we cannot enable/disable it later. Their SDK must be
|
||||
// initialized through appDidFinishLaunching otherwise it will be in a bad state.
|
||||
Adjust.appDidLaunch(config)
|
||||
|
||||
// Disable it right now if we have the attribution and if the user has disabled session tracking. If
|
||||
// we do not have attribution yet then we wait until it comes in and at that point make the decision
|
||||
// to disable Adjust again.
|
||||
if try hasAttribution() {
|
||||
if !shouldTrackRetention() {
|
||||
Logger.browserLogger.info("Adjust - Disabling because sending of usage data is not allowed")
|
||||
Adjust.setEnabled(false)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Logger.browserLogger.info("Adjust - Skipping because no or invalid config found")
|
||||
}
|
||||
} catch let error {
|
||||
Logger.browserLogger.error("Adjust - Disabling because we failed to configure: \(error)")
|
||||
Adjust.setEnabled(false)
|
||||
}
|
||||
}
|
||||
|
||||
/// This is called when Adjust has figured out the attribution. It will call us with a summary
|
||||
/// of all the things it knows. Like the campaign ID. We simply save this to a local file so
|
||||
/// that we know we have done a single attribution ping to Adjust.
|
||||
///
|
||||
/// Here we also disable Adjust based on the Send Anonymous Usage Data setting.
|
||||
|
||||
func adjustAttributionChanged(_ attribution: ADJAttribution!) {
|
||||
do {
|
||||
Logger.browserLogger.info("Adjust - Saving attribution info to disk")
|
||||
try saveAttribution(attribution)
|
||||
} catch let error {
|
||||
Logger.browserLogger.error("Adjust - Failed to save attribution: \(error)")
|
||||
}
|
||||
// Keep Adjust enabled only if the user has allowed this
|
||||
if shouldTrackRetention() {
|
||||
Logger.browserLogger.info("Adjust - Enabling because user allows anonymous usage data collection")
|
||||
Adjust.setEnabled(true)
|
||||
} else {
|
||||
Logger.browserLogger.info("Adjust - Disabling because user does not allow anonymous usage data collection")
|
||||
Adjust.setEnabled(false)
|
||||
}
|
||||
}
|
||||
|
||||
/// This is called from the Settings screen. The settings screen will remember the choice in the
|
||||
/// profile and then use this method to disable or enable Adjust.
|
||||
|
||||
static func setEnabled(_ enabled: Bool) {
|
||||
Adjust.setEnabled(enabled)
|
||||
}
|
||||
|
||||
/// Store the deeplink url from Adjust SDK. Per Adjust documentation, any interstitial view launched could interfere
|
||||
/// with launching the deeplink. We let the interstial view decide what to do with deeplink.
|
||||
/// Ref: https://github.com/adjust/ios_sdk#deferred-deep-linking-scenario
|
||||
|
||||
func adjustDeeplinkResponse(_ deeplink: URL!) -> Bool {
|
||||
profile.prefs.setString("\(deeplink)", forKey: "AdjustDeeplinkKey")
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue