diff --git a/Session.xcodeproj/project.pbxproj b/Session.xcodeproj/project.pbxproj index afce3ae07..6e09b0bca 100644 --- a/Session.xcodeproj/project.pbxproj +++ b/Session.xcodeproj/project.pbxproj @@ -169,6 +169,9 @@ B822F9BD26B26CA2003B8CB8 /* TSCall.m in Sources */ = {isa = PBXBuildFile; fileRef = B822F9BC26B26CA2003B8CB8 /* TSCall.m */; }; B822F9BE26B26CA8003B8CB8 /* TSCall.h in Headers */ = {isa = PBXBuildFile; fileRef = B822F9BB26B26C82003B8CB8 /* TSCall.h */; settings = {ATTRIBUTES = (Public, ); }; }; B822F9C526B27C9B003B8CB8 /* Dependencies+MainApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = B822F9C426B27C9B003B8CB8 /* Dependencies+MainApp.swift */; }; + B822F9C826B376EF003B8CB8 /* DarwinNotificationCenter.m in Sources */ = {isa = PBXBuildFile; fileRef = B822F9C726B376EF003B8CB8 /* DarwinNotificationCenter.m */; }; + B822F9C926B376F6003B8CB8 /* DarwinNotificationCenter.h in Headers */ = {isa = PBXBuildFile; fileRef = B822F9C626B376D2003B8CB8 /* DarwinNotificationCenter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + B822F9CB26B37798003B8CB8 /* DarwinNotificationName.swift in Sources */ = {isa = PBXBuildFile; fileRef = B822F9CA26B37798003B8CB8 /* DarwinNotificationName.swift */; }; B8269D2925C7A4B400488AB4 /* InputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8269D2825C7A4B400488AB4 /* InputView.swift */; }; B8269D3325C7A8C600488AB4 /* InputViewButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8269D3225C7A8C600488AB4 /* InputViewButton.swift */; }; B8269D3D25C7B34D00488AB4 /* InputTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8269D3C25C7B34D00488AB4 /* InputTextView.swift */; }; @@ -1170,6 +1173,9 @@ B822F9BC26B26CA2003B8CB8 /* TSCall.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TSCall.m; sourceTree = ""; }; B822F9C326B275FA003B8CB8 /* INSTRUCTIONS.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = INSTRUCTIONS.md; sourceTree = ""; }; B822F9C426B27C9B003B8CB8 /* Dependencies+MainApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Dependencies+MainApp.swift"; sourceTree = ""; }; + B822F9C626B376D2003B8CB8 /* DarwinNotificationCenter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DarwinNotificationCenter.h; sourceTree = ""; }; + B822F9C726B376EF003B8CB8 /* DarwinNotificationCenter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DarwinNotificationCenter.m; sourceTree = ""; }; + B822F9CA26B37798003B8CB8 /* DarwinNotificationName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DarwinNotificationName.swift; sourceTree = ""; }; B8269D2825C7A4B400488AB4 /* InputView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputView.swift; sourceTree = ""; }; B8269D3225C7A8C600488AB4 /* InputViewButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputViewButton.swift; sourceTree = ""; }; B8269D3C25C7B34D00488AB4 /* InputTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputTextView.swift; sourceTree = ""; }; @@ -2334,6 +2340,9 @@ B882A79826AE897E00B5AB69 /* Atomics.swift */, C33FDAA8255A57FF00E217F9 /* BuildConfiguration.swift */, B8F5F58225EC94A6003BF8D4 /* Collection+Subscripting.swift */, + B822F9C626B376D2003B8CB8 /* DarwinNotificationCenter.h */, + B822F9C726B376EF003B8CB8 /* DarwinNotificationCenter.m */, + B822F9CA26B37798003B8CB8 /* DarwinNotificationName.swift */, B8AE75A325A6C6A6001A84D2 /* Data+Trimming.swift */, C3C2A5D52553860A00C340D1 /* Dictionary+Description.swift */, B87EF18026377A1D00124B3C /* Features.swift */, @@ -3699,6 +3708,7 @@ buildActionMask = 2147483647; files = ( C32C5FAA256DFED9003C73A2 /* NSArray+Functional.h in Headers */, + B822F9C926B376F6003B8CB8 /* DarwinNotificationCenter.h in Headers */, C3D9E3FA25676BCE0040E4F3 /* TSYapDatabaseObject.h in Headers */, C3D9E3A4256763DE0040E4F3 /* AppContext.h in Headers */, C3D9E38A256760390040E4F3 /* OWSFileSystem.h in Headers */, @@ -4662,6 +4672,7 @@ C3BBE0A82554D4DE0050F1E3 /* JSON.swift in Sources */, C352A36D2557858E00338F3E /* NSTimer+Proxying.m in Sources */, C32C5A2D256DB849003C73A2 /* LKGroupUtilities.m in Sources */, + B822F9CB26B37798003B8CB8 /* DarwinNotificationName.swift in Sources */, C3C2ABD22553C6C900C340D1 /* Data+SecureRandom.swift in Sources */, B8856E09256F1676001CE70E /* UIDevice+featureSupport.swift in Sources */, B8856DEF256F161F001CE70E /* NSString+SSK.m in Sources */, @@ -4679,6 +4690,7 @@ C32C600F256E07F5003C73A2 /* NSUserDefaults+OWS.m in Sources */, C3D9E35E25675F640040E4F3 /* OWSFileSystem.m in Sources */, C3C2AC2E2553CBEB00C340D1 /* String+Trimming.swift in Sources */, + B822F9C826B376EF003B8CB8 /* DarwinNotificationCenter.m in Sources */, C32C5B48256DC211003C73A2 /* NSNotificationCenter+OWS.m in Sources */, C3D9E3C925676AF30040E4F3 /* TSYapDatabaseObject.m in Sources */, C352A3A62557B60D00338F3E /* TSRequest.m in Sources */, diff --git a/Session/Calls/CallService.swift b/Session/Calls/CallService.swift index b3061eac6..0f0e339e8 100644 --- a/Session/Calls/CallService.swift +++ b/Session/Calls/CallService.swift @@ -827,7 +827,7 @@ extension CallService { owsFailDebug("Unknown thread") return } - Self.notificationPresenter.notifyUser(for: message, thread: thread, wantsSound: true, transaction: transaction) + AppEnvironment.shared.notificationPresenter.notifyUser(for: message, thread: thread, wantsSound: true, transaction: transaction) } } @@ -891,7 +891,7 @@ extension CallService: CallManagerDelegate { transaction: transaction ) }.then { thread throws -> Promise in - let opaqueBuilder = SSKProtoCallMessageOpaque.builder() + let opaqueBuilder = SNProtoCallMessageOpaque.builder() opaqueBuilder.setData(message) let callMessage = OWSOutgoingCallMessage( @@ -955,7 +955,7 @@ extension CallService: CallManagerDelegate { return request } - + firstly(on: .sharedUtility) { session.dataTaskPromise(url, method: httpMethod, headers: headers, body: body) }.done(on: .main) { response in diff --git a/Session/Calls/Group/GroupCallUpdateMessageHandler.swift b/Session/Calls/Group/GroupCallUpdateMessageHandler.swift index 6675c7350..3ba8a860a 100644 --- a/Session/Calls/Group/GroupCallUpdateMessageHandler.swift +++ b/Session/Calls/Group/GroupCallUpdateMessageHandler.swift @@ -39,7 +39,7 @@ class GroupCallUpdateMessageHandler: CallServiceObserver, CallObserver, Dependen } } - func handleUpdateMessage(_ message: SSKProtoDataMessageGroupCallUpdate, for thread: TSGroupThread, serverReceivedTimestamp: UInt64) { + func handleUpdateMessage(_ message: SNProtoDataMessageGroupCallUpdate, for thread: TSGroupThread, serverReceivedTimestamp: UInt64) { Logger.info("Received group call update message for thread: \(thread.uniqueId) eraId: \(String(describing: message.eraID))") DispatchQueue.main.async { Self.callService.peekCallAndUpdateThread( diff --git a/Session/Calls/Individual/IndividualCallService.swift b/Session/Calls/Individual/IndividualCallService.swift index c661f98c2..d29fd1e39 100644 --- a/Session/Calls/Individual/IndividualCallService.swift +++ b/Session/Calls/Individual/IndividualCallService.swift @@ -393,7 +393,7 @@ import WebRTC /** * Remote client (could be caller or callee) sent us a connectivity update. */ - public func handleReceivedIceCandidates(thread: TSContactThread, callId: UInt64, sourceDevice: UInt32, candidates: [SSKProtoCallMessageIceUpdate]) { + public func handleReceivedIceCandidates(thread: TSContactThread, callId: UInt64, sourceDevice: UInt32, candidates: [SNProtoCallMessageIceUpdate]) { AssertIsOnMainThread() let iceCandidates = candidates.filter { $0.id == callId && $0.opaque != nil }.map { $0.opaque! } @@ -415,7 +415,7 @@ import WebRTC /** * The remote client (caller or callee) ended the call. */ - public func handleReceivedHangup(thread: TSContactThread, callId: UInt64, sourceDevice: UInt32, type: SSKProtoCallMessageHangupType, deviceId: UInt32) { + public func handleReceivedHangup(thread: TSContactThread, callId: UInt64, sourceDevice: UInt32, type: SNProtoCallMessageHangupType, deviceId: UInt32) { AssertIsOnMainThread() let hangupType: HangupType diff --git a/Session/Calls/Signaling/WebRTCCallMessageHandler.swift b/Session/Calls/Signaling/WebRTCCallMessageHandler.swift index c8ce59467..753ff52a0 100644 --- a/Session/Calls/Signaling/WebRTCCallMessageHandler.swift +++ b/Session/Calls/Signaling/WebRTCCallMessageHandler.swift @@ -19,7 +19,7 @@ public class WebRTCCallMessageHandler: NSObject, OWSCallMessageHandler { // MARK: - Call Handlers public func receivedOffer( - _ offer: SSKProtoCallMessageOffer, + _ offer: SNProtoCallMessageOffer, from caller: SignalServiceAddress, sourceDevice: UInt32, sentAtTimestamp: UInt64, @@ -29,7 +29,7 @@ public class WebRTCCallMessageHandler: NSObject, OWSCallMessageHandler { ) { AssertIsOnMainThread() - let callType: SSKProtoCallMessageOfferType + let callType: SNProtoCallMessageOfferType if offer.hasType { callType = offer.unwrappedType } else { @@ -52,7 +52,7 @@ public class WebRTCCallMessageHandler: NSObject, OWSCallMessageHandler { ) } - public func receivedAnswer(_ answer: SSKProtoCallMessageAnswer, from caller: SignalServiceAddress, sourceDevice: UInt32, supportsMultiRing: Bool) { + public func receivedAnswer(_ answer: SNProtoCallMessageAnswer, from caller: SignalServiceAddress, sourceDevice: UInt32, supportsMultiRing: Bool) { AssertIsOnMainThread() let thread = TSContactThread.getOrCreateThread(contactAddress: caller) @@ -66,7 +66,7 @@ public class WebRTCCallMessageHandler: NSObject, OWSCallMessageHandler { ) } - public func receivedIceUpdate(_ iceUpdate: [SSKProtoCallMessageIceUpdate], from caller: SignalServiceAddress, sourceDevice: UInt32) { + public func receivedIceUpdate(_ iceUpdate: [SNProtoCallMessageIceUpdate], from caller: SignalServiceAddress, sourceDevice: UInt32) { AssertIsOnMainThread() let thread = TSContactThread.getOrCreateThread(contactAddress: caller) @@ -78,13 +78,13 @@ public class WebRTCCallMessageHandler: NSObject, OWSCallMessageHandler { ) } - public func receivedHangup(_ hangup: SSKProtoCallMessageHangup, from caller: SignalServiceAddress, sourceDevice: UInt32) { + public func receivedHangup(_ hangup: SNProtoCallMessageHangup, from caller: SignalServiceAddress, sourceDevice: UInt32) { AssertIsOnMainThread() // deviceId is optional and defaults to 0. var deviceId: UInt32 = 0 - let type: SSKProtoCallMessageHangupType + let type: SNProtoCallMessageHangupType if hangup.hasType { type = hangup.unwrappedType @@ -106,7 +106,7 @@ public class WebRTCCallMessageHandler: NSObject, OWSCallMessageHandler { ) } - public func receivedBusy(_ busy: SSKProtoCallMessageBusy, from caller: SignalServiceAddress, sourceDevice: UInt32) { + public func receivedBusy(_ busy: SNProtoCallMessageBusy, from caller: SignalServiceAddress, sourceDevice: UInt32) { AssertIsOnMainThread() let thread = TSContactThread.getOrCreateThread(contactAddress: caller) @@ -118,7 +118,7 @@ public class WebRTCCallMessageHandler: NSObject, OWSCallMessageHandler { } public func receivedOpaque( - _ opaque: SSKProtoCallMessageOpaque, + _ opaque: SNProtoCallMessageOpaque, from caller: SignalServiceAddress, sourceDevice: UInt32, serverReceivedTimestamp: UInt64, @@ -150,7 +150,7 @@ public class WebRTCCallMessageHandler: NSObject, OWSCallMessageHandler { } public func receivedGroupCallUpdateMessage( - _ update: SSKProtoDataMessageGroupCallUpdate, + _ update: SNProtoDataMessageGroupCallUpdate, for groupThread: TSGroupThread, serverReceivedTimestamp: UInt64) { @@ -158,7 +158,7 @@ public class WebRTCCallMessageHandler: NSObject, OWSCallMessageHandler { callService.groupCallMessageHandler.handleUpdateMessage(update, for: groupThread, serverReceivedTimestamp: serverReceivedTimestamp) } - public func externallyHandleCallMessage(envelope: SSKProtoEnvelope, plaintextData: Data, wasReceivedByUD: Bool, serverDeliveryTimestamp: UInt64, transaction: SDSAnyWriteTransaction) -> Bool { + public func externallyHandleCallMessage(envelope: SNProtoEnvelope, plaintextData: Data, wasReceivedByUD: Bool, serverDeliveryTimestamp: UInt64, transaction: SDSAnyWriteTransaction) -> Bool { return false } } diff --git a/Session/Notifications/AppNotifications.swift b/Session/Notifications/AppNotifications.swift index a42c30ce4..3470edd51 100644 --- a/Session/Notifications/AppNotifications.swift +++ b/Session/Notifications/AppNotifications.swift @@ -68,7 +68,6 @@ extension AppNotificationCategory { case .missedCallFromNoLongerVerifiedIdentity: return "Signal.AppNotificationCategory.missedCallFromNoLongerVerifiedIdentity" } - } } var actions: [AppNotificationAction] { @@ -186,8 +185,8 @@ public class NotificationPresenter: NSObject, NotificationsProtocol { } public func presentIncomingCall(_ call: IndividualCallNotificationInfo, callerName: String) { - let remoteAddress = call.remoteAddress - let thread = TSContactThread.getOrCreateThread(contactAddress: remoteAddress) + let publicKey = call.publicKey + let thread = TSContactThread.getOrCreateThread(contactSessionID: publicKey) let notificationTitle: String? let threadIdentifier: String? @@ -201,9 +200,10 @@ public class NotificationPresenter: NSObject, NotificationsProtocol { } let notificationBody: String + // TODO: Distinguish between incoming audio calls and incoming video calls in the copy here switch call.offerMediaType { - case .audio: notificationBody = NotificationStrings.incomingAudioCallBody - case .video: notificationBody = NotificationStrings.incomingVideoCallBody + case .audio: notificationBody = NotificationStrings.incomingCallBody + case .video: notificationBody = NotificationStrings.incomingCallBody } let userInfo = [ @@ -215,7 +215,6 @@ public class NotificationPresenter: NSObject, NotificationsProtocol { self.adaptee.notify(category: .incomingCall, title: notificationTitle, body: notificationBody, - threadIdentifier: threadIdentifier, userInfo: userInfo, sound: nil, replacingIdentifier: call.localId.uuidString) @@ -223,9 +222,8 @@ public class NotificationPresenter: NSObject, NotificationsProtocol { } public func presentMissedCall(_ call: IndividualCallNotificationInfo, callerName: String) { - - let remoteAddress = call.remoteAddress - let thread = TSContactThread.getOrCreateThread(contactAddress: remoteAddress) + let publicKey = call.publicKey + let thread = TSContactThread.getOrCreateThread(contactSessionID: publicKey) let notificationTitle: String? let threadIdentifier: String? @@ -239,12 +237,13 @@ public class NotificationPresenter: NSObject, NotificationsProtocol { } let notificationBody: String + // TODO: Distinguish between incoming audio calls and incoming video calls in the copy here switch call.offerMediaType { - case .audio: notificationBody = NotificationStrings.missedAudioCallBody - case .video: notificationBody = NotificationStrings.missedVideoCallBody + case .audio: notificationBody = NotificationStrings.missedCallBody + case .video: notificationBody = NotificationStrings.missedCallBody } - let userInfo = userInfoForMissedCall(thread: thread, remoteAddress: remoteAddress) + let userInfo = userInfoForMissedCall(thread: thread, publicKey: publicKey) let category: AppNotificationCategory = (shouldShowActions ? .missedCallWithActions @@ -254,7 +253,6 @@ public class NotificationPresenter: NSObject, NotificationsProtocol { self.adaptee.notify(category: category, title: notificationTitle, body: notificationBody, - threadIdentifier: threadIdentifier, userInfo: userInfo, sound: sound, replacingIdentifier: call.localId.uuidString) @@ -286,7 +284,6 @@ public class NotificationPresenter: NSObject, NotificationsProtocol { self.adaptee.notify(category: .missedCallFromNoLongerVerifiedIdentity, title: notificationTitle, body: notificationBody, - threadIdentifier: threadIdentifier, userInfo: userInfo, sound: sound, replacingIdentifier: call.localId.uuidString) @@ -295,8 +292,8 @@ public class NotificationPresenter: NSObject, NotificationsProtocol { public func presentMissedCallBecauseOfNewIdentity(call: IndividualCallNotificationInfo, callerName: String) { - let remoteAddress = call.remoteAddress - let thread = TSContactThread.getOrCreateThread(contactAddress: remoteAddress) + let publicKey = call.publicKey + let thread = TSContactThread.getOrCreateThread(contactSessionID: publicKey) let notificationTitle: String? let threadIdentifier: String? @@ -309,7 +306,7 @@ public class NotificationPresenter: NSObject, NotificationsProtocol { threadIdentifier = thread.uniqueId } let notificationBody = NotificationStrings.missedCallBecauseOfIdentityChangeBody - let userInfo = userInfoForMissedCall(thread: thread, remoteAddress: remoteAddress) + let userInfo = userInfoForMissedCall(thread: thread, publicKey: publicKey) let category: AppNotificationCategory = (shouldShowActions ? .missedCallWithActions @@ -319,16 +316,15 @@ public class NotificationPresenter: NSObject, NotificationsProtocol { self.adaptee.notify(category: category, title: notificationTitle, body: notificationBody, - threadIdentifier: threadIdentifier, userInfo: userInfo, sound: sound, replacingIdentifier: call.localId.uuidString) } } - private func userInfoForMissedCall(thread: TSThread, remoteAddress: SignalServiceAddress) -> [String: Any] { + private func userInfoForMissedCall(thread: TSThread, publicKey: String) -> [String: Any] { var userInfo: [String: Any] = [ - AppNotificationUserInfoKey.threadId: thread.uniqueId + AppNotificationUserInfoKey.threadId: thread.uniqueId! ] if let uuid = remoteAddress.uuid { userInfo[AppNotificationUserInfoKey.callBackUuid] = uuid.uuidString @@ -630,7 +626,7 @@ extension TruncatedList: Collection { } public protocol IndividualCallNotificationInfo { - var remoteAddress: SignalServiceAddress { get } + var publicKey: String { get } var localId: UUID { get } var offerMediaType: TSRecentCallOfferType { get } } diff --git a/SessionUtilitiesKit/General/DarwinNotificationCenter.h b/SessionUtilitiesKit/General/DarwinNotificationCenter.h new file mode 100644 index 000000000..8077f13e7 --- /dev/null +++ b/SessionUtilitiesKit/General/DarwinNotificationCenter.h @@ -0,0 +1,53 @@ +// +// Copyright (c) 2020 Open Whisper Systems. All rights reserved. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class DarwinNotificationName; + +extern const int DarwinNotificationInvalidObserver; + +@interface DarwinNotificationCenter : NSObject + +/// Determines if an observer token is valid for a current registration. +/// Negative integers are never valid. A positive or zero value is valid +/// if the current process has a registration associated with the given value. +/// @param observerToken The token returned by `addObserverForName:` ++ (BOOL)isValidObserver:(int)observerToken; + +/// Post a darwin notification that can be listened for from other processes. +/// @param name The name of the notification to post. ++ (void)postNotificationName:(DarwinNotificationName *)name; + +/// Add an observer for a darwin notification of the given name. +/// @param name The name of the notification to listen for. +/// @param queue The queue to callback on. +/// @param block The block to callback. Includes the observer token as an input parameter to allow +/// removing the observer after receipt. +/// @return An `int` observer token that can be used to remove this observer. ++ (int)addObserverForName:(DarwinNotificationName *)name queue:(dispatch_queue_t)queue usingBlock:(void (^)(int))block; + +/// Stops listening for notifications registered by the given observer token. +/// @param observerToken The token returned by `addObserverForName:` for the notification you want to stop listening +/// for. ++ (void)removeObserver:(int)observerToken; + +/// Sets the state value for a given observer. This value can be set and read from +/// any process listening for this notification. Note: `setState:` and `getState` +/// are vulnerable to races. +/// @param state The `uint64_t` state you wish to share with another process. +/// @param observerToken The token returned by `addObserverForName:` for the notification you want to set state for. ++ (void)setState:(uint64_t)state forObserver:(int)observerToken; + +/// Retrieves the state for a given observer. This value can be set and read from +/// any process listening for this notification. Note: `setState:` and `getState` +/// are vulnerable to races. +/// @param observerToken The token returned by `addObserverForName:` for the notification you want to get state for. ++ (uint64_t)getStateForObserver:(int)observerToken; + +@end + +NS_ASSUME_NONNULL_END diff --git a/SessionUtilitiesKit/General/DarwinNotificationCenter.m b/SessionUtilitiesKit/General/DarwinNotificationCenter.m new file mode 100644 index 000000000..fb12a4042 --- /dev/null +++ b/SessionUtilitiesKit/General/DarwinNotificationCenter.m @@ -0,0 +1,61 @@ +// +// Copyright (c) 2021 Open Whisper Systems. All rights reserved. +// + +#import +#import +#import + +const int DarwinNotificationInvalidObserver = NOTIFY_TOKEN_INVALID; + +@implementation DarwinNotificationCenter + ++ (BOOL)isValidObserver:(int)observerToken +{ + return notify_is_valid_token(observerToken); +} + ++ (void)postNotificationName:(DarwinNotificationName *)name +{ + notify_post((const char *)name.cString); +} + ++ (int)addObserverForName:(DarwinNotificationName *)name + queue:(dispatch_queue_t)queue + usingBlock:(notify_handler_t)block +{ + int observerToken; + notify_register_dispatch((const char *)name.cString, &observerToken, queue, block); + return observerToken; +} + ++ (void)removeObserver:(int)observerToken +{ + if (![self isValidObserver:observerToken]) { + return; + } + + notify_cancel(observerToken); +} + ++ (void)setState:(uint64_t)state forObserver:(int)observerToken +{ + if (![self isValidObserver:observerToken]) { + return; + } + + notify_set_state(observerToken, state); +} + ++ (uint64_t)getStateForObserver:(int)observerToken +{ + if (![self isValidObserver:observerToken]) { + return 0; + } + + uint64_t state; + notify_get_state(observerToken, &state); + return state; +} + +@end diff --git a/SessionUtilitiesKit/General/DarwinNotificationName.swift b/SessionUtilitiesKit/General/DarwinNotificationName.swift new file mode 100644 index 000000000..15bd1a0a9 --- /dev/null +++ b/SessionUtilitiesKit/General/DarwinNotificationName.swift @@ -0,0 +1,45 @@ +// +// Copyright (c) 2021 Open Whisper Systems. All rights reserved. +// + +import Foundation + +@objc +public class DarwinNotificationName: NSObject, ExpressibleByStringLiteral { + @objc public static let sdsCrossProcess: DarwinNotificationName = "org.signal.sdscrossprocess" + @objc public static let nseDidReceiveNotification: DarwinNotificationName = "org.signal.nseDidReceiveNotification" + @objc public static let mainAppHandledNotification: DarwinNotificationName = "org.signal.mainAppHandledNotification" + @objc public static let mainAppLaunched: DarwinNotificationName = "org.signal.mainAppLaunched" + + public typealias StringLiteralType = String + + private let stringValue: String + + @objc + public var cString: UnsafePointer { + return stringValue.withCString { $0 } + } + + @objc + public var isValid: Bool { + return stringValue.isEmpty == false + } + + public required init(stringLiteral value: String) { + stringValue = value + } + + @objc + public init(_ name: String) { + stringValue = name + } + + public override func isEqual(_ object: Any?) -> Bool { + guard let otherName = object as? DarwinNotificationName else { return false } + return otherName.stringValue == stringValue + } + + public override var hash: Int { + return stringValue.hashValue + } +} diff --git a/SessionUtilitiesKit/Meta/SessionUtilitiesKit.h b/SessionUtilitiesKit/Meta/SessionUtilitiesKit.h index 0f375add2..b9e614298 100644 --- a/SessionUtilitiesKit/Meta/SessionUtilitiesKit.h +++ b/SessionUtilitiesKit/Meta/SessionUtilitiesKit.h @@ -4,6 +4,7 @@ FOUNDATION_EXPORT double SessionUtilitiesKitVersionNumber; FOUNDATION_EXPORT const unsigned char SessionUtilitiesKitVersionString[]; #import +#import #import #import #import