mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 10:33:45 +00:00
Updated setPusher function (#684)
* updated set_pusher function from the SDK * this fixes a crash and allows for the navigation to work by using the threadIdentifier of the notification * adding NCE target * project setup completed with xcodegen * no need for those ugly storyboards * code improvement * removing unused outlet * mocks generated with the comment instead of the marker protocol * updated stencil * fixed unit tests * updated swiftformat * pr comments
This commit is contained in:
@@ -473,11 +473,12 @@ extension AppCoordinator: NotificationManagerDelegate {
|
|||||||
func notificationTapped(_ service: NotificationManagerProtocol, content: UNNotificationContent) async {
|
func notificationTapped(_ service: NotificationManagerProtocol, content: UNNotificationContent) async {
|
||||||
MXLog.info("[AppCoordinator] tappedNotification")
|
MXLog.info("[AppCoordinator] tappedNotification")
|
||||||
|
|
||||||
guard let roomId = content.userInfo[NotificationConstants.UserInfoKey.roomIdentifier] as? String else {
|
// We store the room identifier into the thread identifier
|
||||||
|
guard !content.threadIdentifier.isEmpty else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
userSessionFlowCoordinator?.tryDisplayingRoomScreen(roomId: roomId)
|
userSessionFlowCoordinator?.tryDisplayingRoomScreen(roomId: content.threadIdentifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleInlineReply(_ service: NotificationManagerProtocol, content: UNNotificationContent, replyText: String) async {
|
func handleInlineReply(_ service: NotificationManagerProtocol, content: UNNotificationContent, replyText: String) async {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
// DO NOT EDIT
|
// DO NOT EDIT
|
||||||
|
|
||||||
// swiftlint:disable all
|
// swiftlint:disable all
|
||||||
|
|
||||||
import Combine
|
import Combine
|
||||||
import MatrixRustSDK
|
import MatrixRustSDK
|
||||||
class BugReportServiceMock: BugReportServiceProtocol {
|
class BugReportServiceMock: BugReportServiceProtocol {
|
||||||
@@ -11,18 +10,20 @@ class BugReportServiceMock: BugReportServiceProtocol {
|
|||||||
set(value) { underlyingCrashedLastRun = value }
|
set(value) { underlyingCrashedLastRun = value }
|
||||||
}
|
}
|
||||||
var underlyingCrashedLastRun: Bool!
|
var underlyingCrashedLastRun: Bool!
|
||||||
// MARK: - crash
|
|
||||||
|
//MARK: - crash
|
||||||
|
|
||||||
var crashCallsCount = 0
|
var crashCallsCount = 0
|
||||||
var crashCalled: Bool {
|
var crashCalled: Bool {
|
||||||
return crashCallsCount > 0
|
return crashCallsCount > 0
|
||||||
}
|
}
|
||||||
var crashClosure: (() -> Void)?
|
var crashClosure: (() -> Void)?
|
||||||
|
|
||||||
func crash() {
|
func crash() {
|
||||||
crashCallsCount += 1
|
crashCallsCount += 1
|
||||||
crashClosure?()
|
crashClosure?()
|
||||||
}
|
}
|
||||||
// MARK: - submitBugReport
|
//MARK: - submitBugReport
|
||||||
|
|
||||||
var submitBugReportProgressListenerThrowableError: Error?
|
var submitBugReportProgressListenerThrowableError: Error?
|
||||||
var submitBugReportProgressListenerCallsCount = 0
|
var submitBugReportProgressListenerCallsCount = 0
|
||||||
@@ -33,6 +34,7 @@ class BugReportServiceMock: BugReportServiceProtocol {
|
|||||||
var submitBugReportProgressListenerReceivedInvocations: [(bugReport: BugReport, progressListener: ProgressListener?)] = []
|
var submitBugReportProgressListenerReceivedInvocations: [(bugReport: BugReport, progressListener: ProgressListener?)] = []
|
||||||
var submitBugReportProgressListenerReturnValue: SubmitBugReportResponse!
|
var submitBugReportProgressListenerReturnValue: SubmitBugReportResponse!
|
||||||
var submitBugReportProgressListenerClosure: ((BugReport, ProgressListener?) async throws -> SubmitBugReportResponse)?
|
var submitBugReportProgressListenerClosure: ((BugReport, ProgressListener?) async throws -> SubmitBugReportResponse)?
|
||||||
|
|
||||||
func submitBugReport(_ bugReport: BugReport, progressListener: ProgressListener?) async throws -> SubmitBugReportResponse {
|
func submitBugReport(_ bugReport: BugReport, progressListener: ProgressListener?) async throws -> SubmitBugReportResponse {
|
||||||
if let error = submitBugReportProgressListenerThrowableError {
|
if let error = submitBugReportProgressListenerThrowableError {
|
||||||
throw error
|
throw error
|
||||||
@@ -58,7 +60,8 @@ class SessionVerificationControllerProxyMock: SessionVerificationControllerProxy
|
|||||||
set(value) { underlyingIsVerified = value }
|
set(value) { underlyingIsVerified = value }
|
||||||
}
|
}
|
||||||
var underlyingIsVerified: Bool!
|
var underlyingIsVerified: Bool!
|
||||||
// MARK: - requestVerification
|
|
||||||
|
//MARK: - requestVerification
|
||||||
|
|
||||||
var requestVerificationCallsCount = 0
|
var requestVerificationCallsCount = 0
|
||||||
var requestVerificationCalled: Bool {
|
var requestVerificationCalled: Bool {
|
||||||
@@ -66,6 +69,7 @@ class SessionVerificationControllerProxyMock: SessionVerificationControllerProxy
|
|||||||
}
|
}
|
||||||
var requestVerificationReturnValue: Result<Void, SessionVerificationControllerProxyError>!
|
var requestVerificationReturnValue: Result<Void, SessionVerificationControllerProxyError>!
|
||||||
var requestVerificationClosure: (() async -> Result<Void, SessionVerificationControllerProxyError>)?
|
var requestVerificationClosure: (() async -> Result<Void, SessionVerificationControllerProxyError>)?
|
||||||
|
|
||||||
func requestVerification() async -> Result<Void, SessionVerificationControllerProxyError> {
|
func requestVerification() async -> Result<Void, SessionVerificationControllerProxyError> {
|
||||||
requestVerificationCallsCount += 1
|
requestVerificationCallsCount += 1
|
||||||
if let requestVerificationClosure = requestVerificationClosure {
|
if let requestVerificationClosure = requestVerificationClosure {
|
||||||
@@ -74,7 +78,7 @@ class SessionVerificationControllerProxyMock: SessionVerificationControllerProxy
|
|||||||
return requestVerificationReturnValue
|
return requestVerificationReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// MARK: - startSasVerification
|
//MARK: - startSasVerification
|
||||||
|
|
||||||
var startSasVerificationCallsCount = 0
|
var startSasVerificationCallsCount = 0
|
||||||
var startSasVerificationCalled: Bool {
|
var startSasVerificationCalled: Bool {
|
||||||
@@ -82,6 +86,7 @@ class SessionVerificationControllerProxyMock: SessionVerificationControllerProxy
|
|||||||
}
|
}
|
||||||
var startSasVerificationReturnValue: Result<Void, SessionVerificationControllerProxyError>!
|
var startSasVerificationReturnValue: Result<Void, SessionVerificationControllerProxyError>!
|
||||||
var startSasVerificationClosure: (() async -> Result<Void, SessionVerificationControllerProxyError>)?
|
var startSasVerificationClosure: (() async -> Result<Void, SessionVerificationControllerProxyError>)?
|
||||||
|
|
||||||
func startSasVerification() async -> Result<Void, SessionVerificationControllerProxyError> {
|
func startSasVerification() async -> Result<Void, SessionVerificationControllerProxyError> {
|
||||||
startSasVerificationCallsCount += 1
|
startSasVerificationCallsCount += 1
|
||||||
if let startSasVerificationClosure = startSasVerificationClosure {
|
if let startSasVerificationClosure = startSasVerificationClosure {
|
||||||
@@ -90,7 +95,7 @@ class SessionVerificationControllerProxyMock: SessionVerificationControllerProxy
|
|||||||
return startSasVerificationReturnValue
|
return startSasVerificationReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// MARK: - approveVerification
|
//MARK: - approveVerification
|
||||||
|
|
||||||
var approveVerificationCallsCount = 0
|
var approveVerificationCallsCount = 0
|
||||||
var approveVerificationCalled: Bool {
|
var approveVerificationCalled: Bool {
|
||||||
@@ -98,6 +103,7 @@ class SessionVerificationControllerProxyMock: SessionVerificationControllerProxy
|
|||||||
}
|
}
|
||||||
var approveVerificationReturnValue: Result<Void, SessionVerificationControllerProxyError>!
|
var approveVerificationReturnValue: Result<Void, SessionVerificationControllerProxyError>!
|
||||||
var approveVerificationClosure: (() async -> Result<Void, SessionVerificationControllerProxyError>)?
|
var approveVerificationClosure: (() async -> Result<Void, SessionVerificationControllerProxyError>)?
|
||||||
|
|
||||||
func approveVerification() async -> Result<Void, SessionVerificationControllerProxyError> {
|
func approveVerification() async -> Result<Void, SessionVerificationControllerProxyError> {
|
||||||
approveVerificationCallsCount += 1
|
approveVerificationCallsCount += 1
|
||||||
if let approveVerificationClosure = approveVerificationClosure {
|
if let approveVerificationClosure = approveVerificationClosure {
|
||||||
@@ -106,7 +112,7 @@ class SessionVerificationControllerProxyMock: SessionVerificationControllerProxy
|
|||||||
return approveVerificationReturnValue
|
return approveVerificationReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// MARK: - declineVerification
|
//MARK: - declineVerification
|
||||||
|
|
||||||
var declineVerificationCallsCount = 0
|
var declineVerificationCallsCount = 0
|
||||||
var declineVerificationCalled: Bool {
|
var declineVerificationCalled: Bool {
|
||||||
@@ -114,6 +120,7 @@ class SessionVerificationControllerProxyMock: SessionVerificationControllerProxy
|
|||||||
}
|
}
|
||||||
var declineVerificationReturnValue: Result<Void, SessionVerificationControllerProxyError>!
|
var declineVerificationReturnValue: Result<Void, SessionVerificationControllerProxyError>!
|
||||||
var declineVerificationClosure: (() async -> Result<Void, SessionVerificationControllerProxyError>)?
|
var declineVerificationClosure: (() async -> Result<Void, SessionVerificationControllerProxyError>)?
|
||||||
|
|
||||||
func declineVerification() async -> Result<Void, SessionVerificationControllerProxyError> {
|
func declineVerification() async -> Result<Void, SessionVerificationControllerProxyError> {
|
||||||
declineVerificationCallsCount += 1
|
declineVerificationCallsCount += 1
|
||||||
if let declineVerificationClosure = declineVerificationClosure {
|
if let declineVerificationClosure = declineVerificationClosure {
|
||||||
@@ -122,7 +129,7 @@ class SessionVerificationControllerProxyMock: SessionVerificationControllerProxy
|
|||||||
return declineVerificationReturnValue
|
return declineVerificationReturnValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// MARK: - cancelVerification
|
//MARK: - cancelVerification
|
||||||
|
|
||||||
var cancelVerificationCallsCount = 0
|
var cancelVerificationCallsCount = 0
|
||||||
var cancelVerificationCalled: Bool {
|
var cancelVerificationCalled: Bool {
|
||||||
@@ -130,6 +137,7 @@ class SessionVerificationControllerProxyMock: SessionVerificationControllerProxy
|
|||||||
}
|
}
|
||||||
var cancelVerificationReturnValue: Result<Void, SessionVerificationControllerProxyError>!
|
var cancelVerificationReturnValue: Result<Void, SessionVerificationControllerProxyError>!
|
||||||
var cancelVerificationClosure: (() async -> Result<Void, SessionVerificationControllerProxyError>)?
|
var cancelVerificationClosure: (() async -> Result<Void, SessionVerificationControllerProxyError>)?
|
||||||
|
|
||||||
func cancelVerification() async -> Result<Void, SessionVerificationControllerProxyError> {
|
func cancelVerification() async -> Result<Void, SessionVerificationControllerProxyError> {
|
||||||
cancelVerificationCallsCount += 1
|
cancelVerificationCallsCount += 1
|
||||||
if let cancelVerificationClosure = cancelVerificationClosure {
|
if let cancelVerificationClosure = cancelVerificationClosure {
|
||||||
@@ -139,5 +147,4 @@ class SessionVerificationControllerProxyMock: SessionVerificationControllerProxy
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// swiftlint:enable all
|
// swiftlint:enable all
|
||||||
|
|||||||
+12
-3
@@ -14,6 +14,15 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
// This protocol is used only as a marker
|
import Foundation
|
||||||
// to mark protocols that can be auto-mocked by Sourcery
|
|
||||||
protocol AutoMockable { }
|
extension Dictionary {
|
||||||
|
var jsonString: String? {
|
||||||
|
guard let data = try? JSONSerialization.data(withJSONObject: self,
|
||||||
|
options: [.fragmentsAllowed, .sortedKeys]) else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return String(data: data, encoding: .utf8)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,7 +31,8 @@ struct SubmitBugReportResponse: Decodable {
|
|||||||
var reportUrl: String
|
var reportUrl: String
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol BugReportServiceProtocol: AutoMockable {
|
// sourcery: AutoMockable
|
||||||
|
protocol BugReportServiceProtocol {
|
||||||
var crashedLastRun: Bool { get }
|
var crashedLastRun: Bool { get }
|
||||||
|
|
||||||
func crash()
|
func crash()
|
||||||
|
|||||||
@@ -212,30 +212,15 @@ class ClientProxy: ClientProxyProtocol {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// swiftlint:disable:next function_parameter_count
|
func setPusher(with configuration: PusherConfiguration) async throws {
|
||||||
func setPusher(pushkey: String,
|
try await Task.dispatch(on: .global()) {
|
||||||
kind: PusherKind?,
|
try self.client.setPusher(identifiers: configuration.identifiers,
|
||||||
appId: String,
|
kind: configuration.kind,
|
||||||
appDisplayName: String,
|
appDisplayName: configuration.appDisplayName,
|
||||||
deviceDisplayName: String,
|
deviceDisplayName: configuration.deviceDisplayName,
|
||||||
profileTag: String?,
|
profileTag: configuration.profileTag,
|
||||||
lang: String,
|
lang: configuration.lang)
|
||||||
url: URL?,
|
}
|
||||||
format: PushFormat?,
|
|
||||||
defaultPayload: [AnyHashable: Any]?) async throws {
|
|
||||||
// let defaultPayloadString = jsonString(from: defaultPayload)
|
|
||||||
// try await Task.dispatch(on: .global()) {
|
|
||||||
// try self.client.setPusher(pushkey: pushkey,
|
|
||||||
// kind: kind?.rustValue,
|
|
||||||
// appId: appId,
|
|
||||||
// appDisplayName: appDisplayName,
|
|
||||||
// deviceDisplayName: deviceDisplayName,
|
|
||||||
// profileTag: profileTag,
|
|
||||||
// lang: lang,
|
|
||||||
// url: url,
|
|
||||||
// format: format?.rustValue,
|
|
||||||
// defaultPayload: defaultPayloadString)
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Private
|
// MARK: Private
|
||||||
@@ -399,17 +384,6 @@ class ClientProxy: ClientProxyProtocol {
|
|||||||
fileprivate func didReceiveSlidingSyncUpdate(summary: UpdateSummary) {
|
fileprivate func didReceiveSlidingSyncUpdate(summary: UpdateSummary) {
|
||||||
callbacks.send(.receivedSyncUpdate)
|
callbacks.send(.receivedSyncUpdate)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience method to get the json string of an Encodable
|
|
||||||
private func jsonString(from dictionary: [AnyHashable: Any]?) -> String? {
|
|
||||||
guard let dictionary,
|
|
||||||
let data = try? JSONSerialization.data(withJSONObject: dictionary,
|
|
||||||
options: [.fragmentsAllowed]) else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return String(data: data, encoding: .utf8)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ClientProxy: MediaLoaderProtocol {
|
extension ClientProxy: MediaLoaderProtocol {
|
||||||
|
|||||||
@@ -31,37 +31,24 @@ enum ClientProxyError: Error {
|
|||||||
case failedLoadingMedia
|
case failedLoadingMedia
|
||||||
}
|
}
|
||||||
|
|
||||||
enum PusherKind {
|
|
||||||
case http
|
|
||||||
case email
|
|
||||||
|
|
||||||
// var rustValue: MatrixRustSDK.PusherKind {
|
|
||||||
// switch self {
|
|
||||||
// case .http:
|
|
||||||
// return .http
|
|
||||||
// case .email:
|
|
||||||
// return .email
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
enum PushFormat {
|
|
||||||
case eventIdOnly
|
|
||||||
|
|
||||||
// var rustValue: MatrixRustSDK.PushFormat {
|
|
||||||
// switch self {
|
|
||||||
// case .eventIdOnly:
|
|
||||||
// return .eventIdOnly
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
enum SlidingSyncConstants {
|
enum SlidingSyncConstants {
|
||||||
static let initialTimelineLimit: UInt = 0
|
static let initialTimelineLimit: UInt = 0
|
||||||
static let lastMessageTimelineLimit: UInt = 1
|
static let lastMessageTimelineLimit: UInt = 1
|
||||||
static let timelinePrecachingTimelineLimit: UInt = 20
|
static let timelinePrecachingTimelineLimit: UInt = 20
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This struct represents the configuration that we are using to register the application through Pusher to Sygnal
|
||||||
|
/// using the Matrix Rust SDK, more info here:
|
||||||
|
/// https://github.com/matrix-org/sygnal
|
||||||
|
struct PusherConfiguration {
|
||||||
|
let identifiers: PusherIdentifiers
|
||||||
|
let kind: PusherKind
|
||||||
|
let appDisplayName: String
|
||||||
|
let deviceDisplayName: String
|
||||||
|
let profileTag: String?
|
||||||
|
let lang: String
|
||||||
|
}
|
||||||
|
|
||||||
protocol ClientProxyProtocol: AnyObject, MediaLoaderProtocol {
|
protocol ClientProxyProtocol: AnyObject, MediaLoaderProtocol {
|
||||||
var callbacks: PassthroughSubject<ClientProxyCallback, Never> { get }
|
var callbacks: PassthroughSubject<ClientProxyCallback, Never> { get }
|
||||||
|
|
||||||
@@ -97,15 +84,5 @@ protocol ClientProxyProtocol: AnyObject, MediaLoaderProtocol {
|
|||||||
|
|
||||||
func logout() async
|
func logout() async
|
||||||
|
|
||||||
// swiftlint:disable:next function_parameter_count
|
func setPusher(with configuration: PusherConfiguration) async throws
|
||||||
func setPusher(pushkey: String,
|
|
||||||
kind: PusherKind?,
|
|
||||||
appId: String,
|
|
||||||
appDisplayName: String,
|
|
||||||
deviceDisplayName: String,
|
|
||||||
profileTag: String?,
|
|
||||||
lang: String,
|
|
||||||
url: URL?,
|
|
||||||
format: PushFormat?,
|
|
||||||
defaultPayload: [AnyHashable: Any]?) async throws
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,40 +89,13 @@ class MockClientProxy: ClientProxyProtocol {
|
|||||||
// no-op
|
// no-op
|
||||||
}
|
}
|
||||||
|
|
||||||
var setPusherCalled = false
|
|
||||||
var setPusherErrorToThrow: Error?
|
var setPusherErrorToThrow: Error?
|
||||||
var setPusherPushkey: String?
|
var setPusherArgument: PusherConfiguration?
|
||||||
var setPusherKind: PusherKind?
|
var setPusherCalled = false
|
||||||
var setPusherAppId: String?
|
|
||||||
var setPusherAppDisplayName: String?
|
func setPusher(with configuration: PusherConfiguration) async throws {
|
||||||
var setPusherDeviceDisplayName: String?
|
|
||||||
var setPusherProfileTag: String?
|
|
||||||
var setPusherLang: String?
|
|
||||||
var setPusherUrl: URL?
|
|
||||||
var setPusherFormat: PushFormat?
|
|
||||||
var setPusherDefaultPayload: [AnyHashable: Any]?
|
|
||||||
// swiftlint:disable:next function_parameter_count
|
|
||||||
func setPusher(pushkey: String,
|
|
||||||
kind: PusherKind?,
|
|
||||||
appId: String,
|
|
||||||
appDisplayName: String,
|
|
||||||
deviceDisplayName: String,
|
|
||||||
profileTag: String?,
|
|
||||||
lang: String,
|
|
||||||
url: URL?,
|
|
||||||
format: PushFormat?,
|
|
||||||
defaultPayload: [AnyHashable: Any]?) async throws {
|
|
||||||
if let setPusherErrorToThrow { throw setPusherErrorToThrow }
|
if let setPusherErrorToThrow { throw setPusherErrorToThrow }
|
||||||
setPusherCalled = true
|
setPusherCalled = true
|
||||||
setPusherPushkey = pushkey
|
setPusherArgument = configuration
|
||||||
setPusherKind = kind
|
|
||||||
setPusherAppId = appId
|
|
||||||
setPusherAppDisplayName = appDisplayName
|
|
||||||
setPusherDeviceDisplayName = deviceDisplayName
|
|
||||||
setPusherProfileTag = profileTag
|
|
||||||
setPusherLang = lang
|
|
||||||
setPusherUrl = url
|
|
||||||
setPusherFormat = format
|
|
||||||
setPusherDefaultPayload = defaultPayload
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,24 +84,25 @@ class NotificationManager: NSObject, NotificationManagerProtocol {
|
|||||||
|
|
||||||
private func setPusher(with deviceToken: Data, clientProxy: ClientProxyProtocol) async -> Bool {
|
private func setPusher(with deviceToken: Data, clientProxy: ClientProxyProtocol) async -> Bool {
|
||||||
do {
|
do {
|
||||||
try await clientProxy.setPusher(pushkey: deviceToken.base64EncodedString(),
|
let defaultPayload = [
|
||||||
kind: .http,
|
"aps": [
|
||||||
appId: ServiceLocator.shared.settings.pusherAppId,
|
"mutable-content": 1,
|
||||||
appDisplayName: "\(InfoPlistReader.main.bundleDisplayName) (iOS)",
|
"alert": [
|
||||||
deviceDisplayName: UIDevice.current.name,
|
"loc-key": "Notification",
|
||||||
profileTag: pusherProfileTag(),
|
"loc-args": []
|
||||||
lang: Bundle.preferredLanguages.first ?? "en",
|
]
|
||||||
url: ServiceLocator.shared.settings.pushGatewayBaseURL,
|
]
|
||||||
format: .eventIdOnly,
|
]
|
||||||
defaultPayload: [
|
let configuration = await PusherConfiguration(identifiers: .init(pushkey: deviceToken.base64EncodedString(),
|
||||||
"aps": [
|
appId: ServiceLocator.shared.settings.pusherAppId),
|
||||||
"mutable-content": 1,
|
kind: .http(data: .init(url: ServiceLocator.shared.settings.pushGatewayBaseURL.absoluteString,
|
||||||
"alert": [
|
format: .eventIdOnly,
|
||||||
"loc-key": "Notification",
|
defaultPayload: defaultPayload.jsonString)),
|
||||||
"loc-args": []
|
appDisplayName: "\(InfoPlistReader.main.bundleDisplayName) (iOS)",
|
||||||
]
|
deviceDisplayName: UIDevice.current.name,
|
||||||
]
|
profileTag: pusherProfileTag(),
|
||||||
])
|
lang: Bundle.preferredLanguages.first ?? "en")
|
||||||
|
try await clientProxy.setPusher(with: configuration)
|
||||||
MXLog.info("[NotificationManager] set pusher succeeded")
|
MXLog.info("[NotificationManager] set pusher succeeded")
|
||||||
return true
|
return true
|
||||||
} catch {
|
} catch {
|
||||||
@@ -144,6 +145,7 @@ extension NotificationManager: UNUserNotificationCenterDelegate {
|
|||||||
return [.badge, .sound, .list, .banner]
|
return [.badge, .sound, .list, .banner]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@MainActor
|
||||||
func userNotificationCenter(_ center: UNUserNotificationCenter,
|
func userNotificationCenter(_ center: UNUserNotificationCenter,
|
||||||
didReceive response: UNNotificationResponse) async {
|
didReceive response: UNNotificationResponse) async {
|
||||||
switch response.actionIdentifier {
|
switch response.actionIdentifier {
|
||||||
|
|||||||
+2
-1
@@ -39,7 +39,8 @@ struct SessionVerificationEmoji: Hashable {
|
|||||||
let description: String
|
let description: String
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol SessionVerificationControllerProxyProtocol: AutoMockable {
|
// sourcery: AutoMockable
|
||||||
|
protocol SessionVerificationControllerProxyProtocol {
|
||||||
var callbacks: PassthroughSubject<SessionVerificationControllerProxyCallback, Never> { get }
|
var callbacks: PassthroughSubject<SessionVerificationControllerProxyCallback, Never> { get }
|
||||||
|
|
||||||
var isVerified: Bool { get }
|
var isVerified: Bool { get }
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2023 New Vector Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import UserNotifications
|
||||||
|
import UserNotificationsUI
|
||||||
|
|
||||||
|
class NotificationViewController: UIViewController, UNNotificationContentExtension {
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
// Do any required interface initialization here.
|
||||||
|
}
|
||||||
|
|
||||||
|
func didReceive(_ notification: UNNotification) {
|
||||||
|
// Handle the received push notification
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
|
<key>CFBundleDisplayName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>$(PRODUCT_NAME)</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>XPC!</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>$(MARKETING_VERSION)</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
|
<key>NSExtension</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSExtensionAttributes</key>
|
||||||
|
<dict>
|
||||||
|
<key>UNNotificationExtensionCategory</key>
|
||||||
|
<string>myNotificationCategory</string>
|
||||||
|
<key>UNNotificationExtensionInitialContentSizeRatio</key>
|
||||||
|
<integer>1</integer>
|
||||||
|
</dict>
|
||||||
|
<key>NSExtensionPointIdentifier</key>
|
||||||
|
<string>com.apple.usernotifications.content-extension</string>
|
||||||
|
<key>NSExtensionPrincipalClass</key>
|
||||||
|
<string>NCE.NotificationViewController</string>
|
||||||
|
</dict>
|
||||||
|
<key>appGroupIdentifier</key>
|
||||||
|
<string>$(APP_GROUP_IDENTIFIER)</string>
|
||||||
|
<key>baseBundleIdentifier</key>
|
||||||
|
<string>$(BASE_BUNDLE_IDENTIFIER)</string>
|
||||||
|
<key>keychainAccessGroupIdentifier</key>
|
||||||
|
<string>$(KEYCHAIN_ACCESS_GROUP_IDENTIFIER)</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
name: NCE
|
||||||
|
|
||||||
|
schemes:
|
||||||
|
NCE:
|
||||||
|
analyze:
|
||||||
|
config: Debug
|
||||||
|
archive:
|
||||||
|
config: Release
|
||||||
|
build:
|
||||||
|
targets:
|
||||||
|
NCE:
|
||||||
|
- running
|
||||||
|
- testing
|
||||||
|
- profiling
|
||||||
|
- analyzing
|
||||||
|
- archiving
|
||||||
|
profile:
|
||||||
|
config: Release
|
||||||
|
run:
|
||||||
|
askForAppToLaunch: true
|
||||||
|
config: Debug
|
||||||
|
debugEnabled: false
|
||||||
|
disableMainThreadChecker: false
|
||||||
|
launchAutomaticallySubstyle: 2
|
||||||
|
test:
|
||||||
|
config: Debug
|
||||||
|
disableMainThreadChecker: false
|
||||||
|
|
||||||
|
targets:
|
||||||
|
NCE:
|
||||||
|
type: app-extension
|
||||||
|
platform: iOS
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
- package: MatrixRustSDK
|
||||||
|
|
||||||
|
info:
|
||||||
|
path: ../SupportingFiles/Info.plist
|
||||||
|
properties:
|
||||||
|
CFBundleDisplayName: $(PRODUCT_NAME)
|
||||||
|
CFBundleShortVersionString: $(MARKETING_VERSION)
|
||||||
|
CFBundleVersion: $(CURRENT_PROJECT_VERSION)
|
||||||
|
appGroupIdentifier: $(APP_GROUP_IDENTIFIER)
|
||||||
|
baseBundleIdentifier: $(BASE_BUNDLE_IDENTIFIER)
|
||||||
|
keychainAccessGroupIdentifier: $(KEYCHAIN_ACCESS_GROUP_IDENTIFIER)
|
||||||
|
NSExtension:
|
||||||
|
NSExtensionPointIdentifier: com.apple.usernotifications.content-extension
|
||||||
|
NSExtensionPrincipalClass: NCE.NotificationViewController
|
||||||
|
NSExtensionAttributes:
|
||||||
|
UNNotificationExtensionCategory: myNotificationCategory
|
||||||
|
UNNotificationExtensionInitialContentSizeRatio: 1
|
||||||
|
|
||||||
|
settings:
|
||||||
|
base:
|
||||||
|
PRODUCT_NAME: NCE
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER: ${BASE_BUNDLE_IDENTIFIER}.nce
|
||||||
|
MARKETING_VERSION: $(MARKETING_VERSION)
|
||||||
|
CURRENT_PROJECT_VERSION: $(CURRENT_PROJECT_VERSION)
|
||||||
|
DEVELOPMENT_TEAM: $(DEVELOPMENT_TEAM)
|
||||||
|
SWIFT_OBJC_INTERFACE_HEADER_NAME: GeneratedInterface-Swift.h
|
||||||
|
debug:
|
||||||
|
release:
|
||||||
|
|
||||||
|
sources:
|
||||||
|
- path: ../Sources
|
||||||
|
- path: ../SupportingFiles
|
||||||
@@ -132,6 +132,8 @@ extension NotificationItemProxy {
|
|||||||
if let subtitle = subtitle {
|
if let subtitle = subtitle {
|
||||||
notification.subtitle = subtitle
|
notification.subtitle = subtitle
|
||||||
}
|
}
|
||||||
|
// We can store the room identifier into the thread identifier since it's used for notifications
|
||||||
|
// that belong to the same group
|
||||||
notification.threadIdentifier = roomId
|
notification.threadIdentifier = roomId
|
||||||
notification.categoryIdentifier = NotificationConstants.Category.reply
|
notification.categoryIdentifier = NotificationConstants.Category.reply
|
||||||
notification.sound = isNoisy ? UNNotificationSound(named: UNNotificationSoundName(rawValue: "message.caf")) : nil
|
notification.sound = isNoisy ? UNNotificationSound(named: UNNotificationSoundName(rawValue: "message.caf")) : nil
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
// swiftlint:disable all
|
// swiftlint:disable all
|
||||||
|
|
||||||
{% for import in argument.autoMockableImports %}
|
{% for import in argument.autoMockableImports %}
|
||||||
import {{ import }}
|
import {{ import }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -40,7 +39,7 @@ import {{ import }}
|
|||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
{% macro methodClosureCallParameters method %}{% for param in method.parameters %}{{ param.name }}{% if not forloop.last %}, {% endif %}{% endfor %}{% endmacro %}
|
{% macro methodClosureCallParameters method %}{% for param in method.parameters %}{{ param.name }}{% if not forloop.last %}, {% endif %}{% endfor %}{% endmacro %}
|
||||||
{% macro mockMethod method %}
|
{% macro mockMethod method %}
|
||||||
// MARK: - {{ method.shortName }}
|
//MARK: - {{ method.shortName }}
|
||||||
|
|
||||||
{% if method.throws %}
|
{% if method.throws %}
|
||||||
{% call methodThrowableErrorDeclaration method %}
|
{% call methodThrowableErrorDeclaration method %}
|
||||||
@@ -67,6 +66,7 @@ import {{ import }}
|
|||||||
{% call accessLevel method.accessLevel %}{% call staticSpecifier method %}var {% call swiftifyMethodName method.selectorName %}ReturnValue: {{ '(' if method.returnTypeName.isClosure and not method.isOptionalReturnType }}{{ method.returnTypeName }}{{ ')' if method.returnTypeName.isClosure and not method.isOptionalReturnType }}{{ '!' if not method.isOptionalReturnType }}
|
{% call accessLevel method.accessLevel %}{% call staticSpecifier method %}var {% call swiftifyMethodName method.selectorName %}ReturnValue: {{ '(' if method.returnTypeName.isClosure and not method.isOptionalReturnType }}{{ method.returnTypeName }}{{ ')' if method.returnTypeName.isClosure and not method.isOptionalReturnType }}{{ '!' if not method.isOptionalReturnType }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% call methodClosureDeclaration method %}
|
{% call methodClosureDeclaration method %}
|
||||||
|
|
||||||
{% if method.isInitializer %}
|
{% if method.isInitializer %}
|
||||||
{% call accessLevel method.accessLevel %}required {{ method.name }} {
|
{% call accessLevel method.accessLevel %}required {{ method.name }} {
|
||||||
{% call methodReceivedParameters method %}
|
{% call methodReceivedParameters method %}
|
||||||
@@ -98,7 +98,7 @@ import {{ import }}
|
|||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
{% macro resetMethod method %}
|
{% macro resetMethod method %}
|
||||||
{# for type method which are mocked, a way to reset the invocation, argument, etc #}
|
{# for type method which are mocked, a way to reset the invocation, argument, etc #}
|
||||||
{% if method.isStatic and not method.isInitializer %} // MARK: - {{ method.shortName }}
|
{% if method.isStatic and not method.isInitializer %} //MARK: - {{ method.shortName }}
|
||||||
{% if not method.isInitializer %}
|
{% if not method.isInitializer %}
|
||||||
{% call swiftifyMethodName method.selectorName %}CallsCount = 0
|
{% call swiftifyMethodName method.selectorName %}CallsCount = 0
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -127,7 +127,8 @@ import {{ import }}
|
|||||||
get { return {% call underlyingMockedVariableName variable %} }
|
get { return {% call underlyingMockedVariableName variable %} }
|
||||||
set(value) { {% call underlyingMockedVariableName variable %} = value }
|
set(value) { {% call underlyingMockedVariableName variable %} = value }
|
||||||
}
|
}
|
||||||
{% call accessLevel variable.readAccess %}var {% call underlyingMockedVariableName variable %}: {{ variable.typeName }}!
|
{% set wrappedTypeName %}{% if variable.typeName.isProtocolComposition %}({{ variable.typeName }}){% else %}{{ variable.typeName }}{% endif %}{% endset %}
|
||||||
|
{% call accessLevel variable.readAccess %}var {% call underlyingMockedVariableName variable %}: {{ wrappedTypeName }}!
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
{% macro variableThrowableErrorDeclaration variable %}
|
{% macro variableThrowableErrorDeclaration variable %}
|
||||||
{% call accessLevel variable.readAccess %}var {% call mockedVariableName variable %}ThrowableError: Error?
|
{% call accessLevel variable.readAccess %}var {% call mockedVariableName variable %}ThrowableError: Error?
|
||||||
@@ -146,6 +147,7 @@ import {{ import }}
|
|||||||
{% call accessLevel variable.readAccess %}var {% call mockedVariableName variable %}Called: Bool {
|
{% call accessLevel variable.readAccess %}var {% call mockedVariableName variable %}Called: Bool {
|
||||||
return {% call mockedVariableName variable %}CallsCount > 0
|
return {% call mockedVariableName variable %}CallsCount > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
{% call accessLevel variable.readAccess %}var {% call mockedVariableName variable %}: {{ variable.typeName }} {
|
{% call accessLevel variable.readAccess %}var {% call mockedVariableName variable %}: {{ variable.typeName }} {
|
||||||
get {% if variable.isAsync %}async {% endif %}{% if variable.throws %}throws {% endif %}{
|
get {% if variable.isAsync %}async {% endif %}{% if variable.throws %}throws {% endif %}{
|
||||||
{% if variable.throws %}
|
{% if variable.throws %}
|
||||||
@@ -181,10 +183,10 @@ import {{ import }}
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
}
|
}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% for method in type.allMethods|!definedInExtension %}
|
{% for method in type.allMethods|!definedInExtension %}
|
||||||
{% call mockMethod method %}
|
{% call mockMethod method %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
}
|
}
|
||||||
{% endif %}{% endfor %}
|
{% endif %}{% endfor %}
|
||||||
|
|
||||||
// swiftlint:enable all
|
// swiftlint:enable all
|
||||||
|
|||||||
@@ -56,16 +56,18 @@ final class NotificationManagerTests: XCTestCase {
|
|||||||
func test_whenRegistered_pusherIsCalledWithCorrectValues() async throws {
|
func test_whenRegistered_pusherIsCalledWithCorrectValues() async throws {
|
||||||
let pushkeyData = Data("1234".utf8)
|
let pushkeyData = Data("1234".utf8)
|
||||||
_ = await notificationManager.register(with: pushkeyData)
|
_ = await notificationManager.register(with: pushkeyData)
|
||||||
XCTAssertEqual(clientProxy.setPusherPushkey, pushkeyData.base64EncodedString())
|
XCTAssertEqual(clientProxy.setPusherArgument?.identifiers.pushkey, pushkeyData.base64EncodedString())
|
||||||
XCTAssertEqual(clientProxy.setPusherAppId, settings?.pusherAppId)
|
XCTAssertEqual(clientProxy.setPusherArgument?.identifiers.appId, settings?.pusherAppId)
|
||||||
XCTAssertEqual(clientProxy.setPusherKind, .http)
|
XCTAssertEqual(clientProxy.setPusherArgument?.appDisplayName, "\(InfoPlistReader.main.bundleDisplayName) (iOS)")
|
||||||
XCTAssertEqual(clientProxy.setPusherAppId, settings?.pusherAppId)
|
XCTAssertEqual(clientProxy.setPusherArgument?.deviceDisplayName, UIDevice.current.name)
|
||||||
XCTAssertEqual(clientProxy.setPusherAppDisplayName, "\(InfoPlistReader.main.bundleDisplayName) (iOS)")
|
XCTAssertNotNil(clientProxy.setPusherArgument?.profileTag)
|
||||||
XCTAssertEqual(clientProxy.setPusherDeviceDisplayName, UIDevice.current.name)
|
XCTAssertEqual(clientProxy.setPusherArgument?.lang, Bundle.preferredLanguages.first)
|
||||||
XCTAssertNotNil(clientProxy.setPusherProfileTag)
|
guard case let .http(data) = clientProxy.setPusherArgument?.kind else {
|
||||||
XCTAssertEqual(clientProxy.setPusherLang, Bundle.preferredLanguages.first)
|
XCTFail("Http kind expected")
|
||||||
XCTAssertEqual(clientProxy.setPusherUrl, settings?.pushGatewayBaseURL)
|
return
|
||||||
XCTAssertEqual(clientProxy.setPusherFormat, .eventIdOnly)
|
}
|
||||||
|
XCTAssertEqual(data.url, settings?.pushGatewayBaseURL.absoluteString)
|
||||||
|
XCTAssertEqual(data.format, .eventIdOnly)
|
||||||
let defaultPayload: [AnyHashable: Any] = [
|
let defaultPayload: [AnyHashable: Any] = [
|
||||||
"aps": [
|
"aps": [
|
||||||
"mutable-content": 1,
|
"mutable-content": 1,
|
||||||
@@ -75,8 +77,7 @@ final class NotificationManagerTests: XCTestCase {
|
|||||||
]
|
]
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
let actualPayload = NSDictionary(dictionary: clientProxy.setPusherDefaultPayload ?? [:])
|
XCTAssertEqual(data.defaultPayload, defaultPayload.jsonString)
|
||||||
XCTAssertTrue(actualPayload.isEqual(to: defaultPayload))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func test_whenRegisteredAndPusherTagNotSetInSettings_tagGeneratedAndSavedInSettings() async throws {
|
func test_whenRegisteredAndPusherTagNotSetInSettings_tagGeneratedAndSavedInSettings() async throws {
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ include:
|
|||||||
- path: UITests/SupportingFiles/target.yml
|
- path: UITests/SupportingFiles/target.yml
|
||||||
- path: IntegrationTests/SupportingFiles/target.yml
|
- path: IntegrationTests/SupportingFiles/target.yml
|
||||||
- path: NSE/SupportingFiles/target.yml
|
- path: NSE/SupportingFiles/target.yml
|
||||||
|
- path: NCE/SupportingFiles/target.yml
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
MatrixRustSDK:
|
MatrixRustSDK:
|
||||||
|
|||||||
Reference in New Issue
Block a user