Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat: add debug namespace #112

Draft
wants to merge 12 commits into
base: refactor/merge-cores
Choose a base branch
from
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 6.0.0

- Minimum supported iOS version is now 13.0.

## 5.6.0

- Support the delayed configuration for SDK. Add new public APIs:
Expand Down
33 changes: 0 additions & 33 deletions OptimoveCore/Sources/Classes/AppGroupsHelper.swift

This file was deleted.

15 changes: 13 additions & 2 deletions OptimoveCore/Sources/Classes/Extension/Bundle+HostApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,27 @@
import Foundation

extension Bundle {
/// Returns the bundle containing the host app.
/// https://stackoverflow.com/a/27849695
static func hostAppBundle() -> Bundle? {
static func hostAppBundle() -> Bundle {
let mainBundle = Bundle.main
if mainBundle.bundleURL.pathExtension == "appex" {
// Peel off two directory levels - SOME_APP.app/PlugIns/SOME_APP_EXTENSION.appex
// Peel off two directory levels - APP.app/PlugIns/APP_EXTENSION.appex
let url = mainBundle.bundleURL.deletingLastPathComponent().deletingLastPathComponent()
if let hostBundle = Bundle(url: url) {
return hostBundle
}
}
return mainBundle
}

/// Returns the bundle identifier of the host app.
static var hostAppBundleIdentifier: String {
return hostAppBundle().bundleIdentifier!
}

/// Returns the app group identifier for the SDK app.
static var optimoveAppGroupIdentifier: String {
return "group.\(hostAppBundleIdentifier).optimove"
}
}
59 changes: 0 additions & 59 deletions OptimoveCore/Sources/Classes/KeyValPersistenceHelper.swift

This file was deleted.

12 changes: 9 additions & 3 deletions OptimoveCore/Sources/Classes/MediaHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,27 @@

import Foundation

public enum MediaHelper {
public struct MediaHelper {
enum Error: LocalizedError {
case noMediaUrlFound
case invalidPictureUrl(String)
}

public static func getCompletePictureUrl(pictureUrlString: String, width: UInt) throws -> URL {
let storage: KeyValueStorage

public init(storage: KeyValueStorage) {
self.storage = storage
}

public func getCompletePictureUrl(pictureUrlString: String, width: UInt) throws -> URL {
if pictureUrlString.hasPrefix("https://") || pictureUrlString.hasPrefix("http://") {
guard let url = URL(string: pictureUrlString) else {
throw Error.invalidPictureUrl(pictureUrlString)
}
return url
}

guard let mediaUrl = KeyValPersistenceHelper.object(forKey: OptimobileUserDefaultsKey.MEDIA_BASE_URL.rawValue) as? String else {
guard let mediaUrl: String = storage[.mediaURL] else {
throw Error.noMediaUrlFound
}

Expand Down
63 changes: 26 additions & 37 deletions OptimoveCore/Sources/Classes/OptimobileHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,28 @@

import Foundation

public enum OptimobileHelper {
private static let installIdLock = DispatchSemaphore(value: 1)
public struct OptimobileHelper {
static let installIdLock = DispatchSemaphore(value: 1)
public static let userIdLock = DispatchSemaphore(value: 1)

public static var installId: String {
installIdLock.wait()
let storage: KeyValueStorage

public init(storage: KeyValueStorage) {
self.storage = storage
}

public func installId() -> String {
OptimobileHelper.installIdLock.wait()
defer {
installIdLock.signal()
OptimobileHelper.installIdLock.signal()
}

if let existingID = KeyValPersistenceHelper.object(forKey: OptimobileUserDefaultsKey.INSTALL_UUID.rawValue) {
return existingID as! String
if let existingID: String = storage[.installUUID] {
return existingID
}

let newID = UUID().uuidString
KeyValPersistenceHelper.set(newID, forKey: OptimobileUserDefaultsKey.INSTALL_UUID.rawValue)

storage.set(value: newID, key: .installUUID)
return newID
}

Expand All @@ -27,40 +32,24 @@ public enum OptimobileHelper {

If no user is associated, it returns the Kumulos installation ID
*/
public static var currentUserIdentifier: String {
userIdLock.wait()
defer { userIdLock.signal() }
if let userId = KeyValPersistenceHelper.object(forKey: OptimobileUserDefaultsKey.USER_ID.rawValue) as! String? {
public func currentUserIdentifier() -> String {
OptimobileHelper.userIdLock.wait()
defer { OptimobileHelper.userIdLock.signal() }
if let userId: String = storage[.userID] {
return userId
}

return OptimobileHelper.installId
return installId()
}

public static func getBadgeFromUserInfo(userInfo: [AnyHashable: Any]) -> NSNumber? {
let custom = userInfo["custom"] as? [AnyHashable: Any]
let aps = userInfo["aps"] as? [AnyHashable: Any]

if custom == nil || aps == nil {
return nil
}

let incrementBy: NSNumber? = custom!["badge_inc"] as? NSNumber
let badge: NSNumber? = aps!["badge"] as? NSNumber

if badge == nil {
return nil
}

var newBadge: NSNumber? = badge
if let incrementBy = incrementBy, let currentVal = KeyValPersistenceHelper.object(forKey: OptimobileUserDefaultsKey.BADGE_COUNT.rawValue) as? NSNumber {
newBadge = NSNumber(value: currentVal.intValue + incrementBy.intValue)

if newBadge!.intValue < 0 {
newBadge = 0
}
public func getBadge(notification: PushNotification) -> Int? {
if let incrementBy = notification.badgeIncrement,
let current: Int = storage[.badgeCount]
{
let badge = current + incrementBy
return badge < 0 ? 0 : badge
}

return newBadge
return notification.aps.badge
}
}
5 changes: 1 addition & 4 deletions OptimoveCore/Sources/Classes/OptimobileUserDefaultsKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,14 @@

import Foundation

public enum OptimobileUserDefaultsKey: String {
public enum OptimobileUserDefaultsKey: String, CaseIterable {
case REGION = "KumulosEventsRegion"
case MEDIA_BASE_URL = "KumulosMediaBaseUrl"
case INSTALL_UUID = "KumulosUUID"
case USER_ID = "KumulosCurrentUserID"
case BADGE_COUNT = "KumulosBadgeCount"
case PENDING_NOTIFICATIONS = "KumulosPendingNotifications"
case PENDING_ANALYTICS = "KumulosPendingAnalytics"

// exist only in standard defaults for app
case MIGRATED_TO_GROUPS = "KumulosDidMigrateToAppGroups"
case IN_APP_LAST_SYNCED_AT = "KumulosMessagesLastSyncedAt"
case IN_APP_MOST_RECENT_UPDATED_AT = "KumulosInAppMostRecentUpdatedAt"
case IN_APP_CONSENTED = "KumulosInAppConsented"
Expand Down
24 changes: 15 additions & 9 deletions OptimoveCore/Sources/Classes/PendingNotificationHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@

import Foundation

public enum PendingNotificationHelper {
public static func remove(id: Int) {
public struct PendingNotificationHelper {
let storage: KeyValueStorage

public init(storage: KeyValueStorage) {
self.storage = storage
}

public func remove(id: Int) {
var pendingNotifications = readAll()

if let i = pendingNotifications.firstIndex(where: { $0.id == id }) {
Expand All @@ -13,7 +19,7 @@ public enum PendingNotificationHelper {
}
}

public static func remove(identifier: String) {
public func remove(identifier: String) {
var pendingNotifications = readAll()

if let i = pendingNotifications.firstIndex(where: { $0.identifier == identifier }) {
Expand All @@ -23,18 +29,18 @@ public enum PendingNotificationHelper {
}
}

public static func readAll() -> [PendingNotification] {
public func readAll() -> [PendingNotification] {
var pendingNotifications = [PendingNotification]()
if let data = KeyValPersistenceHelper.object(forKey: OptimobileUserDefaultsKey.PENDING_NOTIFICATIONS.rawValue),
let decoded = try? JSONDecoder().decode([PendingNotification].self, from: data as! Data)
if let data: Data = storage[.pendingNotifications],
let decoded = try? JSONDecoder().decode([PendingNotification].self, from: data)
{
pendingNotifications = decoded
}

return pendingNotifications
}

public static func add(notification: PendingNotification) {
public func add(notification: PendingNotification) {
var pendingNotifications = readAll()

if let _ = pendingNotifications.firstIndex(where: { $0.id == notification.id }) {
Expand All @@ -46,9 +52,9 @@ public enum PendingNotificationHelper {
save(pendingNotifications: pendingNotifications)
}

static func save(pendingNotifications: [PendingNotification]) {
func save(pendingNotifications: [PendingNotification]) {
if let data = try? JSONEncoder().encode(pendingNotifications) {
KeyValPersistenceHelper.set(data, forKey: OptimobileUserDefaultsKey.PENDING_NOTIFICATIONS.rawValue)
storage.set(value: data, key: .pendingNotifications)
}
}
}
6 changes: 3 additions & 3 deletions OptimoveCore/Sources/Classes/PushNotification.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public struct PushNotification: Decodable {
public let aps: Aps
public let attachment: PushNotification.Attachment?
/// Optimove badge
public let badge: Int?
public let badgeIncrement: Int?
public let buttons: [PushNotification.Button]?
public let deeplink: PushNotification.Data?
public let message: PushNotification.Data
Expand All @@ -86,7 +86,7 @@ public struct PushNotification: Decodable {
case a
case aps
case attachments
case badge = "badge_inc"
case badgeIncrement = "badge_inc"
case buttons = "k.buttons"
case custom
case deeplink = "k.deepLink"
Expand All @@ -106,7 +106,7 @@ public struct PushNotification: Decodable {
self.attachment = try container.decodeIfPresent(Attachment.self, forKey: .attachments)

let custom = try container.nestedContainer(keyedBy: CodingKeys.self, forKey: .custom)
self.badge = try custom.decodeIfPresent(Int.self, forKey: .badge)
self.badgeIncrement = try custom.decodeIfPresent(Int.self, forKey: .badgeIncrement)
self.url = try custom.decodeIfPresent(URL.self, forKey: .u)

let a = try custom.nestedContainer(keyedBy: CodingKeys.self, forKey: .a)
Expand Down
19 changes: 19 additions & 0 deletions OptimoveCore/Sources/Classes/Storage/FileManager+AppGroup.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright © 2023 Optimove. All rights reserved.

import Foundation

public extension FileManager {
static func optimoveAppGroupURL() throws -> URL {
let suiteName = Bundle.optimoveAppGroupIdentifier
guard let url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: suiteName) else {
let message = """
Unable to initialize UserDefault with suit name "\(suiteName)".
Highly possible that the client forgot to add the app group as described in the documentation.
Link: https://github.com/optimove-tech/Optimove-SDK-iOS/wiki/SDK-Setup-Capabilities
"""
assertionFailure(message)
throw GuardError.custom(message)
}
return url
}
}
Loading
Loading