mirror of
https://github.com/vector-im/element-ios.git
synced 2024-09-28 23:32:41 +00:00
Merge branch 'release/1.1.3/master'
This commit is contained in:
commit
d2dec60dfd
10 changed files with 227 additions and 520 deletions
31
CHANGES.rst
31
CHANGES.rst
|
@ -1,3 +1,30 @@
|
|||
Changes in 1.1.3 (2020-12-16)
|
||||
=================================================
|
||||
|
||||
✨ Features
|
||||
*
|
||||
|
||||
🙌 Improvements
|
||||
* AuthVC: Update SSO button wording.
|
||||
|
||||
🐛 Bugfix
|
||||
* Refresh account details on NSE runs (#3719).
|
||||
|
||||
⚠️ API Changes
|
||||
*
|
||||
|
||||
🗣 Translations
|
||||
*
|
||||
|
||||
🧱 Build
|
||||
*
|
||||
|
||||
Others
|
||||
*
|
||||
|
||||
Improvements:
|
||||
* Upgrade MatrixKit version ([v0.13.3](https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.13.3)).
|
||||
|
||||
Changes in 1.1.2 (2020-12-02)
|
||||
=================================================
|
||||
|
||||
|
@ -7,6 +34,7 @@ Changes in 1.1.2 (2020-12-02)
|
|||
🙌 Improvements
|
||||
* Room History: Remove the report option for outgoing messages.
|
||||
* Empty views: Add empty screen when there is nothing to display on home, people, favourites and rooms screen (#3836).
|
||||
* BuildSettings.messageDetailsAllowShare now hide /show action button in document preview (#3864).
|
||||
|
||||
🐛 Bugfix
|
||||
* Restore the modular widget events in the rooms histories.
|
||||
|
@ -105,6 +133,7 @@ Changes in 1.0.18 (2020-10-27)
|
|||
* Update MatomoTracker to 7.2.2 (#3570).
|
||||
* Update SwiftGen to 6.3.0 (#3570).
|
||||
* Update SwiftLint to 0.40.3 (#3570).
|
||||
* NSE: Utilize MXBackgroundService on pushes, to make messages available when the app is foregrounded (#3579).
|
||||
|
||||
🐛 Bugfix
|
||||
* Fix typos in UI
|
||||
|
@ -133,7 +162,7 @@ Changes in 1.0.17 (2020-10-14)
|
|||
🙌 Improvements
|
||||
* Device verification: Do not check for existing key backup after SSSS & Cross-Signing reset.
|
||||
* Cross-signing: Detect when cross-signing keys have been changed.
|
||||
* Make copying & pasting media configurable.
|
||||
* Make copying & pasting media configurable.
|
||||
|
||||
🐛 Bugfix
|
||||
*
|
||||
|
|
4
Podfile
4
Podfile
|
@ -11,7 +11,7 @@ use_frameworks!
|
|||
# - `{ {kit spec hash} => {sdk spec hash}` to depend on specific pod options (:git => …, :podspec => …) for each repo. Used by Fastfile during CI
|
||||
#
|
||||
# Warning: our internal tooling depends on the name of this variable name, so be sure not to change it
|
||||
$matrixKitVersion = '= 0.13.2'
|
||||
$matrixKitVersion = '= 0.13.3'
|
||||
# $matrixKitVersion = :local
|
||||
# $matrixKitVersion = {'develop' => 'develop'}
|
||||
|
||||
|
@ -35,7 +35,6 @@ end
|
|||
# Method to import the right MatrixKit flavour
|
||||
def import_MatrixKit
|
||||
pod 'MatrixSDK', $matrixSDKVersionSpec
|
||||
pod 'MatrixSDK/SwiftSupport', $matrixSDKVersionSpec
|
||||
pod 'MatrixSDK/JingleCallStack', $matrixSDKVersionSpec
|
||||
pod 'MatrixKit', $matrixKitVersionSpec
|
||||
end
|
||||
|
@ -43,7 +42,6 @@ end
|
|||
# Method to import the right MatrixKit/AppExtension flavour
|
||||
def import_MatrixKitAppExtension
|
||||
pod 'MatrixSDK', $matrixSDKVersionSpec
|
||||
pod 'MatrixSDK/SwiftSupport', $matrixSDKVersionSpec
|
||||
pod 'MatrixKit/AppExtension', $matrixKitVersionSpec
|
||||
end
|
||||
|
||||
|
|
35
Podfile.lock
35
Podfile.lock
|
@ -60,39 +60,37 @@ PODS:
|
|||
- MatomoTracker (7.2.2):
|
||||
- MatomoTracker/Core (= 7.2.2)
|
||||
- MatomoTracker/Core (7.2.2)
|
||||
- MatrixKit (0.13.2):
|
||||
- MatrixKit (0.13.3):
|
||||
- Down (~> 0.9.3)
|
||||
- DTCoreText (~> 1.6.23)
|
||||
- HPGrowingTextView (~> 1.1)
|
||||
- libPhoneNumber-iOS (~> 0.9.13)
|
||||
- MatrixKit/Core (= 0.13.2)
|
||||
- MatrixSDK (= 0.17.4)
|
||||
- MatrixKit/AppExtension (0.13.2):
|
||||
- MatrixKit/Core (= 0.13.3)
|
||||
- MatrixSDK (= 0.17.5)
|
||||
- MatrixKit/AppExtension (0.13.3):
|
||||
- Down (~> 0.9.3)
|
||||
- DTCoreText (~> 1.6.23)
|
||||
- DTCoreText/Extension
|
||||
- HPGrowingTextView (~> 1.1)
|
||||
- libPhoneNumber-iOS (~> 0.9.13)
|
||||
- MatrixSDK (= 0.17.4)
|
||||
- MatrixKit/Core (0.13.2):
|
||||
- MatrixSDK (= 0.17.5)
|
||||
- MatrixKit/Core (0.13.3):
|
||||
- Down (~> 0.9.3)
|
||||
- DTCoreText (~> 1.6.23)
|
||||
- HPGrowingTextView (~> 1.1)
|
||||
- libPhoneNumber-iOS (~> 0.9.13)
|
||||
- MatrixSDK (= 0.17.4)
|
||||
- MatrixSDK (0.17.4):
|
||||
- MatrixSDK/Core (= 0.17.4)
|
||||
- MatrixSDK/Core (0.17.4):
|
||||
- MatrixSDK (= 0.17.5)
|
||||
- MatrixSDK (0.17.5):
|
||||
- MatrixSDK/Core (= 0.17.5)
|
||||
- MatrixSDK/Core (0.17.5):
|
||||
- AFNetworking (~> 4.0.0)
|
||||
- GZIP (~> 1.3.0)
|
||||
- libbase58 (~> 0.1.4)
|
||||
- OLMKit (~> 3.1.0)
|
||||
- Realm (= 10.1.4)
|
||||
- MatrixSDK/JingleCallStack (0.17.4):
|
||||
- MatrixSDK/JingleCallStack (0.17.5):
|
||||
- JitsiMeetSDK (= 2.11.0)
|
||||
- MatrixSDK/Core
|
||||
- MatrixSDK/SwiftSupport (0.17.4):
|
||||
- MatrixSDK/Core
|
||||
- OLMKit (3.1.0):
|
||||
- OLMKit/olmc (= 3.1.0)
|
||||
- OLMKit/olmcpp (= 3.1.0)
|
||||
|
@ -129,11 +127,10 @@ DEPENDENCIES:
|
|||
- KeychainAccess (~> 4.2.1)
|
||||
- KTCenterFlowLayout (~> 1.3.1)
|
||||
- MatomoTracker (~> 7.2.2)
|
||||
- MatrixKit (= 0.13.2)
|
||||
- MatrixKit/AppExtension (= 0.13.2)
|
||||
- MatrixKit (= 0.13.3)
|
||||
- MatrixKit/AppExtension (= 0.13.3)
|
||||
- MatrixSDK
|
||||
- MatrixSDK/JingleCallStack
|
||||
- MatrixSDK/SwiftSupport
|
||||
- OLMKit
|
||||
- ReadMoreTextView (~> 3.0.1)
|
||||
- Reusable (~> 4.1)
|
||||
|
@ -202,8 +199,8 @@ SPEC CHECKSUMS:
|
|||
LoggerAPI: ad9c4a6f1e32f518fdb43a1347ac14d765ab5e3d
|
||||
Logging: beeb016c9c80cf77042d62e83495816847ef108b
|
||||
MatomoTracker: a59ec4da0f580be57bdc6baa708a71a86532a832
|
||||
MatrixKit: 411348d4690b414e18958a0437c13edc21054a18
|
||||
MatrixSDK: 39282219213aebf621326f6335073b5a2b1e9113
|
||||
MatrixKit: 86f5239fab112ab0d3714fd1f366916ebd4d2b25
|
||||
MatrixSDK: aadf483438804d9e93d5d46ad3e5e832b7bb8848
|
||||
OLMKit: 4ee0159d63feeb86d836fdcfefe418e163511639
|
||||
ReadMoreTextView: 19147adf93abce6d7271e14031a00303fe28720d
|
||||
Realm: 80f4fb2971ccb9adc27a47d0955ae8e533a7030b
|
||||
|
@ -215,6 +212,6 @@ SPEC CHECKSUMS:
|
|||
zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c
|
||||
ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb
|
||||
|
||||
PODFILE CHECKSUM: 5f40ae970fc6a939c548fedf78849358a895c315
|
||||
PODFILE CHECKSUM: 22fcc5047435925034265c61cd821507736bf492
|
||||
|
||||
COCOAPODS: 1.10.0
|
||||
|
|
|
@ -895,7 +895,6 @@
|
|||
EC85D752247C0F52002C44C9 /* UNUserNotificationCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC85D750247C0E8F002C44C9 /* UNUserNotificationCenter.swift */; };
|
||||
EC85D754247C0F5B002C44C9 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC85D753247C0F5B002C44C9 /* Constants.swift */; };
|
||||
EC85D755247C0F84002C44C9 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC85D753247C0F5B002C44C9 /* Constants.swift */; };
|
||||
EC85D757247E700F002C44C9 /* NSEMemoryStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC85D756247E700F002C44C9 /* NSEMemoryStore.swift */; };
|
||||
EC9A3EC524E1616900A8CFAE /* PushNotificationStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC9A3EC424E1616900A8CFAE /* PushNotificationStore.swift */; };
|
||||
EC9A3EC624E1632C00A8CFAE /* PushNotificationStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC9A3EC424E1616900A8CFAE /* PushNotificationStore.swift */; };
|
||||
EC9A3EC724E1634100A8CFAE /* KeyValueStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC1CA87124C823E700DE9EBF /* KeyValueStore.swift */; };
|
||||
|
@ -2137,7 +2136,6 @@
|
|||
EC85D74E2477E614002C44C9 /* RiotNSE.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = RiotNSE.entitlements; sourceTree = "<group>"; };
|
||||
EC85D750247C0E8F002C44C9 /* UNUserNotificationCenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UNUserNotificationCenter.swift; sourceTree = "<group>"; };
|
||||
EC85D753247C0F5B002C44C9 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
|
||||
EC85D756247E700F002C44C9 /* NSEMemoryStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSEMemoryStore.swift; sourceTree = "<group>"; };
|
||||
EC9A3EC424E1616900A8CFAE /* PushNotificationStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PushNotificationStore.swift; sourceTree = "<group>"; };
|
||||
ECAE7AE424EC0E01002FA813 /* TableViewSections.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableViewSections.swift; sourceTree = "<group>"; };
|
||||
ECAE7AE624EC15F7002FA813 /* Section.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Section.swift; sourceTree = "<group>"; };
|
||||
|
@ -5187,7 +5185,6 @@
|
|||
children = (
|
||||
EC85D74E2477E614002C44C9 /* RiotNSE.entitlements */,
|
||||
EC85D7452477E5F7002C44C9 /* NotificationService.swift */,
|
||||
EC85D756247E700F002C44C9 /* NSEMemoryStore.swift */,
|
||||
EC85D7472477E5F7002C44C9 /* Info.plist */,
|
||||
EC1CA8D924D811B400DE9EBF /* NSE-Common.xcconfig */,
|
||||
EC1CA8BC24D1B4CF00DE9EBF /* NSE-Debug.xcconfig */,
|
||||
|
@ -6213,7 +6210,6 @@
|
|||
files = (
|
||||
EC85D74F2477E8EB002C44C9 /* RiotSettings.swift in Sources */,
|
||||
32FD756824D2AD5100BA7B37 /* BuildSettings.swift in Sources */,
|
||||
EC85D757247E700F002C44C9 /* NSEMemoryStore.swift in Sources */,
|
||||
EC2B4EF224A1EF34005EB739 /* DataProtectionHelper.swift in Sources */,
|
||||
EC85D7462477E5F7002C44C9 /* NotificationService.swift in Sources */,
|
||||
32FD755424D074C700BA7B37 /* CommonConfiguration.swift in Sources */,
|
||||
|
@ -7351,7 +7347,7 @@
|
|||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 1.1.2;
|
||||
CURRENT_PROJECT_VERSION = 1.1.3;
|
||||
DEFINES_MODULE = YES;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
|
@ -7371,7 +7367,7 @@
|
|||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
MARKETING_VERSION = 1.1.2;
|
||||
MARKETING_VERSION = 1.1.3;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
|
@ -7410,7 +7406,7 @@
|
|||
CODE_SIGN_IDENTITY = "iPhone Distribution";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
CURRENT_PROJECT_VERSION = 1.1.2;
|
||||
CURRENT_PROJECT_VERSION = 1.1.3;
|
||||
DEFINES_MODULE = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
|
@ -7423,7 +7419,7 @@
|
|||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
MARKETING_VERSION = 1.1.2;
|
||||
MARKETING_VERSION = 1.1.3;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
"auth_register" = "Register";
|
||||
"auth_submit" = "Submit";
|
||||
"auth_skip" = "Skip";
|
||||
"auth_login_single_sign_on" = "Sign in with single sign-on";
|
||||
"auth_login_single_sign_on" = "Sign In";
|
||||
"auth_send_reset_email" = "Send Reset Email";
|
||||
"auth_return_to_login" = "Return to login screen";
|
||||
"auth_user_id_placeholder" = "Email or user name";
|
||||
|
|
|
@ -114,7 +114,7 @@ internal enum VectorL10n {
|
|||
internal static var authLogin: String {
|
||||
return VectorL10n.tr("Vector", "auth_login")
|
||||
}
|
||||
/// Sign in with single sign-on
|
||||
/// Sign In
|
||||
internal static var authLoginSingleSignOn: String {
|
||||
return VectorL10n.tr("Vector", "auth_login_single_sign_on")
|
||||
}
|
||||
|
|
|
@ -617,8 +617,6 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
|||
}
|
||||
|
||||
_isAppForeground = YES;
|
||||
|
||||
[self configurePinCodeScreenFor:application createIfRequired:NO];
|
||||
}
|
||||
|
||||
- (void)applicationDidBecomeActive:(UIApplication *)application
|
||||
|
@ -1109,9 +1107,6 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
|||
|
||||
- (void)pushNotificationService:(PushNotificationService *)pushNotificationService shouldNavigateToRoomWithId:(NSString *)roomId
|
||||
{
|
||||
[MXSDKOptions.sharedInstance.profiler startMeasuringTaskWithName:AnalyticsNoficationsTimeToDisplayContent
|
||||
category:AnalyticsNoficationsCategory];
|
||||
|
||||
_lastNavigatedRoomIdFromPush = roomId;
|
||||
[self navigateToRoomById:roomId];
|
||||
}
|
||||
|
|
|
@ -294,6 +294,9 @@
|
|||
// Listen to the event sent state changes
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(eventDidChangeSentState:) name:kMXEventDidChangeSentStateNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(eventDidChangeIdentifier:) name:kMXEventDidChangeIdentifierNotification object:nil];
|
||||
|
||||
// Show / hide actions button in document preview according BuildSettings
|
||||
self.allowActionsInDocumentPreview = BuildSettings.messageDetailsAllowShare;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
|
|
|
@ -1,133 +0,0 @@
|
|||
/*
|
||||
Copyright 2020 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 Foundation
|
||||
import MatrixSDK
|
||||
|
||||
// error domain
|
||||
let NSEMemoryStoreErrorDomain: String = "NSEMemoryStoreErrorDomain"
|
||||
|
||||
// error codes
|
||||
enum NSEMemoryStoreErrorCode: Int {
|
||||
case userIDMissing = 1001 // User ID is missing in credentials
|
||||
}
|
||||
|
||||
/// Fake memory store implementation. Uses some real values from an MXFileStore instance.
|
||||
class NSEMemoryStore: MXMemoryStore {
|
||||
|
||||
// In-memory value for eventStreamToken. Will be used as eventStreamToken if provided.
|
||||
private var lastStoredEventStreamToken: String?
|
||||
private var credentials: MXCredentials
|
||||
// real store
|
||||
private var fileStore: MXFileStore!
|
||||
private var myUser: MXUser?
|
||||
|
||||
init(withCredentials credentials: MXCredentials) {
|
||||
self.credentials = credentials
|
||||
if fileStore == nil {
|
||||
fileStore = MXFileStore(credentials: credentials)
|
||||
// load real eventStreamToken
|
||||
fileStore.loadMetaData()
|
||||
}
|
||||
}
|
||||
|
||||
override func open(with credentials: MXCredentials, onComplete: (() -> Void)?, failure: ((Error?) -> Void)? = nil) {
|
||||
super.open(with: credentials, onComplete: {
|
||||
guard let userId = credentials.userId else {
|
||||
failure?(NSError(domain: NSEMemoryStoreErrorDomain,
|
||||
code: NSEMemoryStoreErrorCode.userIDMissing.rawValue,
|
||||
userInfo: nil))
|
||||
return
|
||||
}
|
||||
// load session user before calling onComplete
|
||||
self.fileStore.asyncUsers(withUserIds: [userId], success: { (users) in
|
||||
if let user = users.first {
|
||||
self.myUser = user
|
||||
}
|
||||
onComplete?()
|
||||
}, failure: failure)
|
||||
}, failure: failure)
|
||||
}
|
||||
|
||||
// Return real eventStreamToken, to be able to launch a meaningful background sync
|
||||
override var eventStreamToken: String? {
|
||||
get {
|
||||
// if more up-to-date token exists, use it
|
||||
if let token = lastStoredEventStreamToken {
|
||||
return token
|
||||
}
|
||||
return fileStore.eventStreamToken
|
||||
} set {
|
||||
// store new token values in memory, and return these values in future reads
|
||||
lastStoredEventStreamToken = newValue
|
||||
}
|
||||
}
|
||||
|
||||
// Return real userAccountData, to be able to use push rules
|
||||
override var userAccountData: [AnyHashable : Any]? {
|
||||
get {
|
||||
return fileStore.userAccountData
|
||||
} set {
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
|
||||
// This store should act like as a permanent one
|
||||
override var isPermanent: Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Some mandatory methods to implement to be permanent
|
||||
override func storeState(forRoom roomId: String, stateEvents: [MXEvent]) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
// Fetch real room state
|
||||
override func state(ofRoom roomId: String, success: @escaping ([MXEvent]) -> Void, failure: ((Error) -> Void)? = nil) {
|
||||
fileStore.state(ofRoom: roomId, success: success, failure: failure)
|
||||
}
|
||||
|
||||
// Fetch real soom summary
|
||||
override func summary(ofRoom roomId: String) -> MXRoomSummary? {
|
||||
return fileStore.summary(ofRoom: roomId)
|
||||
}
|
||||
|
||||
// Fetch real room account data
|
||||
override func accountData(ofRoom roomId: String) -> MXRoomAccountData? {
|
||||
return fileStore.accountData(ofRoom: roomId)
|
||||
}
|
||||
|
||||
// Override and return a user to be stored on session.myUser
|
||||
override func user(withUserId userId: String) -> MXUser? {
|
||||
if userId == credentials.userId, let myUser = myUser {
|
||||
// if asking for session user and myUser is set, return that
|
||||
return myUser
|
||||
}
|
||||
return MXUser(userId: userId)
|
||||
}
|
||||
|
||||
override var syncFilterId: String? {
|
||||
get {
|
||||
let filter = MXFilterJSONModel()
|
||||
filter.room = MXRoomFilter()
|
||||
filter.room.rooms = []
|
||||
return filter.jsonString()
|
||||
} set {
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -21,21 +21,21 @@ import MatrixSDK
|
|||
class NotificationService: UNNotificationServiceExtension {
|
||||
|
||||
/// Content handlers. Keys are eventId's
|
||||
var contentHandlers: [String: ((UNNotificationContent) -> Void)] = [:]
|
||||
private var contentHandlers: [String: ((UNNotificationContent) -> Void)] = [:]
|
||||
|
||||
private var userAccount: MXKAccount?
|
||||
|
||||
/// Best attempt contents. Will be updated incrementally, if something fails during the process, this best attempt content will be showed as notification. Keys are eventId's
|
||||
var bestAttemptContents: [String: UNMutableNotificationContent] = [:]
|
||||
private var bestAttemptContents: [String: UNMutableNotificationContent] = [:]
|
||||
|
||||
/// Cached events. Keys are eventId's
|
||||
var cachedEvents: [String: MXEvent] = [:]
|
||||
static var mxSession: MXSession?
|
||||
var showDecryptedContentInNotifications: Bool {
|
||||
private static var backgroundSyncService: MXBackgroundSyncService!
|
||||
private var showDecryptedContentInNotifications: Bool {
|
||||
return RiotSettings.shared.showDecryptedContentInNotifications
|
||||
}
|
||||
lazy var configuration: Configurable = {
|
||||
private lazy var configuration: Configurable = {
|
||||
return CommonConfiguration()
|
||||
}()
|
||||
static var isLoggerInitialized: Bool = false
|
||||
private static var isLoggerInitialized: Bool = false
|
||||
private lazy var pushGatewayRestClient: MXPushGatewayRestClient = {
|
||||
let url = URL(string: BuildSettings.serverConfigSygnalAPIUrlString)!
|
||||
return MXPushGatewayRestClient(pushGateway: url.scheme! + "://" + url.host!, andOnUnrecognizedCertificateBlock: nil)
|
||||
|
@ -110,25 +110,13 @@ class NotificationService: UNNotificationServiceExtension {
|
|||
}
|
||||
|
||||
func setup(withRoomId roomId: String, eventId: String, completion: @escaping () -> Void) {
|
||||
if let userAccount = MXKAccountManager.shared()?.activeAccounts.first {
|
||||
if NotificationService.mxSession == nil {
|
||||
let store = NSEMemoryStore(withCredentials: userAccount.mxCredentials)
|
||||
NotificationService.mxSession = MXSession(matrixRestClient: MXRestClient(credentials: userAccount.mxCredentials, unrecognizedCertificateHandler: nil))
|
||||
NotificationService.mxSession?.setStore(store, completion: { (response) in
|
||||
switch response {
|
||||
case .success:
|
||||
completion()
|
||||
break
|
||||
case .failure(let error):
|
||||
NSLog("[NotificationService] setup: MXSession.setStore method returned error: \(String(describing: error))")
|
||||
self.fallbackToBestAttemptContent(forEventId: eventId)
|
||||
break
|
||||
}
|
||||
})
|
||||
} else {
|
||||
NSLog("[NotificationService] Instance: Reusing session")
|
||||
completion()
|
||||
MXKAccountManager.shared()?.forceReloadAccounts()
|
||||
self.userAccount = MXKAccountManager.shared()?.activeAccounts.first
|
||||
if let userAccount = userAccount {
|
||||
if NotificationService.backgroundSyncService == nil {
|
||||
NotificationService.backgroundSyncService = MXBackgroundSyncService(withCredentials: userAccount.mxCredentials)
|
||||
}
|
||||
completion()
|
||||
} else {
|
||||
NSLog("[NotificationService] setup: No active accounts")
|
||||
fallbackToBestAttemptContent(forEventId: eventId)
|
||||
|
@ -144,10 +132,9 @@ class NotificationService: UNNotificationServiceExtension {
|
|||
NSLog("[NotificationService] preprocessPayload: Do not preprocess because app protection is set")
|
||||
return
|
||||
}
|
||||
guard let session = NotificationService.mxSession else { return }
|
||||
guard let roomDisplayName = session.store.summary?(ofRoom: roomId)?.displayname else { return }
|
||||
let isDirect = session.directUserId(inRoom: roomId) != nil
|
||||
if isDirect {
|
||||
guard let roomSummary = NotificationService.backgroundSyncService.roomSummary(forRoomId: roomId) else { return }
|
||||
guard let roomDisplayName = roomSummary.displayname else { return }
|
||||
if roomSummary.isDirect == true {
|
||||
bestAttemptContents[eventId]?.body = NSString.localizedUserNotificationString(forKey: "MESSAGE_FROM_X", arguments: [roomDisplayName as Any])
|
||||
} else {
|
||||
bestAttemptContents[eventId]?.body = NSString.localizedUserNotificationString(forKey: "MESSAGE_IN_X", arguments: [roomDisplayName as Any])
|
||||
|
@ -155,133 +142,29 @@ class NotificationService: UNNotificationServiceExtension {
|
|||
}
|
||||
|
||||
func fetchEvent(withEventId eventId: String, roomId: String, allowSync: Bool = true) {
|
||||
guard let mxSession = NotificationService.mxSession else {
|
||||
// there is something wrong, do not change the content
|
||||
NSLog("[NotificationService] fetchEvent: Either originalContent or mxSession is missing.")
|
||||
fallbackToBestAttemptContent(forEventId: eventId)
|
||||
return
|
||||
}
|
||||
NSLog("[NotificationService] fetchEvent")
|
||||
|
||||
/// Inline function to handle decryption failure
|
||||
func handleDecryptionFailure() {
|
||||
if allowSync {
|
||||
NSLog("[NotificationService] fetchEvent: Launch a background sync.")
|
||||
self.launchBackgroundSync(forEventId: eventId, roomId: roomId)
|
||||
} else {
|
||||
NSLog("[NotificationService] fetchEvent: Do not sync anymore.")
|
||||
self.fallbackToBestAttemptContent(forEventId: eventId)
|
||||
}
|
||||
}
|
||||
|
||||
/// Inline function to handle encryption for event, either from cache or from the backend
|
||||
/// - Parameter event: The event to be handled
|
||||
func handleEncryption(forEvent event: MXEvent) {
|
||||
if !event.isEncrypted {
|
||||
// not encrypted, go on processing
|
||||
NSLog("[NotificationService] fetchEvent: Event not encrypted.")
|
||||
self.processEvent(event)
|
||||
return
|
||||
}
|
||||
|
||||
// encrypted
|
||||
if event.clear != nil {
|
||||
// already decrypted
|
||||
NSLog("[NotificationService] fetchEvent: Event already decrypted.")
|
||||
self.processEvent(event)
|
||||
return
|
||||
}
|
||||
|
||||
// should decrypt it first
|
||||
if mxSession.crypto.hasKeys(toDecryptEvent: event) {
|
||||
// we have keys to decrypt the event
|
||||
NSLog("[NotificationService] fetchEvent: Event needs to be decrpyted, and we have the keys to decrypt it.")
|
||||
if mxSession.decryptEvent(event, inTimeline: nil) {
|
||||
// decryption succeeded
|
||||
NSLog("[NotificationService] fetchEvent: Event decrypted successfully.")
|
||||
self.processEvent(event)
|
||||
} else {
|
||||
// decryption failed
|
||||
NSLog("[NotificationService] fetchEvent: Decryption failed even crypto claimed it has the keys.")
|
||||
handleDecryptionFailure()
|
||||
}
|
||||
} else {
|
||||
// we don't have keys to decrypt the event
|
||||
NSLog("[NotificationService] fetchEvent: Event needs to be decrpyted, but we don't have the keys to decrypt it.")
|
||||
handleDecryptionFailure()
|
||||
}
|
||||
}
|
||||
|
||||
// check if we've fetched the event before
|
||||
if let cachedEvent = self.cachedEvents[eventId] {
|
||||
// use cached event
|
||||
handleEncryption(forEvent: cachedEvent)
|
||||
} else {
|
||||
// attempt to fetch the event
|
||||
mxSession.event(withEventId: eventId, inRoom: roomId, success: { [weak self] (event) in
|
||||
guard let self = self else {
|
||||
NSLog("[NotificationService] fetchEvent: MXSession.event method returned too late successfully.")
|
||||
return
|
||||
}
|
||||
|
||||
guard let event = event else {
|
||||
NSLog("[NotificationService] fetchEvent: MXSession.event method returned successfully with no event.")
|
||||
self.fallbackToBestAttemptContent(forEventId: eventId)
|
||||
return
|
||||
}
|
||||
|
||||
// cache this event
|
||||
self.cachedEvents[eventId] = event
|
||||
|
||||
// handle encryption for this event
|
||||
handleEncryption(forEvent: event)
|
||||
}) { [weak self] (error) in
|
||||
guard let self = self else {
|
||||
NSLog("[NotificationService] fetchEvent: MXSession.event method returned too late with error: \(String(describing: error))")
|
||||
return
|
||||
}
|
||||
NSLog("[NotificationService] fetchEvent: MXSession.event method returned error: \(String(describing: error))")
|
||||
self.fallbackToBestAttemptContent(forEventId: eventId)
|
||||
}
|
||||
}
|
||||
NotificationService.backgroundSyncService.event(withEventId: eventId,
|
||||
inRoom: roomId,
|
||||
completion: { (response) in
|
||||
switch response {
|
||||
case .success(let event):
|
||||
NSLog("[NotificationService] fetchEvent: Event fetched successfully")
|
||||
self.processEvent(event)
|
||||
case .failure(let error):
|
||||
NSLog("[NotificationService] fetchEvent: error: \(error)")
|
||||
self.fallbackToBestAttemptContent(forEventId: eventId)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func launchBackgroundSync(forEventId eventId: String, roomId: String) {
|
||||
guard let mxSession = NotificationService.mxSession else {
|
||||
NSLog("[NotificationService] launchBackgroundSync: mxSession is missing.")
|
||||
self.fallbackToBestAttemptContent(forEventId: eventId)
|
||||
return
|
||||
}
|
||||
|
||||
// launch an initial background sync
|
||||
mxSession.backgroundSync(withTimeout: 20, ignoreSessionState: true) { [weak self] (response) in
|
||||
switch response {
|
||||
case .success:
|
||||
guard let self = self else {
|
||||
NSLog("[NotificationService] launchBackgroundSync: MXSession.initialBackgroundSync returned too late successfully")
|
||||
return
|
||||
}
|
||||
// do not allow to sync anymore
|
||||
self.fetchEvent(withEventId: eventId, roomId: roomId, allowSync: false)
|
||||
break
|
||||
case .failure(let error):
|
||||
guard let self = self else {
|
||||
NSLog("[NotificationService] launchBackgroundSync: MXSession.initialBackgroundSync returned too late with error: \(String(describing: error))")
|
||||
return
|
||||
}
|
||||
NSLog("[NotificationService] launchBackgroundSync: MXSession.initialBackgroundSync returned with error: \(String(describing: error))")
|
||||
self.fallbackToBestAttemptContent(forEventId: eventId)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func processEvent(_ event: MXEvent) {
|
||||
guard let content = bestAttemptContents[event.eventId], let mxSession = NotificationService.mxSession else {
|
||||
private func processEvent(_ event: MXEvent) {
|
||||
guard let content = bestAttemptContents[event.eventId], let userAccount = userAccount else {
|
||||
self.fallbackToBestAttemptContent(forEventId: event.eventId)
|
||||
return
|
||||
}
|
||||
|
||||
self.notificationContent(forEvent: event, inSession: mxSession) { (notificationContent) in
|
||||
self.notificationContent(forEvent: event, forAccount: userAccount) { (notificationContent) in
|
||||
var isUnwantedNotification = false
|
||||
|
||||
// Modify the notification content here...
|
||||
|
@ -301,10 +184,13 @@ class NotificationService: UNNotificationServiceExtension {
|
|||
|
||||
NSLog("[NotificationService] processEvent: Calling content handler for: \(String(describing: event.eventId)), isUnwanted: \(isUnwantedNotification)")
|
||||
self.contentHandlers[event.eventId]?(content)
|
||||
// clear maps
|
||||
self.contentHandlers.removeValue(forKey: event.eventId)
|
||||
self.bestAttemptContents.removeValue(forKey: event.eventId)
|
||||
}
|
||||
}
|
||||
|
||||
func fallbackToBestAttemptContent(forEventId eventId: String) {
|
||||
private func fallbackToBestAttemptContent(forEventId eventId: String) {
|
||||
NSLog("[NotificationService] fallbackToBestAttemptContent: method called.")
|
||||
|
||||
guard let content = bestAttemptContents[eventId] else {
|
||||
|
@ -314,190 +200,163 @@ class NotificationService: UNNotificationServiceExtension {
|
|||
|
||||
// call contentHandler
|
||||
contentHandlers[eventId]?(content)
|
||||
// clear maps
|
||||
contentHandlers.removeValue(forKey: eventId)
|
||||
bestAttemptContents.removeValue(forKey: eventId)
|
||||
}
|
||||
|
||||
func notificationContent(forEvent event: MXEvent, inSession session: MXSession, onComplete: @escaping (UNNotificationContent?) -> Void) {
|
||||
private func notificationContent(forEvent event: MXEvent, forAccount account: MXKAccount, onComplete: @escaping (UNNotificationContent?) -> Void) {
|
||||
guard let content = event.content, content.count > 0 else {
|
||||
NSLog("[NotificationService] notificationContentForEvent: empty event content")
|
||||
onComplete(nil)
|
||||
return
|
||||
}
|
||||
guard let room = MXRoom.load(from: session.store, withRoomId: event.roomId, matrixSession: session) as? MXRoom else {
|
||||
NSLog("[NotificationService] notificationContentForEvent: Unknown room")
|
||||
onComplete(nil)
|
||||
return
|
||||
}
|
||||
|
||||
let roomId = event.roomId!
|
||||
let isRoomMentionsOnly = NotificationService.backgroundSyncService.isRoomMentionsOnly(roomId)
|
||||
let roomSummary = NotificationService.backgroundSyncService.roomSummary(forRoomId: roomId)
|
||||
|
||||
NSLog("[NotificationService] notificationContentForEvent: Attempt to fetch the room state")
|
||||
room.state { (roomState) in
|
||||
guard let roomState = roomState else {
|
||||
NSLog("[NotificationService] notificationContentForEvent: Could not fetch the room state")
|
||||
onComplete(nil)
|
||||
return
|
||||
}
|
||||
|
||||
var notificationTitle: String?
|
||||
var notificationBody: String?
|
||||
|
||||
var threadIdentifier = room.roomId
|
||||
let eventSenderName = roomState.members.memberName(event.sender)
|
||||
let currentUserId = session.credentials.userId
|
||||
|
||||
let pushRule = session.notificationCenter.rule(matching: event, roomState: roomState)
|
||||
|
||||
switch event.eventType {
|
||||
case .callInvite:
|
||||
let offer = event.content["offer"] as? [AnyHashable: Any]
|
||||
let sdp = offer?["sdp"] as? String
|
||||
let isVideoCall = sdp?.contains("m=video") ?? false
|
||||
|
||||
NotificationService.backgroundSyncService.roomState(forRoomId: roomId, completion: { (response) in
|
||||
switch response {
|
||||
case .success(let roomState):
|
||||
var notificationTitle: String?
|
||||
var notificationBody: String?
|
||||
|
||||
if isVideoCall {
|
||||
notificationBody = NSString.localizedUserNotificationString(forKey: "VIDEO_CALL_FROM_USER", arguments: [eventSenderName as Any])
|
||||
} else {
|
||||
notificationBody = NSString.localizedUserNotificationString(forKey: "VOICE_CALL_FROM_USER", arguments: [eventSenderName as Any])
|
||||
}
|
||||
var threadIdentifier: String? = roomId
|
||||
let eventSenderName = roomState.members.memberName(event.sender)
|
||||
let currentUserId = account.mxCredentials.userId
|
||||
let roomDisplayName = roomSummary?.displayname
|
||||
let pushRule = NotificationService.backgroundSyncService.pushRule(matching: event, roomState: roomState)
|
||||
|
||||
// call notifications should stand out from normal messages, so we don't stack them
|
||||
threadIdentifier = nil
|
||||
self.sendVoipPush(forEvent: event)
|
||||
case .roomMessage, .roomEncrypted:
|
||||
if room.isMentionsOnly {
|
||||
// A local notification will be displayed only for highlighted notification.
|
||||
var isHighlighted = false
|
||||
switch event.eventType {
|
||||
case .callInvite:
|
||||
let offer = event.content["offer"] as? [AnyHashable: Any]
|
||||
let sdp = offer?["sdp"] as? String
|
||||
let isVideoCall = sdp?.contains("m=video") ?? false
|
||||
|
||||
// Check whether is there an highlight tweak on it
|
||||
for ruleAction in pushRule?.actions ?? [] {
|
||||
guard let action = ruleAction as? MXPushRuleAction else { continue }
|
||||
guard action.actionType == MXPushRuleActionTypeSetTweak else { continue }
|
||||
guard action.parameters["set_tweak"] as? String == "highlight" else { continue }
|
||||
// Check the highlight tweak "value"
|
||||
// If not present, highlight. Else check its value before highlighting
|
||||
if nil == action.parameters["value"] || true == (action.parameters["value"] as? Bool) {
|
||||
isHighlighted = true
|
||||
break
|
||||
if isVideoCall {
|
||||
notificationBody = NSString.localizedUserNotificationString(forKey: "VIDEO_CALL_FROM_USER", arguments: [eventSenderName as Any])
|
||||
} else {
|
||||
notificationBody = NSString.localizedUserNotificationString(forKey: "VOICE_CALL_FROM_USER", arguments: [eventSenderName as Any])
|
||||
}
|
||||
|
||||
// call notifications should stand out from normal messages, so we don't stack them
|
||||
threadIdentifier = nil
|
||||
self.sendVoipPush(forEvent: event)
|
||||
case .roomMessage, .roomEncrypted:
|
||||
if isRoomMentionsOnly {
|
||||
// A local notification will be displayed only for highlighted notification.
|
||||
var isHighlighted = false
|
||||
|
||||
// Check whether is there an highlight tweak on it
|
||||
for ruleAction in pushRule?.actions ?? [] {
|
||||
guard let action = ruleAction as? MXPushRuleAction else { continue }
|
||||
guard action.actionType == MXPushRuleActionTypeSetTweak else { continue }
|
||||
guard action.parameters["set_tweak"] as? String == "highlight" else { continue }
|
||||
// Check the highlight tweak "value"
|
||||
// If not present, highlight. Else check its value before highlighting
|
||||
if nil == action.parameters["value"] || true == (action.parameters["value"] as? Bool) {
|
||||
isHighlighted = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !isHighlighted {
|
||||
// Ignore this notif.
|
||||
NSLog("[NotificationService] notificationContentForEvent: Ignore non highlighted notif in mentions only room")
|
||||
onComplete(nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if !isHighlighted {
|
||||
// Ignore this notif.
|
||||
NSLog("[NotificationService] notificationContentForEvent: Ignore non highlighted notif in mentions only room")
|
||||
onComplete(nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var msgType = event.content["msgtype"] as? String
|
||||
let messageContent = event.content["body"] as? String
|
||||
|
||||
if event.isEncrypted && !self.showDecryptedContentInNotifications {
|
||||
// Hide the content
|
||||
msgType = nil
|
||||
}
|
||||
|
||||
let roomDisplayName = session.store.summary?(ofRoom: room.roomId)?.displayname
|
||||
let myUserId = session.myUser.userId
|
||||
let isIncomingEvent = event.sender != myUserId
|
||||
|
||||
// Display the room name only if it is different than the sender name
|
||||
if roomDisplayName != nil && roomDisplayName != eventSenderName {
|
||||
notificationTitle = NSString.localizedUserNotificationString(forKey: "MSG_FROM_USER_IN_ROOM_TITLE", arguments: [eventSenderName as Any, roomDisplayName as Any])
|
||||
var msgType = event.content["msgtype"] as? String
|
||||
let messageContent = event.content["body"] as? String
|
||||
|
||||
if msgType == kMXMessageTypeText {
|
||||
notificationBody = messageContent
|
||||
} else if msgType == kMXMessageTypeEmote {
|
||||
notificationBody = NSString.localizedUserNotificationString(forKey: "ACTION_FROM_USER", arguments: [eventSenderName as Any, messageContent as Any])
|
||||
} else if msgType == kMXMessageTypeImage {
|
||||
notificationBody = NSString.localizedUserNotificationString(forKey: "IMAGE_FROM_USER", arguments: [eventSenderName as Any, messageContent as Any])
|
||||
} else if room.isDirect && isIncomingEvent && msgType == kMXMessageTypeKeyVerificationRequest {
|
||||
session.crypto.keyVerificationManager.keyVerification(fromKeyVerificationEvent: event,
|
||||
success:{ (keyVerification) in
|
||||
guard let request = keyVerification.request, request.state == MXKeyVerificationRequestStatePending else {
|
||||
onComplete(nil)
|
||||
return
|
||||
}
|
||||
// TODO: Add accept and decline actions to notification
|
||||
let body = NSString.localizedUserNotificationString(forKey: "KEY_VERIFICATION_REQUEST_FROM_USER", arguments: [eventSenderName as Any])
|
||||
|
||||
let notificationContent = self.notificationContent(withTitle: notificationTitle,
|
||||
body: body,
|
||||
threadIdentifier: threadIdentifier,
|
||||
userId: currentUserId,
|
||||
event: event,
|
||||
pushRule: pushRule)
|
||||
|
||||
onComplete(notificationContent)
|
||||
}, failure:{ (error) in
|
||||
NSLog("[NotificationService] notificationContentForEvent: failed to fetch key verification with error: \(error)")
|
||||
onComplete(nil)
|
||||
})
|
||||
if event.isEncrypted && !self.showDecryptedContentInNotifications {
|
||||
// Hide the content
|
||||
msgType = nil
|
||||
}
|
||||
|
||||
// Display the room name only if it is different than the sender name
|
||||
if roomDisplayName != nil && roomDisplayName != eventSenderName {
|
||||
notificationTitle = NSString.localizedUserNotificationString(forKey: "MSG_FROM_USER_IN_ROOM_TITLE", arguments: [eventSenderName as Any, roomDisplayName as Any])
|
||||
|
||||
if msgType == kMXMessageTypeText {
|
||||
notificationBody = messageContent
|
||||
} else if msgType == kMXMessageTypeEmote {
|
||||
notificationBody = NSString.localizedUserNotificationString(forKey: "ACTION_FROM_USER", arguments: [eventSenderName as Any, messageContent as Any])
|
||||
} else if msgType == kMXMessageTypeImage {
|
||||
notificationBody = NSString.localizedUserNotificationString(forKey: "IMAGE_FROM_USER", arguments: [eventSenderName as Any, messageContent as Any])
|
||||
} else {
|
||||
// Encrypted messages falls here
|
||||
notificationBody = NSString.localizedUserNotificationString(forKey: "MESSAGE", arguments: [])
|
||||
}
|
||||
} else {
|
||||
// Encrypted messages falls here
|
||||
notificationBody = NSString.localizedUserNotificationString(forKey: "MESSAGE", arguments: [])
|
||||
notificationTitle = eventSenderName
|
||||
|
||||
switch msgType {
|
||||
case kMXMessageTypeText:
|
||||
notificationBody = messageContent
|
||||
break
|
||||
case kMXMessageTypeEmote:
|
||||
notificationBody = NSString.localizedUserNotificationString(forKey: "ACTION_FROM_USER", arguments: [eventSenderName as Any, messageContent as Any])
|
||||
break
|
||||
case kMXMessageTypeImage:
|
||||
notificationBody = NSString.localizedUserNotificationString(forKey: "IMAGE_FROM_USER", arguments: [eventSenderName as Any, messageContent as Any])
|
||||
break
|
||||
default:
|
||||
// Encrypted messages falls here
|
||||
notificationBody = NSString.localizedUserNotificationString(forKey: "MESSAGE", arguments: [])
|
||||
break
|
||||
}
|
||||
}
|
||||
break
|
||||
case .roomMember:
|
||||
if roomDisplayName != nil && roomDisplayName != eventSenderName {
|
||||
notificationBody = NSString.localizedUserNotificationString(forKey: "USER_INVITE_TO_NAMED_ROOM", arguments: [eventSenderName as Any, roomDisplayName as Any])
|
||||
} else {
|
||||
notificationBody = NSString.localizedUserNotificationString(forKey: "USER_INVITE_TO_CHAT", arguments: [eventSenderName as Any])
|
||||
}
|
||||
case .sticker:
|
||||
if roomDisplayName != nil && roomDisplayName != eventSenderName {
|
||||
notificationTitle = NSString.localizedUserNotificationString(forKey: "MSG_FROM_USER_IN_ROOM_TITLE", arguments: [eventSenderName as Any, roomDisplayName as Any])
|
||||
} else {
|
||||
notificationTitle = eventSenderName
|
||||
}
|
||||
} else {
|
||||
notificationTitle = eventSenderName
|
||||
|
||||
switch msgType {
|
||||
case kMXMessageTypeText:
|
||||
notificationBody = messageContent
|
||||
break
|
||||
case kMXMessageTypeEmote:
|
||||
notificationBody = NSString.localizedUserNotificationString(forKey: "ACTION_FROM_USER", arguments: [eventSenderName as Any, messageContent as Any])
|
||||
break
|
||||
case kMXMessageTypeImage:
|
||||
notificationBody = NSString.localizedUserNotificationString(forKey: "IMAGE_FROM_USER", arguments: [eventSenderName as Any, messageContent as Any])
|
||||
break
|
||||
default:
|
||||
// Encrypted messages falls here
|
||||
notificationBody = NSString.localizedUserNotificationString(forKey: "MESSAGE", arguments: [])
|
||||
break
|
||||
}
|
||||
}
|
||||
break
|
||||
case .roomMember:
|
||||
let roomDisplayName = room.summary.displayname
|
||||
|
||||
if roomDisplayName != nil && roomDisplayName != eventSenderName {
|
||||
notificationBody = NSString.localizedUserNotificationString(forKey: "USER_INVITE_TO_NAMED_ROOM", arguments: [eventSenderName as Any, roomDisplayName as Any])
|
||||
} else {
|
||||
notificationBody = NSString.localizedUserNotificationString(forKey: "USER_INVITE_TO_CHAT", arguments: [eventSenderName as Any])
|
||||
}
|
||||
case .sticker:
|
||||
let roomDisplayName = room.summary.displayname
|
||||
|
||||
if roomDisplayName != nil && roomDisplayName != eventSenderName {
|
||||
notificationTitle = NSString.localizedUserNotificationString(forKey: "MSG_FROM_USER_IN_ROOM_TITLE", arguments: [eventSenderName as Any, roomDisplayName as Any])
|
||||
} else {
|
||||
notificationTitle = eventSenderName
|
||||
notificationBody = NSString.localizedUserNotificationString(forKey: "STICKER_FROM_USER", arguments: [eventSenderName as Any])
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
notificationBody = NSString.localizedUserNotificationString(forKey: "STICKER_FROM_USER", arguments: [eventSenderName as Any])
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
if self.localAuthenticationService.isProtectionSet {
|
||||
NSLog("[NotificationService] notificationContentForEvent: Resetting title and body because app protection is set")
|
||||
notificationBody = NSString.localizedUserNotificationString(forKey: "MESSAGE_PROTECTED", arguments: [])
|
||||
notificationTitle = nil
|
||||
}
|
||||
|
||||
guard notificationBody != nil else {
|
||||
NSLog("[NotificationService] notificationContentForEvent: notificationBody is nil")
|
||||
if self.localAuthenticationService.isProtectionSet {
|
||||
NSLog("[NotificationService] notificationContentForEvent: Resetting title and body because app protection is set")
|
||||
notificationBody = NSString.localizedUserNotificationString(forKey: "MESSAGE_PROTECTED", arguments: [])
|
||||
notificationTitle = nil
|
||||
}
|
||||
|
||||
guard notificationBody != nil else {
|
||||
NSLog("[NotificationService] notificationContentForEvent: notificationBody is nil")
|
||||
onComplete(nil)
|
||||
return
|
||||
}
|
||||
|
||||
let notificationContent = self.notificationContent(withTitle: notificationTitle,
|
||||
body: notificationBody,
|
||||
threadIdentifier: threadIdentifier,
|
||||
userId: currentUserId,
|
||||
event: event,
|
||||
pushRule: pushRule)
|
||||
|
||||
NSLog("[NotificationService] notificationContentForEvent: Calling onComplete.")
|
||||
onComplete(notificationContent)
|
||||
case .failure(let error):
|
||||
NSLog("[NotificationService] notificationContentForEvent: error: \(error)")
|
||||
onComplete(nil)
|
||||
return
|
||||
}
|
||||
|
||||
let notificationContent = self.notificationContent(withTitle: notificationTitle,
|
||||
body: notificationBody,
|
||||
threadIdentifier: threadIdentifier,
|
||||
userId: currentUserId,
|
||||
event: event,
|
||||
pushRule: pushRule)
|
||||
|
||||
NSLog("[NotificationService] notificationContentForEvent: Calling onComplete.")
|
||||
onComplete(notificationContent)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func notificationContent(withTitle title: String?,
|
||||
|
@ -597,40 +456,3 @@ class NotificationService: UNNotificationServiceExtension {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
extension MXRoom {
|
||||
|
||||
func getRoomPushRule() -> MXPushRule? {
|
||||
guard let rules = self.mxSession.notificationCenter.rules.global.room else {
|
||||
return nil
|
||||
}
|
||||
|
||||
for rule in rules {
|
||||
guard let pushRule = rule as? MXPushRule else { continue }
|
||||
// the rule id is the room Id
|
||||
// it is the server trick to avoid duplicated rule on the same room.
|
||||
if pushRule.ruleId == self.roomId {
|
||||
return pushRule
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var isMentionsOnly: Bool {
|
||||
// Check push rules at room level
|
||||
guard let rule = self.getRoomPushRule() else {
|
||||
return false
|
||||
}
|
||||
|
||||
for ruleAction in rule.actions {
|
||||
guard let action = ruleAction as? MXPushRuleAction else { continue }
|
||||
if action.actionType == MXPushRuleActionTypeDontNotify {
|
||||
return rule.enabled
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue