Skip to content
This repository has been archived by the owner on Sep 14, 2024. It is now read-only.

Commit

Permalink
fix: updates to push singleton
Browse files Browse the repository at this point in the history
  • Loading branch information
gtokman committed Mar 9, 2024
1 parent 43cc6cb commit 28cfd8e
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 52 deletions.
6 changes: 3 additions & 3 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
PODS:
- boost (1.83.0)
- candlefinance-push (0.2.3):
- candlefinance-push (0.4.1):
- glog
- RCT-Folly (= 2022.05.16.00)
- React-Core
Expand Down Expand Up @@ -1179,7 +1179,7 @@ EXTERNAL SOURCES:

SPEC CHECKSUMS:
boost: d3f49c53809116a5d38da093a8aa78bf551aed09
candlefinance-push: 3b3c1f4669c2bf478c146718ca11ea923795b4fe
candlefinance-push: 1519da157c7caa87d313bbe1ec4c66920ee5109e
DoubleConversion: fea03f2699887d960129cc54bba7e52542b6f953
FBLazyVector: 84f6edbe225f38aebd9deaf1540a4160b1f087d7
FBReactNativeSpec: d0086a479be91c44ce4687a962956a352d2dc697
Expand Down Expand Up @@ -1229,6 +1229,6 @@ SPEC CHECKSUMS:
SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17
Yoga: 64cd2a583ead952b0315d5135bf39e053ae9be70

PODFILE CHECKSUM: 041bf51303cf30c6e88a6d2780937e50c827ccf6
PODFILE CHECKSUM: 07ac4e73e4895943d5bb8f9dfb2658c0d89fca69

COCOAPODS: 1.14.3
10 changes: 8 additions & 2 deletions example/ios/PushExample.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,10 @@
"-DFOLLY_USE_LIBCPP=1",
"-DFOLLY_CFG_NO_COROUTINES=1",
);
OTHER_LDFLAGS = "$(inherited) ";
OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
USE_HERMES = false;
Expand Down Expand Up @@ -620,7 +623,10 @@
"-DFOLLY_USE_LIBCPP=1",
"-DFOLLY_CFG_NO_COROUTINES=1",
);
OTHER_LDFLAGS = "$(inherited) ";
OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
USE_HERMES = false;
Expand Down
132 changes: 85 additions & 47 deletions ios/Push.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,65 +2,94 @@ import UIKit
import NotificationCenter
import React

enum NotificationType: String, CaseIterable {
case notificationReceived, deviceTokenReceived, errorReceived
}

struct Action {
let type: NotificationType
let payload: Any!
}

public protocol Logger {
func track(event: String)
}

public class SharedPush: NSObject {

static var sharedInstance: SharedPush? = {
let instance = SharedPush()
return instance
}()

var didInitialize = false
var notificationCallbackDictionary: [String: () -> Void] = [:]
@objc public var emitter: RCTEventEmitter?
var queue: [Action] = []
var logger: Logger?

public func initPush(logger: Logger?) {
guard !didInitialize else {
logger?.track(event: "\(#function) didInitialize: \(didInitialize)")
return
}
Self.sharedInstance = self
didInitialize = true
self.logger = logger
logger?.track(event: "\(#function) didInitialize: \(true)")
}
}

@objc(Push)
final public class Push: RCTEventEmitter {
public lazy var shared = SharedPush.sharedInstance

private var notificationCallbackDictionary: [String: () -> Void] = [:]
private static var isInitialized = false
@objc public static var emitter: RCTEventEmitter?
private static var queue: [Action] = []

override public init() {
super.init()
Self.emitter = self
}

enum NotificationType: String, CaseIterable {
case notificationReceived, deviceTokenReceived, errorReceived
}

struct Action {
let type: NotificationType
let payload: Any!
super.init()
shared?.emitter = self
shared?.logger?.track(event: "\(#function)")
}

private static func sendStoreAction(_ action: Action) {
if let emitter = self.emitter {
private func sendStoreAction(_ action: Action) {
shared?.logger?.track(event: "\(#function)")
if let emitter = shared?.emitter {
emitter.sendEvent(withName: action.type.rawValue, body: action.payload)
}
}

@objc public static func dispatch(type: String, payload: Any!) {
@objc public func dispatch(type: String, payload: Any!) {
shared?.logger?.track(event: "\(#function): \(type)")
let actionObj = Action(type: .init(rawValue: type) ?? .errorReceived, payload: payload)
if isInitialized {
if let didInitialize = shared?.didInitialize, didInitialize {
sendStoreAction(actionObj)
} else {
queue.append(actionObj)
shared?.queue.append(actionObj)
}
}

@objc public override func startObserving() {
Self.isInitialized = true
for event in Self.queue {
Self.sendStoreAction(event)
}
Self.queue = []
}
@objc public override func stopObserving() {
Self.isInitialized = false
}
shared?.logger?.track(event: "\(#function)")
for event in (shared?.queue ?? []) {
sendStoreAction(event)
}
shared?.queue = []
}

@objc public override func stopObserving() {
shared?.logger?.track(event: "\(#function)")
}

public override func supportedEvents() -> [String]! {
return NotificationType.allCases.map { $0.rawValue }
}

@objc(onFinish:withResolver:withRejecter:)
public func onFinish(uuid: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
if let callback = notificationCallbackDictionary[uuid] {
if let callback = shared?.notificationCallbackDictionary[uuid] {
callback()
notificationCallbackDictionary.removeValue(forKey: uuid)
shared?.notificationCallbackDictionary.removeValue(forKey: uuid)
}
shared?.logger?.track(event: "\(#function)")
}

@objc(requestPermissions:withRejecter:)
Expand All @@ -77,10 +106,12 @@ final public class Push: RCTEventEmitter {
}
}
}
shared?.logger?.track(event: "\(#function)")
}

@objc(getAuthorizationStatus:withRejecter:)
func getAuthorizationStatus(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) -> Void {
shared?.logger?.track(event: "\(#function)")
DispatchQueue.main.async {
UNUserNotificationCenter.current().getNotificationSettings { settings in
resolve(settings.authorizationStatus.rawValue)
Expand All @@ -94,6 +125,7 @@ final public class Push: RCTEventEmitter {
UIApplication.shared.registerForRemoteNotifications()
resolve(true)
}
shared?.logger?.track(event: "\(#function)")
}

@objc(isRegisteredForRemoteNotifications:withRejecter:)
Expand All @@ -102,6 +134,7 @@ final public class Push: RCTEventEmitter {
let value = UIApplication.shared.isRegisteredForRemoteNotifications
resolve(value)
}
shared?.logger?.track(event: "\(#function)")
}

}
Expand All @@ -113,63 +146,68 @@ extension Push: UNUserNotificationCenterDelegate {
return String(format: "%02x", data)
}
let token = tokenParts.joined()
Self.dispatch(type: NotificationType.deviceTokenReceived.rawValue, payload: token)
dispatch(type: NotificationType.deviceTokenReceived.rawValue, payload: token)
shared?.logger?.track(event: "\(#function)")
}

public func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
Self.dispatch(
dispatch(
type: NotificationType.errorReceived.rawValue,
payload: error.localizedDescription
)
shared?.logger?.track(event: "\(#function)")
}

public func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
let uuid = UUID().uuidString
Self.dispatch(
dispatch(
type: NotificationType.notificationReceived.rawValue,
payload: ["payload": notification.request.content.userInfo, "uuid": uuid, "kind": "foreground"]
)
notificationCallbackDictionary[uuid] = {
shared?.notificationCallbackDictionary[uuid] = {
completionHandler([.badge, .banner, .sound, .list])
}
DispatchQueue.main.asyncAfter(deadline: .now() + 29) {
if let callback = self.notificationCallbackDictionary[uuid] {
DispatchQueue.main.asyncAfter(deadline: .now() + 29) { [weak self] in
if let callback = self?.shared?.notificationCallbackDictionary[uuid] {
callback()
self.notificationCallbackDictionary.removeValue(forKey: uuid)
self?.shared?.notificationCallbackDictionary.removeValue(forKey: uuid)
}
}
shared?.logger?.track(event: "\(#function)")
}

public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse) async {
Self.dispatch(
dispatch(
type: NotificationType.notificationReceived.rawValue,
payload: ["payload": response.notification.request.content.userInfo, "kind": "opened"]
)
shared?.logger?.track(event: "\(#function)")
}

public func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
if application.applicationState == .active {
Self.dispatch(
dispatch(
type: NotificationType.errorReceived.rawValue,
payload: "Background notification received while the app is foregrounded state, use to handle `notificationReceived` in the foreground."
)
completionHandler(.newData)
return
}
let uuid = UUID().uuidString
Self.dispatch(
dispatch(
type: NotificationType.notificationReceived.rawValue,
payload: ["payload": userInfo, "uuid": uuid, "kind": "background"]
)
notificationCallbackDictionary[uuid] = {
shared?.notificationCallbackDictionary[uuid] = {
completionHandler(.newData)
}
DispatchQueue.main.asyncAfter(deadline: .now() + 29) {
if let callback = self.notificationCallbackDictionary[uuid] {
DispatchQueue.main.asyncAfter(deadline: .now() + 29) { [weak self] in
if let callback = self?.shared?.notificationCallbackDictionary[uuid] {
callback()
self.notificationCallbackDictionary.removeValue(forKey: uuid)
self?.shared?.notificationCallbackDictionary.removeValue(forKey: uuid)
}
}
shared?.logger?.track(event: "\(#function)")
}

}

0 comments on commit 28cfd8e

Please sign in to comment.