diff --git a/Session.xcodeproj/project.pbxproj b/Session.xcodeproj/project.pbxproj index e6a50a7d4..985a383ac 100644 --- a/Session.xcodeproj/project.pbxproj +++ b/Session.xcodeproj/project.pbxproj @@ -3070,8 +3070,6 @@ children = ( C3C2A5B0255385C700C340D1 /* Meta */, FD17D79D27F40CAA00122BE0 /* Database */, - FD17D7DF27F67BC400122BE0 /* Models */, - FD17D7D027F5795300122BE0 /* Types */, FDC438AF27BB158500C60D73 /* Models */, C3C2A5CD255385F300C340D1 /* Utilities */, C3C2A5B9255385ED00C340D1 /* Configuration.swift */, @@ -3558,20 +3556,6 @@ path = Models; sourceTree = ""; }; - FD17D7D027F5795300122BE0 /* Types */ = { - isa = PBXGroup; - children = ( - ); - path = Types; - sourceTree = ""; - }; - FD17D7DF27F67BC400122BE0 /* Models */ = { - isa = PBXGroup; - children = ( - ); - path = Models; - sourceTree = ""; - }; FD17D7E827F6A1B800122BE0 /* LegacyDatabase */ = { isa = PBXGroup; children = ( @@ -6830,7 +6814,7 @@ CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CURRENT_PROJECT_VERSION = 357; + CURRENT_PROJECT_VERSION = 360; DEVELOPMENT_TEAM = SUQ8J2PCT7; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -6902,7 +6886,7 @@ CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CURRENT_PROJECT_VERSION = 357; + CURRENT_PROJECT_VERSION = 360; DEVELOPMENT_TEAM = SUQ8J2PCT7; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", diff --git a/Session/DMs/NewDMVC.swift b/Session/DMs/NewDMVC.swift index 8767c8263..b55fbb3df 100644 --- a/Session/DMs/NewDMVC.swift +++ b/Session/DMs/NewDMVC.swift @@ -134,30 +134,42 @@ final class NewDMVC : BaseVC, UIPageViewControllerDataSource, UIPageViewControll } fileprivate func startNewDMIfPossible(with onsNameOrPublicKey: String) { - if ECKeyPair.isValidHexEncodedPublicKey(candidate: onsNameOrPublicKey) { + let maybeSessionId: SessionId? = SessionId(from: onsNameOrPublicKey) + + if ECKeyPair.isValidHexEncodedPublicKey(candidate: onsNameOrPublicKey) && maybeSessionId?.prefix == .standard { startNewDM(with: onsNameOrPublicKey) - } else { - // This could be an ONS name - ModalActivityIndicatorViewController.present(fromViewController: navigationController!, canCancel: false) { [weak self] modalActivityIndicator in - SnodeAPI.getSessionID(for: onsNameOrPublicKey).done { sessionID in - modalActivityIndicator.dismiss { - self?.startNewDM(with: sessionID) - } - }.catch { error in - modalActivityIndicator.dismiss { - var messageOrNil: String? - if let error = error as? SnodeAPIError { - switch error { - case .decryptionFailed, .hashingFailed, .validationFailed: - messageOrNil = error.errorDescription - default: break - } + return + } + + // This could be an ONS name + ModalActivityIndicatorViewController.present(fromViewController: navigationController!, canCancel: false) { [weak self] modalActivityIndicator in + SnodeAPI.getSessionID(for: onsNameOrPublicKey).done { sessionID in + modalActivityIndicator.dismiss { + self?.startNewDM(with: sessionID) + } + }.catch { error in + modalActivityIndicator.dismiss { + var messageOrNil: String? + if let error = error as? SnodeAPIError { + switch error { + case .decryptionFailed, .hashingFailed, .validationFailed: + messageOrNil = error.errorDescription + default: break } - let message = messageOrNil ?? "Please check the Session ID or ONS name and try again" - let alert = UIAlertController(title: "Error", message: message, preferredStyle: .alert) - alert.addAction(UIAlertAction(title: NSLocalizedString("BUTTON_OK", comment: ""), style: .default, handler: nil)) - self?.presentAlert(alert) } + let message: String = { + if let messageOrNil: String = messageOrNil { + return messageOrNil + } + + return (maybeSessionId?.prefix == .blinded ? + "You can only send messages to Blinded IDs from within an Open Group" : + "Please check the Session ID or ONS name and try again" + ) + }() + let alert = UIAlertController(title: "Error", message: message, preferredStyle: .alert) + alert.addAction(UIAlertAction(title: "BUTTON_OK".localized(), style: .default, handler: nil)) + self?.presentAlert(alert) } } } diff --git a/Session/Meta/AppDelegate.swift b/Session/Meta/AppDelegate.swift index 84286342e..7067ea3db 100644 --- a/Session/Meta/AppDelegate.swift +++ b/Session/Meta/AppDelegate.swift @@ -114,6 +114,16 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD return true } + func applicationWillEnterForeground(_ application: UIApplication) { + /// **Note:** We _shouldn't_ need to call this here but for some reason the OS doesn't seems to + /// be calling the `userNotificationCenter(_:,didReceive:withCompletionHandler:)` + /// method when the device is locked while the app is in the foreground (or if the user returns to the + /// springboard without swapping to another app) - adding this here in addition to the one in + /// `appDidFinishLaunching` seems to fix this odd behaviour (even though it doesn't match + /// Apple's documentation on the matter) + UNUserNotificationCenter.current().delegate = self + } + func applicationDidEnterBackground(_ application: UIApplication) { DDLog.flushLog() @@ -149,7 +159,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD /// no longer always called before `applicationDidBecomeActive` we need to trigger the "clear notifications" logic /// within the `runNowOrWhenAppDidBecomeReady` callback and dispatch to the next run loop to ensure it runs after /// the notification has actually been handled - DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) { [weak self] in + DispatchQueue.main.async { [weak self] in self?.clearAllNotificationsAndRestoreBadgeCount() } } diff --git a/SessionMessagingKit/Jobs/Types/UpdateProfilePictureJob.swift b/SessionMessagingKit/Jobs/Types/UpdateProfilePictureJob.swift index 803ea34b9..260f150be 100644 --- a/SessionMessagingKit/Jobs/Types/UpdateProfilePictureJob.swift +++ b/SessionMessagingKit/Jobs/Types/UpdateProfilePictureJob.swift @@ -52,7 +52,14 @@ public enum UpdateProfilePictureJob: JobExecutor { image: nil, imageFilePath: profileFilePath, requiredSync: true, - success: { _, _ in success(job, false) }, + success: { _, _ in + // Need to call the 'success' closure asynchronously on the queue to prevent a reentrancy + // issue as it will write to the database and this closure is already called within + // another database write + queue.async { + success(job, false) + } + }, failure: { error in failure(job, error, false) } ) } diff --git a/SessionMessagingKit/Sending & Receiving/Pollers/OpenGroupPoller.swift b/SessionMessagingKit/Sending & Receiving/Pollers/OpenGroupPoller.swift index 72f5126b7..c46938844 100644 --- a/SessionMessagingKit/Sending & Receiving/Pollers/OpenGroupPoller.swift +++ b/SessionMessagingKit/Sending & Receiving/Pollers/OpenGroupPoller.swift @@ -194,7 +194,10 @@ extension OpenGroupAPI { case .roomPollInfo(let roomToken, _): guard let responseData: BatchSubResponse = endpointResponse.data as? BatchSubResponse, let responseBody: RoomPollInfo = responseData.body else { - SNLog("Open group polling failed due to invalid room info data.") + switch (endpointResponse.data as? BatchSubResponse)?.code { + case 404: SNLog("Open group polling failed to retrieve info for unknown room '\(roomToken)'.") + default: SNLog("Open group polling failed due to invalid room info data.") + } return } @@ -209,7 +212,10 @@ extension OpenGroupAPI { case .roomMessagesRecent(let roomToken), .roomMessagesBefore(let roomToken, _), .roomMessagesSince(let roomToken, _): guard let responseData: BatchSubResponse<[Failable]> = endpointResponse.data as? BatchSubResponse<[Failable]>, let responseBody: [Failable] = responseData.body else { - SNLog("Open group polling failed due to invalid messages data.") + switch (endpointResponse.data as? BatchSubResponse<[Failable]>)?.code { + case 404: SNLog("Open group polling failed to retrieve messages for unknown room '\(roomToken)'.") + default: SNLog("Open group polling failed due to invalid messages data.") + } return } let successfulMessages: [Message] = responseBody.compactMap { $0.value }