From c934415355f76280b2f437ceddf476bb3f60184a Mon Sep 17 00:00:00 2001 From: Morgan Pretty Date: Thu, 3 Nov 2022 17:26:10 +1100 Subject: [PATCH 1/3] General bug fixing Fixed an issue where the database could get suspended if the app is launched when the app is doing a background fetch Fixed an incorrectly localized string Fixed an issue where the author name on a message didn't have it's width constrained Fixed a bug where the conversation message list inset wasn't getting updated properly in some cases Tweaked some logic in the OpenGroupPoller when running from the background to try and close some of the odd cases --- Session.xcodeproj/project.pbxproj | 24 +++++++++---------- Session/Closed Groups/EditClosedGroupVC.swift | 2 +- Session/Conversations/ConversationVC.swift | 20 +++++++++------- .../Message Cells/VisibleMessageCell.swift | 2 ++ Session/Meta/AppDelegate.swift | 12 ++++++---- .../Pollers/OpenGroupPoller.swift | 14 ++++++++--- 6 files changed, 45 insertions(+), 29 deletions(-) diff --git a/Session.xcodeproj/project.pbxproj b/Session.xcodeproj/project.pbxproj index 642093112..ea42d0fbb 100644 --- a/Session.xcodeproj/project.pbxproj +++ b/Session.xcodeproj/project.pbxproj @@ -6032,7 +6032,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 385; + CURRENT_PROJECT_VERSION = 386; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = SUQ8J2PCT7; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; @@ -6057,7 +6057,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.2.1; + MARKETING_VERSION = 2.2.2; MTL_ENABLE_DEBUG_INFO = YES; PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger.ShareExtension"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -6105,7 +6105,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 385; + CURRENT_PROJECT_VERSION = 386; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = SUQ8J2PCT7; ENABLE_NS_ASSERTIONS = NO; @@ -6135,7 +6135,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.2.1; + MARKETING_VERSION = 2.2.2; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger.ShareExtension"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -6171,7 +6171,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 385; + CURRENT_PROJECT_VERSION = 386; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = SUQ8J2PCT7; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; @@ -6194,7 +6194,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.2.1; + MARKETING_VERSION = 2.2.2; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger.NotificationServiceExtension"; @@ -6245,7 +6245,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 385; + CURRENT_PROJECT_VERSION = 386; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = SUQ8J2PCT7; ENABLE_NS_ASSERTIONS = NO; @@ -6273,7 +6273,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.2.1; + MARKETING_VERSION = 2.2.2; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger.NotificationServiceExtension"; @@ -7173,7 +7173,7 @@ CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CURRENT_PROJECT_VERSION = 385; + CURRENT_PROJECT_VERSION = 386; DEVELOPMENT_TEAM = SUQ8J2PCT7; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -7212,7 +7212,7 @@ "$(SRCROOT)", ); LLVM_LTO = NO; - MARKETING_VERSION = 2.2.1; + MARKETING_VERSION = 2.2.2; OTHER_LDFLAGS = "$(inherited)"; OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\""; PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger"; @@ -7245,7 +7245,7 @@ CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CURRENT_PROJECT_VERSION = 385; + CURRENT_PROJECT_VERSION = 386; DEVELOPMENT_TEAM = SUQ8J2PCT7; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -7284,7 +7284,7 @@ "$(SRCROOT)", ); LLVM_LTO = NO; - MARKETING_VERSION = 2.2.1; + MARKETING_VERSION = 2.2.2; OTHER_LDFLAGS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger"; PRODUCT_NAME = Session; diff --git a/Session/Closed Groups/EditClosedGroupVC.swift b/Session/Closed Groups/EditClosedGroupVC.swift index 42c150a15..3c1ef4444 100644 --- a/Session/Closed Groups/EditClosedGroupVC.swift +++ b/Session/Closed Groups/EditClosedGroupVC.swift @@ -314,7 +314,7 @@ final class EditClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegat .trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) guard !updatedName.isEmpty else { - return showError(title: "vc_create_closed_group_group_name_missing_error".lowercased()) + return showError(title: "vc_create_closed_group_group_name_missing_error".localized()) } guard updatedName.count < 64 else { return showError(title: "vc_create_closed_group_group_name_too_long_error".localized()) diff --git a/Session/Conversations/ConversationVC.swift b/Session/Conversations/ConversationVC.swift index 8bb622e84..f342c6824 100644 --- a/Session/Conversations/ConversationVC.swift +++ b/Session/Conversations/ConversationVC.swift @@ -54,9 +54,10 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl var scrollDistanceToBottomBeforeUpdate: CGFloat? var baselineKeyboardHeight: CGFloat = 0 - /// This flag is true between `viewDidAppear` and `viewWillDisappear` and is used to prevent keyboard changes - /// from trying to animate (as the animations can cause staggering with push transitions) - var viewIsFocussed = false + /// These flags are true between `viewDid/Will Appear/Disappear` and is used to prevent keyboard changes + /// from trying to animate (as the animations can cause buggy transitions) + var viewIsDisappearing = false + var viewIsAppearing = false // Reaction var currentReactionListSheet: ReactionListSheet? @@ -399,6 +400,8 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl super.viewWillAppear(animated) startObservingChanges() + + viewIsAppearing = true } override func viewDidAppear(_ animated: Bool) { @@ -407,7 +410,7 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl // Flag that the initial layout has been completed (the flag blocks and unblocks a number // of different behaviours) didFinishInitialLayout = true - viewIsFocussed = true + viewIsAppearing = false if delayFirstResponder || isShowingSearchUI { delayFirstResponder = false @@ -426,7 +429,7 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) - viewIsFocussed = false + viewIsDisappearing = true // Don't set the draft or resign the first responder if we are replacing the thread (want the keyboard // to appear to remain focussed) @@ -442,6 +445,7 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl mediaCache.removeAllObjects() hasReloadedThreadDataAfterDisappearance = false + viewIsDisappearing = false } @objc func applicationDidBecomeActive(_ notification: Notification) { @@ -1067,7 +1071,7 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl // MARK: - Notifications @objc func handleKeyboardWillChangeFrameNotification(_ notification: Notification) { - guard viewIsFocussed || !didFinishInitialLayout else { return } + guard !viewIsDisappearing else { return } // Please refer to https://github.com/mapbox/mapbox-navigation-ios/issues/1600 // and https://stackoverflow.com/a/25260930 to better understand what we are @@ -1115,7 +1119,7 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl } // Perform the changes (don't animate if the initial layout hasn't been completed) - guard hasDoneLayout && didFinishInitialLayout else { + guard hasDoneLayout && didFinishInitialLayout && !viewIsAppearing else { UIView.performWithoutAnimation { changes() } @@ -1132,8 +1136,6 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl } @objc func handleKeyboardWillHideNotification(_ notification: Notification) { - guard viewIsFocussed else { return } - // Please refer to https://github.com/mapbox/mapbox-navigation-ios/issues/1600 // and https://stackoverflow.com/a/25260930 to better understand what we are // doing with the UIViewAnimationOptions diff --git a/Session/Conversations/Message Cells/VisibleMessageCell.swift b/Session/Conversations/Message Cells/VisibleMessageCell.swift index 84e3004ed..442a7e9aa 100644 --- a/Session/Conversations/Message Cells/VisibleMessageCell.swift +++ b/Session/Conversations/Message Cells/VisibleMessageCell.swift @@ -227,6 +227,7 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate { // Remaining constraints authorLabel.pin(.leading, to: .leading, of: snContentView, withInset: VisibleMessageCell.authorLabelInset) + authorLabel.pin(.trailing, to: .trailing, of: self, withInset: -Values.mediumSpacing) // Under bubble content addSubview(underBubbleStackView) @@ -1052,6 +1053,7 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate { ) -> TappableLabel { let isOutgoing: Bool = (cellViewModel.variant == .standardOutgoing) let result: TappableLabel = TappableLabel() + result.setContentCompressionResistancePriority(.required, for: .vertical) result.themeBackgroundColor = .clear result.isOpaque = false result.isUserInteractionEnabled = true diff --git a/Session/Meta/AppDelegate.swift b/Session/Meta/AppDelegate.swift index b2a97dfe4..12a5b6b83 100644 --- a/Session/Meta/AppDelegate.swift +++ b/Session/Meta/AppDelegate.swift @@ -214,8 +214,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD BackgroundPoller.isValid = false - // Suspend database - NotificationCenter.default.post(name: Database.suspendNotification, object: self) + if CurrentAppContext().isInBackground() { + // Suspend database + NotificationCenter.default.post(name: Database.suspendNotification, object: self) + } SNLog("Background poll failed due to manual timeout") completionHandler(.failed) @@ -233,8 +235,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD BackgroundPoller.isValid = false - // Suspend database - NotificationCenter.default.post(name: Database.suspendNotification, object: self) + if CurrentAppContext().isInBackground() { + // Suspend database + NotificationCenter.default.post(name: Database.suspendNotification, object: self) + } cancelTimer.invalidate() completionHandler(result) diff --git a/SessionMessagingKit/Sending & Receiving/Pollers/OpenGroupPoller.swift b/SessionMessagingKit/Sending & Receiving/Pollers/OpenGroupPoller.swift index 0166e026c..6bb65315d 100644 --- a/SessionMessagingKit/Sending & Receiving/Pollers/OpenGroupPoller.swift +++ b/SessionMessagingKit/Sending & Receiving/Pollers/OpenGroupPoller.swift @@ -84,7 +84,7 @@ extension OpenGroupAPI { let (promise, seal) = Promise.pending() promise.retainUntilComplete() - Threading.pollerQueue.async { + let pollingLogic: () -> Void = { dependencies.storage .read { db -> Promise<(Int64, PollResponse)> in let failureCount: Int64 = (try? OpenGroup @@ -150,7 +150,7 @@ extension OpenGroupAPI { error: error ) .done(on: OpenGroupAPI.workQueue) { [weak self] didHandleError in - if !didHandleError { + if !didHandleError && isBackgroundPollerValid() { // Increase the failure count let pollFailureCount: Int64 = Storage.shared .read { db in @@ -181,6 +181,14 @@ extension OpenGroupAPI { } } + // If this was run via the background poller then don't run on the pollerQueue + if calledFromBackgroundPoller { + pollingLogic() + } + else { + Threading.pollerQueue.async { pollingLogic() } + } + return promise } @@ -217,7 +225,7 @@ extension OpenGroupAPI { ) } .then(on: OpenGroupAPI.workQueue) { [weak self] _, responseBody -> Promise in - guard let strongSelf = self else { return Promise.value(()) } + guard let strongSelf = self, isBackgroundPollerValid() else { return Promise.value(()) } // Handle the updated capabilities and re-trigger the poll strongSelf.isPolling = false From f4d4e7d81092e363f4232a1cd70096ae42205ebf Mon Sep 17 00:00:00 2001 From: Morgan Pretty Date: Mon, 7 Nov 2022 10:18:59 +1100 Subject: [PATCH 2/3] Fixed an issue with blinding being switched on Fixed an issue where a user that was part of an open group before blinding was enabled wouldn't be able to access the group once blinding was switched on Updated the code to better support errors sent from SOGS as bencoded data --- .../Open Groups/OpenGroupAPI.swift | 11 ++- .../Models/OnionRequestAPIError.swift | 3 + SessionSnodeKit/OnionRequestAPI.swift | 98 +++++++++++-------- 3 files changed, 67 insertions(+), 45 deletions(-) diff --git a/SessionMessagingKit/Open Groups/OpenGroupAPI.swift b/SessionMessagingKit/Open Groups/OpenGroupAPI.swift index 4d32c974b..051ba7cc2 100644 --- a/SessionMessagingKit/Open Groups/OpenGroupAPI.swift +++ b/SessionMessagingKit/Open Groups/OpenGroupAPI.swift @@ -227,6 +227,7 @@ public enum OpenGroupAPI { public static func capabilities( _ db: Database, server: String, + forceBlinded: Bool = false, using dependencies: SMKDependencies = SMKDependencies() ) -> Promise<(OnionRequestResponseInfoType, Capabilities)> { return OpenGroupAPI @@ -236,6 +237,7 @@ public enum OpenGroupAPI { server: server, endpoint: .capabilities ), + forceBlinded: forceBlinded, using: dependencies ) .decoded(as: Capabilities.self, on: OpenGroupAPI.workQueue, using: dependencies) @@ -1260,6 +1262,7 @@ public enum OpenGroupAPI { messageBytes: Bytes, for serverName: String, fallbackSigningType signingType: SessionId.Prefix, + forceBlinded: Bool = false, using dependencies: SMKDependencies = SMKDependencies() ) -> (publicKey: String, signature: Bytes)? { guard @@ -1279,7 +1282,7 @@ public enum OpenGroupAPI { .defaulting(to: []) // If we have no capabilities or if the server supports blinded keys then sign using the blinded key - if capabilities.isEmpty || capabilities.contains(.blind) { + if forceBlinded || capabilities.isEmpty || capabilities.contains(.blind) { guard let blindedKeyPair: Box.KeyPair = dependencies.sodium.blindedKeyPair(serverPublicKey: serverPublicKey, edKeyPair: userEdKeyPair, genericHash: dependencies.genericHash) else { return nil } @@ -1326,6 +1329,7 @@ public enum OpenGroupAPI { request: URLRequest, for serverName: String, with serverPublicKey: String, + forceBlinded: Bool = false, using dependencies: SMKDependencies = SMKDependencies() ) -> URLRequest? { guard let url: URL = request.url else { return nil } @@ -1366,7 +1370,7 @@ public enum OpenGroupAPI { .appending(contentsOf: bodyHash ?? []) /// Sign the above message - guard let signResult: (publicKey: String, signature: Bytes) = sign(db, messageBytes: messageBytes, for: serverName, fallbackSigningType: .unblinded, using: dependencies) else { + guard let signResult: (publicKey: String, signature: Bytes) = sign(db, messageBytes: messageBytes, for: serverName, fallbackSigningType: .unblinded, forceBlinded: forceBlinded, using: dependencies) else { return nil } @@ -1386,6 +1390,7 @@ public enum OpenGroupAPI { private static func send( _ db: Database, request: Request, + forceBlinded: Bool = false, using dependencies: SMKDependencies = SMKDependencies() ) -> Promise<(OnionRequestResponseInfoType, Data?)> { let urlRequest: URLRequest @@ -1406,7 +1411,7 @@ public enum OpenGroupAPI { guard let publicKey: String = maybePublicKey else { return Promise(error: OpenGroupAPIError.noPublicKey) } // Attempt to sign the request with the new auth - guard let signedRequest: URLRequest = sign(db, request: urlRequest, for: request.server, with: publicKey, using: dependencies) else { + guard let signedRequest: URLRequest = sign(db, request: urlRequest, for: request.server, with: publicKey, forceBlinded: forceBlinded, using: dependencies) else { return Promise(error: OpenGroupAPIError.signingFailed) } diff --git a/SessionSnodeKit/Models/OnionRequestAPIError.swift b/SessionSnodeKit/Models/OnionRequestAPIError.swift index 3b75fe124..43e70da73 100644 --- a/SessionSnodeKit/Models/OnionRequestAPIError.swift +++ b/SessionSnodeKit/Models/OnionRequestAPIError.swift @@ -16,6 +16,9 @@ public enum OnionRequestAPIError: LocalizedError { switch self { case .httpRequestFailedAtDestination(let statusCode, let data, let destination): if statusCode == 429 { return "Rate limited." } + if let processedResponseBodyData: Data = OnionRequestAPI.process(bencodedData: data)?.body, let errorResponse: String = String(data: processedResponseBodyData, encoding: .utf8) { + return "HTTP request failed at destination (\(destination)) with status code: \(statusCode), error body: \(errorResponse)." + } if let errorResponse: String = String(data: data, encoding: .utf8) { return "HTTP request failed at destination (\(destination)) with status code: \(statusCode), error body: \(errorResponse)." } diff --git a/SessionSnodeKit/OnionRequestAPI.swift b/SessionSnodeKit/OnionRequestAPI.swift index 5a7e2fd45..d2a71b66c 100644 --- a/SessionSnodeKit/OnionRequestAPI.swift +++ b/SessionSnodeKit/OnionRequestAPI.swift @@ -700,72 +700,86 @@ public enum OnionRequestAPI: OnionRequestAPIType { do { let data: Data = try AESGCM.decrypt(responseData, with: destinationSymmetricKey) - // The data will be in the form of `l123:jsone` or `l123:json456:bodye` so we need to break the data into - // parts to properly process it - guard let responseString: String = String(data: data, encoding: .ascii), responseString.starts(with: "l") else { - return seal.reject(HTTP.Error.invalidResponse) - } - - let stringParts: [String.SubSequence] = responseString.split(separator: ":") - - guard stringParts.count > 1, let infoLength: Int = Int(stringParts[0].suffix(from: stringParts[0].index(stringParts[0].startIndex, offsetBy: 1))) else { - return seal.reject(HTTP.Error.invalidResponse) - } - - let infoStringStartIndex: String.Index = responseString.index(responseString.startIndex, offsetBy: "l\(infoLength):".count) - let infoStringEndIndex: String.Index = responseString.index(infoStringStartIndex, offsetBy: infoLength) - let infoString: String = String(responseString[infoStringStartIndex.. "l\(infoLength)\(infoString)e".count else { - return seal.fulfill((responseInfo, nil)) - } - - // Extract the response data as well - let dataString: String = String(responseString.suffix(from: infoStringEndIndex)) - let dataStringParts: [String.SubSequence] = dataString.split(separator: ":") - - guard dataStringParts.count > 1, let finalDataLength: Int = Int(dataStringParts[0]), let suffixData: Data = "e".data(using: .utf8) else { - return seal.reject(HTTP.Error.invalidResponse) - } - - let dataBytes: Array = Array(data) - let dataEndIndex: Int = (dataBytes.count - suffixData.count) - let dataStartIndex: Int = (dataEndIndex - finalDataLength) - let finalDataBytes: ArraySlice = dataBytes[dataStartIndex.. (info: ResponseInfo, body: Data?)? { + // The data will be in the form of `l123:jsone` or `l123:json456:bodye` so we need to break the data + // into parts to properly process it + guard let responseString: String = String(data: data, encoding: .ascii), responseString.starts(with: "l") else { + return nil + } + + let stringParts: [String.SubSequence] = responseString.split(separator: ":") + + guard stringParts.count > 1, let infoLength: Int = Int(stringParts[0].suffix(from: stringParts[0].index(stringParts[0].startIndex, offsetBy: 1))) else { + return nil + } + + let infoStringStartIndex: String.Index = responseString.index(responseString.startIndex, offsetBy: "l\(infoLength):".count) + let infoStringEndIndex: String.Index = responseString.index(infoStringStartIndex, offsetBy: infoLength) + let infoString: String = String(responseString[infoStringStartIndex.. "l\(infoLength)\(infoString)e".count else { + return (responseInfo, nil) + } + + // Extract the response data as well + let dataString: String = String(responseString.suffix(from: infoStringEndIndex)) + let dataStringParts: [String.SubSequence] = dataString.split(separator: ":") + + guard dataStringParts.count > 1, let finalDataLength: Int = Int(dataStringParts[0]), let suffixData: Data = "e".data(using: .utf8) else { + return nil + } + + let dataBytes: Array = Array(data) + let dataEndIndex: Int = (dataBytes.count - suffixData.count) + let dataStartIndex: Int = (dataEndIndex - finalDataLength) + let finalDataBytes: ArraySlice = dataBytes[dataStartIndex.. Date: Mon, 7 Nov 2022 10:19:17 +1100 Subject: [PATCH 3/3] Actually setting the 'forceBlinded' flag --- .../Sending & Receiving/Pollers/OpenGroupPoller.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/SessionMessagingKit/Sending & Receiving/Pollers/OpenGroupPoller.swift b/SessionMessagingKit/Sending & Receiving/Pollers/OpenGroupPoller.swift index 6bb65315d..48b8c0dff 100644 --- a/SessionMessagingKit/Sending & Receiving/Pollers/OpenGroupPoller.swift +++ b/SessionMessagingKit/Sending & Receiving/Pollers/OpenGroupPoller.swift @@ -221,6 +221,7 @@ extension OpenGroupAPI { OpenGroupAPI.capabilities( db, server: server, + forceBlinded: true, using: dependencies ) }