mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 10:33:45 +00:00
Replace completion handlers with async/await. (#407)
This commit is contained in:
@@ -302,7 +302,7 @@ class AppCoordinator: AppCoordinatorProtocol {
|
|||||||
.sink { [weak self] callback in
|
.sink { [weak self] callback in
|
||||||
switch callback {
|
switch callback {
|
||||||
case .registeredNotifications(let deviceToken):
|
case .registeredNotifications(let deviceToken):
|
||||||
self?.notificationManager?.register(with: deviceToken, completion: nil)
|
Task { await self?.notificationManager?.register(with: deviceToken) }
|
||||||
case .failedToRegisteredNotifications(let error):
|
case .failedToRegisteredNotifications(let error):
|
||||||
self?.notificationManager?.registrationFailed(with: error)
|
self?.notificationManager?.registrationFailed(with: error)
|
||||||
}
|
}
|
||||||
@@ -467,8 +467,8 @@ extension AppCoordinator: NotificationManagerDelegate {
|
|||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
// error or no room proxy
|
// error or no room proxy
|
||||||
service.showLocalNotification(with: "⚠️ " + ElementL10n.dialogTitleError,
|
await service.showLocalNotification(with: "⚠️ " + ElementL10n.dialogTitleError,
|
||||||
subtitle: ElementL10n.a11yErrorSomeMessageNotSent)
|
subtitle: ElementL10n.a11yErrorSomeMessageNotSent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ class MockNotificationManager: NotificationManagerProtocol {
|
|||||||
delegate?.authorizationStatusUpdated(self, granted: false)
|
delegate?.authorizationStatusUpdated(self, granted: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func register(with deviceToken: Data, completion: ((Bool) -> Void)? = nil) { }
|
func register(with deviceToken: Data) async -> Bool { false }
|
||||||
|
|
||||||
func registrationFailed(with error: Error) { }
|
func registrationFailed(with error: Error) { }
|
||||||
|
|
||||||
|
|||||||
@@ -46,30 +46,26 @@ class NotificationManager: NSObject, NotificationManagerProtocol {
|
|||||||
options: [])
|
options: [])
|
||||||
notificationCenter.setNotificationCategories([replyCategory])
|
notificationCenter.setNotificationCategories([replyCategory])
|
||||||
notificationCenter.delegate = self
|
notificationCenter.delegate = self
|
||||||
notificationCenter.requestAuthorization(options: [.alert, .sound, .badge]) { [weak self] granted, error in
|
Task {
|
||||||
guard let self else {
|
do {
|
||||||
return
|
let granted = try await notificationCenter.requestAuthorization(options: [.alert, .sound, .badge])
|
||||||
}
|
|
||||||
if let error {
|
|
||||||
MXLog.debug("[NotificationManager] request authorization failed: \(error)")
|
|
||||||
} else {
|
|
||||||
MXLog.debug("[NotificationManager] permission granted: \(granted)")
|
MXLog.debug("[NotificationManager] permission granted: \(granted)")
|
||||||
DispatchQueue.main.async {
|
await MainActor.run {
|
||||||
self.delegate?.authorizationStatusUpdated(self, granted: granted)
|
self.delegate?.authorizationStatusUpdated(self, granted: granted)
|
||||||
}
|
}
|
||||||
|
} catch {
|
||||||
|
MXLog.debug("[NotificationManager] request authorization failed: \(error)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func register(with deviceToken: Data, completion: ((Bool) -> Void)? = nil) {
|
func register(with deviceToken: Data) async -> Bool {
|
||||||
setPusher(with: deviceToken,
|
await setPusher(with: deviceToken, clientProxy: clientProxy)
|
||||||
clientProxy: clientProxy,
|
|
||||||
completion: completion)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func registrationFailed(with error: Error) { }
|
func registrationFailed(with error: Error) { }
|
||||||
|
|
||||||
func showLocalNotification(with title: String, subtitle: String?) {
|
func showLocalNotification(with title: String, subtitle: String?) async {
|
||||||
let content = UNMutableNotificationContent()
|
let content = UNMutableNotificationContent()
|
||||||
content.title = title
|
content.title = title
|
||||||
if let subtitle {
|
if let subtitle {
|
||||||
@@ -78,44 +74,39 @@ class NotificationManager: NSObject, NotificationManagerProtocol {
|
|||||||
let request = UNNotificationRequest(identifier: ProcessInfo.processInfo.globallyUniqueString,
|
let request = UNNotificationRequest(identifier: ProcessInfo.processInfo.globallyUniqueString,
|
||||||
content: content,
|
content: content,
|
||||||
trigger: nil)
|
trigger: nil)
|
||||||
notificationCenter.add(request) { error in
|
do {
|
||||||
if let error {
|
try await notificationCenter.add(request)
|
||||||
MXLog.debug("[NotificationManager] show local notification failed: \(error)")
|
MXLog.debug("[NotificationManager] show local notification succeeded")
|
||||||
} else {
|
} catch {
|
||||||
MXLog.debug("[NotificationManager] show local notification succeeded")
|
MXLog.debug("[NotificationManager] show local notification failed: \(error)")
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setPusher(with deviceToken: Data,
|
private func setPusher(with deviceToken: Data, clientProxy: ClientProxyProtocol) async -> Bool {
|
||||||
clientProxy: ClientProxyProtocol,
|
do {
|
||||||
completion: ((Bool) -> Void)?) {
|
try await clientProxy.setPusher(pushkey: deviceToken.base64EncodedString(),
|
||||||
Task {
|
kind: .http,
|
||||||
do {
|
appId: ServiceLocator.shared.settings.pusherAppId,
|
||||||
try await clientProxy.setPusher(pushkey: deviceToken.base64EncodedString(),
|
appDisplayName: "\(InfoPlistReader.target.bundleDisplayName) (iOS)",
|
||||||
kind: .http,
|
deviceDisplayName: UIDevice.current.name,
|
||||||
appId: ServiceLocator.shared.settings.pusherAppId,
|
profileTag: pusherProfileTag(),
|
||||||
appDisplayName: "\(InfoPlistReader.target.bundleDisplayName) (iOS)",
|
lang: Bundle.preferredLanguages.first ?? "en",
|
||||||
deviceDisplayName: UIDevice.current.name,
|
url: ServiceLocator.shared.settings.pushGatewayBaseURL.absoluteString,
|
||||||
profileTag: pusherProfileTag(),
|
format: .eventIdOnly,
|
||||||
lang: Bundle.preferredLanguages.first ?? "en",
|
defaultPayload: [
|
||||||
url: ServiceLocator.shared.settings.pushGatewayBaseURL.absoluteString,
|
"aps": [
|
||||||
format: .eventIdOnly,
|
"mutable-content": 1,
|
||||||
defaultPayload: [
|
"alert": [
|
||||||
"aps": [
|
"loc-key": "Notification",
|
||||||
"mutable-content": 1,
|
"loc-args": []
|
||||||
"alert": [
|
|
||||||
"loc-key": "Notification",
|
|
||||||
"loc-args": []
|
|
||||||
]
|
|
||||||
]
|
]
|
||||||
])
|
]
|
||||||
MXLog.debug("[NotificationManager] set pusher succeeded")
|
])
|
||||||
completion?(true)
|
MXLog.debug("[NotificationManager] set pusher succeeded")
|
||||||
} catch {
|
return true
|
||||||
MXLog.debug("[NotificationManager] set pusher failed: \(error)")
|
} catch {
|
||||||
completion?(false)
|
MXLog.debug("[NotificationManager] set pusher failed: \(error)")
|
||||||
}
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ protocol NotificationManagerProtocol {
|
|||||||
var delegate: NotificationManagerDelegate? { get set }
|
var delegate: NotificationManagerDelegate? { get set }
|
||||||
|
|
||||||
func start()
|
func start()
|
||||||
func register(with deviceToken: Data, completion: ((Bool) -> Void)?)
|
func register(with deviceToken: Data) async -> Bool
|
||||||
func registrationFailed(with error: Error)
|
func registrationFailed(with error: Error)
|
||||||
func showLocalNotification(with title: String, subtitle: String?)
|
func showLocalNotification(with title: String, subtitle: String?) async
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import UserNotifications
|
|||||||
|
|
||||||
protocol UserNotificationCenterProtocol: AnyObject {
|
protocol UserNotificationCenterProtocol: AnyObject {
|
||||||
var delegate: UNUserNotificationCenterDelegate? { get set }
|
var delegate: UNUserNotificationCenterDelegate? { get set }
|
||||||
func add(_ request: UNNotificationRequest, withCompletionHandler completionHandler: ((Error?) -> Void)?)
|
func add(_ request: UNNotificationRequest) async throws
|
||||||
func requestAuthorization(options: UNAuthorizationOptions, completionHandler: @escaping (Bool, Error?) -> Void)
|
func requestAuthorization(options: UNAuthorizationOptions) async throws -> Bool
|
||||||
func setNotificationCategories(_ categories: Set<UNNotificationCategory>)
|
func setNotificationCategories(_ categories: Set<UNNotificationCategory>)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,48 +33,29 @@ final class NotificationManagerTests: XCTestCase {
|
|||||||
sut = NotificationManager(clientProxy: clientProxySpy, notificationCenter: notificationCenter)
|
sut = NotificationManager(clientProxy: clientProxySpy, notificationCenter: notificationCenter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func test_whenRegistered_pusherIsCalled() throws {
|
func test_whenRegistered_pusherIsCalled() async {
|
||||||
let expectation = expectation(description: "Callback happened")
|
_ = await sut.register(with: Data())
|
||||||
sut.register(with: Data(), completion: { _ in
|
|
||||||
expectation.fulfill()
|
|
||||||
})
|
|
||||||
waitForExpectations(timeout: 0.5)
|
|
||||||
XCTAssertTrue(clientProxySpy.setPusherCalled)
|
XCTAssertTrue(clientProxySpy.setPusherCalled)
|
||||||
}
|
}
|
||||||
|
|
||||||
func test_whenRegisteredSuccess_completionSuccessIsCalled() throws {
|
func test_whenRegisteredSuccess_completionSuccessIsCalled() async throws {
|
||||||
let expectation = expectation(description: "Callback happened")
|
let success = await sut.register(with: Data())
|
||||||
var success = false
|
|
||||||
sut.register(with: Data(), completion: { s in
|
|
||||||
success = s
|
|
||||||
expectation.fulfill()
|
|
||||||
})
|
|
||||||
waitForExpectations(timeout: 0.5)
|
|
||||||
XCTAssertTrue(success)
|
XCTAssertTrue(success)
|
||||||
}
|
}
|
||||||
|
|
||||||
func test_whenRegisteredAndPusherThrowsError_completionFalseIsCalled() throws {
|
func test_whenRegisteredAndPusherThrowsError_completionFalseIsCalled() async throws {
|
||||||
let expectation = expectation(description: "Callback happened")
|
|
||||||
var success = true
|
|
||||||
enum TestError: Error {
|
enum TestError: Error {
|
||||||
case someError
|
case someError
|
||||||
}
|
}
|
||||||
clientProxySpy.setPusherErrorToThrow = TestError.someError
|
clientProxySpy.setPusherErrorToThrow = TestError.someError
|
||||||
sut.register(with: Data(), completion: { s in
|
let success = await sut.register(with: Data())
|
||||||
success = s
|
|
||||||
expectation.fulfill()
|
|
||||||
})
|
|
||||||
waitForExpectations(timeout: 0.5)
|
|
||||||
XCTAssertFalse(success)
|
XCTAssertFalse(success)
|
||||||
}
|
}
|
||||||
|
|
||||||
func test_whenRegistered_pusherIsCalledWithCorrectValues() throws {
|
@MainActor
|
||||||
let expectation = expectation(description: "Callback happened")
|
func test_whenRegistered_pusherIsCalledWithCorrectValues() async throws {
|
||||||
let pushkeyData = Data("1234".utf8)
|
let pushkeyData = Data("1234".utf8)
|
||||||
sut.register(with: pushkeyData, completion: { _ in
|
_ = await sut.register(with: pushkeyData)
|
||||||
expectation.fulfill()
|
|
||||||
})
|
|
||||||
waitForExpectations(timeout: 0.5)
|
|
||||||
XCTAssertEqual(clientProxySpy.setPusherPushkey, pushkeyData.base64EncodedString())
|
XCTAssertEqual(clientProxySpy.setPusherPushkey, pushkeyData.base64EncodedString())
|
||||||
XCTAssertEqual(clientProxySpy.setPusherAppId, settings?.pusherAppId)
|
XCTAssertEqual(clientProxySpy.setPusherAppId, settings?.pusherAppId)
|
||||||
XCTAssertEqual(clientProxySpy.setPusherKind, .http)
|
XCTAssertEqual(clientProxySpy.setPusherKind, .http)
|
||||||
@@ -98,28 +79,20 @@ final class NotificationManagerTests: XCTestCase {
|
|||||||
XCTAssertTrue(actualPayload.isEqual(to: defaultPayload))
|
XCTAssertTrue(actualPayload.isEqual(to: defaultPayload))
|
||||||
}
|
}
|
||||||
|
|
||||||
func test_whenRegisteredAndPusherTagNotSetInSettings_tagGeneratedAndSavedInSettings() throws {
|
func test_whenRegisteredAndPusherTagNotSetInSettings_tagGeneratedAndSavedInSettings() async throws {
|
||||||
let expectation = expectation(description: "Callback happened")
|
|
||||||
settings?.pusherProfileTag = nil
|
settings?.pusherProfileTag = nil
|
||||||
sut.register(with: Data(), completion: { _ in
|
_ = await sut.register(with: Data())
|
||||||
expectation.fulfill()
|
|
||||||
})
|
|
||||||
waitForExpectations(timeout: 0.5)
|
|
||||||
XCTAssertNotNil(settings?.pusherProfileTag)
|
XCTAssertNotNil(settings?.pusherProfileTag)
|
||||||
}
|
}
|
||||||
|
|
||||||
func test_whenRegisteredAndPusherTagIsSetInSettings_tagNotGenerated() throws {
|
func test_whenRegisteredAndPusherTagIsSetInSettings_tagNotGenerated() async throws {
|
||||||
let expectation = expectation(description: "Callback happened")
|
|
||||||
settings?.pusherProfileTag = "12345"
|
settings?.pusherProfileTag = "12345"
|
||||||
sut.register(with: Data(), completion: { _ in
|
_ = await sut.register(with: Data())
|
||||||
expectation.fulfill()
|
|
||||||
})
|
|
||||||
waitForExpectations(timeout: 0.5)
|
|
||||||
XCTAssertEqual(settings?.pusherProfileTag, "12345")
|
XCTAssertEqual(settings?.pusherProfileTag, "12345")
|
||||||
}
|
}
|
||||||
|
|
||||||
func test_whenShowLocalNotification_notificationRequestGetsAdded() throws {
|
func test_whenShowLocalNotification_notificationRequestGetsAdded() async throws {
|
||||||
sut.showLocalNotification(with: "Title", subtitle: "Subtitle")
|
await sut.showLocalNotification(with: "Title", subtitle: "Subtitle")
|
||||||
let request = try XCTUnwrap(notificationCenter.addRequest)
|
let request = try XCTUnwrap(notificationCenter.addRequest)
|
||||||
XCTAssertEqual(request.content.title, "Title")
|
XCTAssertEqual(request.content.title, "Title")
|
||||||
XCTAssertEqual(request.content.subtitle, "Subtitle")
|
XCTAssertEqual(request.content.subtitle, "Subtitle")
|
||||||
@@ -143,21 +116,18 @@ final class NotificationManagerTests: XCTestCase {
|
|||||||
XCTAssertTrue(delegate.isEqual(sut))
|
XCTAssertTrue(delegate.isEqual(sut))
|
||||||
}
|
}
|
||||||
|
|
||||||
func test_whenStart_requestAuthorizationCalledWithCorrectParams() throws {
|
func test_whenStart_requestAuthorizationCalledWithCorrectParams() async throws {
|
||||||
sut.start()
|
sut.start()
|
||||||
|
await Task.yield()
|
||||||
XCTAssertEqual(notificationCenter.requestAuthorizationOptions, [.alert, .sound, .badge])
|
XCTAssertEqual(notificationCenter.requestAuthorizationOptions, [.alert, .sound, .badge])
|
||||||
}
|
}
|
||||||
|
|
||||||
func test_whenStartAndAuthorizationGranted_delegateCalled() throws {
|
func test_whenStartAndAuthorizationGranted_delegateCalled() async throws {
|
||||||
authorizationStatusWasGranted = false
|
authorizationStatusWasGranted = false
|
||||||
notificationCenter.requestAuthorizationGrantedReturnValue = true
|
notificationCenter.requestAuthorizationGrantedReturnValue = true
|
||||||
sut.delegate = self
|
sut.delegate = self
|
||||||
sut.start()
|
sut.start()
|
||||||
let expectation = expectation(description: "Wait for main thread")
|
try await Task.sleep(for: .milliseconds(100))
|
||||||
DispatchQueue.main.async {
|
|
||||||
expectation.fulfill()
|
|
||||||
}
|
|
||||||
waitForExpectations(timeout: 1, handler: nil)
|
|
||||||
XCTAssertTrue(authorizationStatusWasGranted)
|
XCTAssertTrue(authorizationStatusWasGranted)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,16 +21,15 @@ class UserNotificationCenterSpy: UserNotificationCenterProtocol {
|
|||||||
weak var delegate: UNUserNotificationCenterDelegate?
|
weak var delegate: UNUserNotificationCenterDelegate?
|
||||||
|
|
||||||
var addRequest: UNNotificationRequest?
|
var addRequest: UNNotificationRequest?
|
||||||
func add(_ request: UNNotificationRequest, withCompletionHandler completionHandler: ((Error?) -> Void)?) {
|
func add(_ request: UNNotificationRequest) async throws {
|
||||||
addRequest = request
|
addRequest = request
|
||||||
completionHandler?(nil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var requestAuthorizationOptions: UNAuthorizationOptions?
|
var requestAuthorizationOptions: UNAuthorizationOptions?
|
||||||
var requestAuthorizationGrantedReturnValue = false
|
var requestAuthorizationGrantedReturnValue = false
|
||||||
func requestAuthorization(options: UNAuthorizationOptions, completionHandler: @escaping (Bool, Error?) -> Void) {
|
func requestAuthorization(options: UNAuthorizationOptions) async throws -> Bool {
|
||||||
requestAuthorizationOptions = options
|
requestAuthorizationOptions = options
|
||||||
completionHandler(requestAuthorizationGrantedReturnValue, nil)
|
return requestAuthorizationGrantedReturnValue
|
||||||
}
|
}
|
||||||
|
|
||||||
var notificationCategoriesValue: Set<UNNotificationCategory>?
|
var notificationCategoriesValue: Set<UNNotificationCategory>?
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
Notification Manager: Replace completion handlers with async/await.
|
||||||
Reference in New Issue
Block a user