diff --git a/Session.xcodeproj/project.pbxproj b/Session.xcodeproj/project.pbxproj index e4187065c..375c62a27 100644 --- a/Session.xcodeproj/project.pbxproj +++ b/Session.xcodeproj/project.pbxproj @@ -6040,7 +6040,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 385; + CURRENT_PROJECT_VERSION = 387; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = SUQ8J2PCT7; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; @@ -6065,7 +6065,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)"; @@ -6113,7 +6113,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 385; + CURRENT_PROJECT_VERSION = 387; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = SUQ8J2PCT7; ENABLE_NS_ASSERTIONS = NO; @@ -6143,7 +6143,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)"; @@ -6179,7 +6179,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 385; + CURRENT_PROJECT_VERSION = 387; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = SUQ8J2PCT7; FRAMEWORK_SEARCH_PATHS = "$(inherited)"; @@ -6202,7 +6202,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"; @@ -6253,7 +6253,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 385; + CURRENT_PROJECT_VERSION = 387; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = SUQ8J2PCT7; ENABLE_NS_ASSERTIONS = NO; @@ -6281,7 +6281,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"; @@ -7181,7 +7181,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 = 387; DEVELOPMENT_TEAM = SUQ8J2PCT7; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -7220,7 +7220,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"; @@ -7253,7 +7253,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 = 387; DEVELOPMENT_TEAM = SUQ8J2PCT7; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -7292,7 +7292,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 e2a61e723..569d42005 100644 --- a/Session/Conversations/ConversationVC.swift +++ b/Session/Conversations/ConversationVC.swift @@ -29,6 +29,7 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl var shouldHighlightNextScrollToInteraction: Bool = false var scrollButtonBottomConstraint: NSLayoutConstraint? var scrollButtonMessageRequestsBottomConstraint: NSLayoutConstraint? + var scrollButtonPendingMessageRequestInfoBottomConstraint: NSLayoutConstraint? var messageRequestsViewBotomConstraint: NSLayoutConstraint? // Search @@ -54,9 +55,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? @@ -234,7 +236,7 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl result.text = "MESSAGE_REQUESTS_INFO".localized() result.themeTextColor = .textSecondary result.textAlignment = .center - result.numberOfLines = 2 + result.numberOfLines = 0 return result }() @@ -268,6 +270,23 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl return result }() + + private lazy var pendingMessageRequestExplanationLabel: UILabel = { + let result: UILabel = UILabel() + result.translatesAutoresizingMaskIntoConstraints = false + result.setContentCompressionResistancePriority(.required, for: .vertical) + result.font = UIFont.systemFont(ofSize: 12) + result.text = "MESSAGE_REQUEST_PENDING_APPROVAL_INFO".localized() + result.themeTextColor = .textSecondary + result.textAlignment = .center + result.numberOfLines = 0 + result.isHidden = ( + !self.messageRequestView.isHidden || + self.viewModel.threadData.threadRequiresApproval == false + ) + + return result + }() // MARK: - Settings @@ -322,6 +341,7 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl // Message requests view & scroll to bottom view.addSubview(scrollButton) view.addSubview(messageRequestView) + view.addSubview(pendingMessageRequestExplanationLabel) messageRequestView.addSubview(messageRequestBlockButton) messageRequestView.addSubview(messageRequestDescriptionLabel) @@ -335,6 +355,7 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl self.scrollButtonBottomConstraint = scrollButton.pin(.bottom, to: .bottom, of: view, withInset: -16) self.scrollButtonBottomConstraint?.isActive = false // Note: Need to disable this to avoid a conflict with the other bottom constraint self.scrollButtonMessageRequestsBottomConstraint = scrollButton.pin(.bottom, to: .top, of: messageRequestView, withInset: -16) + self.scrollButtonPendingMessageRequestInfoBottomConstraint = scrollButton.pin(.bottom, to: .top, of: pendingMessageRequestExplanationLabel, withInset: -16) messageRequestBlockButton.pin(.top, to: .top, of: messageRequestView, withInset: 10) messageRequestBlockButton.center(.horizontal, in: messageRequestView) @@ -352,6 +373,10 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl messageRequestDeleteButton.pin(.right, to: .right, of: messageRequestView, withInset: -20) messageRequestDeleteButton.pin(.bottom, to: .bottom, of: messageRequestView) messageRequestDeleteButton.set(.width, to: .width, of: messageRequestAcceptButton) + + pendingMessageRequestExplanationLabel.pin(.left, to: .left, of: messageRequestView, withInset: 40) + pendingMessageRequestExplanationLabel.pin(.right, to: .right, of: messageRequestView, withInset: -40) + pendingMessageRequestExplanationLabel.pin(.bottom, to: .bottom, of: messageRequestView, withInset: -16) // Unread count view view.addSubview(unreadCountView) @@ -399,6 +424,8 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl super.viewWillAppear(animated) startObservingChanges() + + viewIsAppearing = true } override func viewDidAppear(_ animated: Bool) { @@ -407,7 +434,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 +453,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 +469,7 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl mediaCache.removeAllObjects() hasReloadedThreadDataAfterDisappearance = false + viewIsDisappearing = false } @objc func applicationDidBecomeActive(_ notification: Notification) { @@ -578,18 +606,34 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl { updateNavBarButtons(threadData: updatedThreadData, initialVariant: viewModel.initialThreadVariant) - let messageRequestsViewWasVisible: Bool = (messageRequestView.isHidden == false) + let messageRequestsViewWasVisible: Bool = ( + messageRequestView.isHidden == false + ) + let pendingMessageRequestInfoWasVisible: Bool = ( + pendingMessageRequestExplanationLabel.isHidden == false + ) UIView.animate(withDuration: 0.3) { [weak self] in self?.messageRequestView.isHidden = ( updatedThreadData.threadIsMessageRequest == false || updatedThreadData.threadRequiresApproval == true ) + self?.pendingMessageRequestExplanationLabel.isHidden = ( + self?.messageRequestView.isHidden == false || + updatedThreadData.threadRequiresApproval == false + ) self?.scrollButtonMessageRequestsBottomConstraint?.isActive = ( - updatedThreadData.threadIsMessageRequest == true + self?.messageRequestView.isHidden == false + ) + self?.scrollButtonPendingMessageRequestInfoBottomConstraint?.isActive = ( + self?.scrollButtonPendingMessageRequestInfoBottomConstraint?.isActive == false && + self?.pendingMessageRequestExplanationLabel.isHidden == false + ) + self?.scrollButtonBottomConstraint?.isActive = ( + self?.scrollButtonMessageRequestsBottomConstraint?.isActive == false && + self?.scrollButtonPendingMessageRequestInfoBottomConstraint?.isActive == false ) - self?.scrollButtonBottomConstraint?.isActive = (updatedThreadData.threadIsMessageRequest == false) // Update the table content inset and offset to account for // the dissapearance of the messageRequestsView @@ -603,6 +647,16 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl trailing: 0 ) } + else if pendingMessageRequestInfoWasVisible { + let messageRequestsOffset: CGFloat = ((self?.pendingMessageRequestExplanationLabel.bounds.height ?? 0) + (16 * 2)) + let oldContentInset: UIEdgeInsets = (self?.tableView.contentInset ?? UIEdgeInsets.zero) + self?.tableView.contentInset = UIEdgeInsets( + top: 0, + leading: 0, + bottom: max(oldContentInset.bottom - messageRequestsOffset, 0), + trailing: 0 + ) + } } } @@ -1069,7 +1123,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 @@ -1094,11 +1148,12 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl let keyboardTop = (UIScreen.main.bounds.height - keyboardRect.minY) let messageRequestsOffset: CGFloat = (messageRequestView.isHidden ? 0 : messageRequestView.bounds.height + 16) + let pendingMessageRequestsOffset: CGFloat = (pendingMessageRequestExplanationLabel.isHidden ? 0 : (pendingMessageRequestExplanationLabel.bounds.height + (16 * 2))) let oldContentInset: UIEdgeInsets = tableView.contentInset let newContentInset: UIEdgeInsets = UIEdgeInsets( top: 0, leading: 0, - bottom: (Values.mediumSpacing + keyboardTop + messageRequestsOffset), + bottom: (Values.mediumSpacing + keyboardTop + messageRequestsOffset + pendingMessageRequestsOffset), trailing: 0 ) let newContentOffsetY: CGFloat = (tableView.contentOffset.y + (newContentInset.bottom - oldContentInset.bottom)) @@ -1117,7 +1172,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() } @@ -1134,8 +1189,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/Session/Meta/Translations/de.lproj/Localizable.strings b/Session/Meta/Translations/de.lproj/Localizable.strings index 03a01a1c7..10c2ce745 100644 --- a/Session/Meta/Translations/de.lproj/Localizable.strings +++ b/Session/Meta/Translations/de.lproj/Localizable.strings @@ -598,3 +598,4 @@ "YOU_DISAPPERING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages"; +"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; diff --git a/Session/Meta/Translations/en.lproj/Localizable.strings b/Session/Meta/Translations/en.lproj/Localizable.strings index 9c11eddec..67133da69 100644 --- a/Session/Meta/Translations/en.lproj/Localizable.strings +++ b/Session/Meta/Translations/en.lproj/Localizable.strings @@ -598,3 +598,4 @@ "YOU_DISAPPERING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages"; +"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; diff --git a/Session/Meta/Translations/es.lproj/Localizable.strings b/Session/Meta/Translations/es.lproj/Localizable.strings index 3619cde1a..cefc78825 100644 --- a/Session/Meta/Translations/es.lproj/Localizable.strings +++ b/Session/Meta/Translations/es.lproj/Localizable.strings @@ -598,3 +598,4 @@ "YOU_DISAPPERING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages"; +"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; diff --git a/Session/Meta/Translations/fa.lproj/Localizable.strings b/Session/Meta/Translations/fa.lproj/Localizable.strings index 25c1869a5..0c1d16db5 100644 --- a/Session/Meta/Translations/fa.lproj/Localizable.strings +++ b/Session/Meta/Translations/fa.lproj/Localizable.strings @@ -598,3 +598,4 @@ "YOU_DISAPPERING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages"; +"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; diff --git a/Session/Meta/Translations/fi.lproj/Localizable.strings b/Session/Meta/Translations/fi.lproj/Localizable.strings index 741bbd8e8..cb66e006c 100644 --- a/Session/Meta/Translations/fi.lproj/Localizable.strings +++ b/Session/Meta/Translations/fi.lproj/Localizable.strings @@ -598,3 +598,4 @@ "YOU_DISAPPERING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages"; +"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; diff --git a/Session/Meta/Translations/fr.lproj/Localizable.strings b/Session/Meta/Translations/fr.lproj/Localizable.strings index 159feb782..3ad83243a 100644 --- a/Session/Meta/Translations/fr.lproj/Localizable.strings +++ b/Session/Meta/Translations/fr.lproj/Localizable.strings @@ -598,3 +598,4 @@ "YOU_DISAPPERING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages"; +"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; diff --git a/Session/Meta/Translations/hi.lproj/Localizable.strings b/Session/Meta/Translations/hi.lproj/Localizable.strings index 1e6eee0ff..4a9960713 100644 --- a/Session/Meta/Translations/hi.lproj/Localizable.strings +++ b/Session/Meta/Translations/hi.lproj/Localizable.strings @@ -598,3 +598,4 @@ "YOU_DISAPPERING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages"; +"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; diff --git a/Session/Meta/Translations/hr.lproj/Localizable.strings b/Session/Meta/Translations/hr.lproj/Localizable.strings index d13b0f11f..cebe1d317 100644 --- a/Session/Meta/Translations/hr.lproj/Localizable.strings +++ b/Session/Meta/Translations/hr.lproj/Localizable.strings @@ -598,3 +598,4 @@ "YOU_DISAPPERING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages"; +"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; diff --git a/Session/Meta/Translations/id-ID.lproj/Localizable.strings b/Session/Meta/Translations/id-ID.lproj/Localizable.strings index eeba101c4..7c349d809 100644 --- a/Session/Meta/Translations/id-ID.lproj/Localizable.strings +++ b/Session/Meta/Translations/id-ID.lproj/Localizable.strings @@ -598,3 +598,4 @@ "YOU_DISAPPERING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages"; +"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; diff --git a/Session/Meta/Translations/it.lproj/Localizable.strings b/Session/Meta/Translations/it.lproj/Localizable.strings index 70ca92445..86a38fef8 100644 --- a/Session/Meta/Translations/it.lproj/Localizable.strings +++ b/Session/Meta/Translations/it.lproj/Localizable.strings @@ -598,3 +598,4 @@ "YOU_DISAPPERING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages"; +"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; diff --git a/Session/Meta/Translations/ja.lproj/Localizable.strings b/Session/Meta/Translations/ja.lproj/Localizable.strings index cf739b52b..9442803ca 100644 --- a/Session/Meta/Translations/ja.lproj/Localizable.strings +++ b/Session/Meta/Translations/ja.lproj/Localizable.strings @@ -598,3 +598,4 @@ "YOU_DISAPPERING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages"; +"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; diff --git a/Session/Meta/Translations/nl.lproj/Localizable.strings b/Session/Meta/Translations/nl.lproj/Localizable.strings index 33eefbe49..ad165fade 100644 --- a/Session/Meta/Translations/nl.lproj/Localizable.strings +++ b/Session/Meta/Translations/nl.lproj/Localizable.strings @@ -598,3 +598,4 @@ "YOU_DISAPPERING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages"; +"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; diff --git a/Session/Meta/Translations/pl.lproj/Localizable.strings b/Session/Meta/Translations/pl.lproj/Localizable.strings index 77bcda429..41e9004ca 100644 --- a/Session/Meta/Translations/pl.lproj/Localizable.strings +++ b/Session/Meta/Translations/pl.lproj/Localizable.strings @@ -598,3 +598,4 @@ "YOU_DISAPPERING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages"; +"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; diff --git a/Session/Meta/Translations/pt_BR.lproj/Localizable.strings b/Session/Meta/Translations/pt_BR.lproj/Localizable.strings index a475a43e9..58bf3ad1e 100644 --- a/Session/Meta/Translations/pt_BR.lproj/Localizable.strings +++ b/Session/Meta/Translations/pt_BR.lproj/Localizable.strings @@ -597,4 +597,4 @@ "MESSAGE_STATE_SENT" = "sent"; "YOU_DISAPPERING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@"; -"YOU_DISAPPERING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages"; +"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; diff --git a/Session/Meta/Translations/ru.lproj/Localizable.strings b/Session/Meta/Translations/ru.lproj/Localizable.strings index 79c7da25a..02d019208 100644 --- a/Session/Meta/Translations/ru.lproj/Localizable.strings +++ b/Session/Meta/Translations/ru.lproj/Localizable.strings @@ -598,3 +598,4 @@ "YOU_DISAPPERING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages"; +"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; diff --git a/Session/Meta/Translations/si.lproj/Localizable.strings b/Session/Meta/Translations/si.lproj/Localizable.strings index 19112054a..562fd89e4 100644 --- a/Session/Meta/Translations/si.lproj/Localizable.strings +++ b/Session/Meta/Translations/si.lproj/Localizable.strings @@ -598,3 +598,4 @@ "YOU_DISAPPERING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages"; +"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; diff --git a/Session/Meta/Translations/sk.lproj/Localizable.strings b/Session/Meta/Translations/sk.lproj/Localizable.strings index 22fcb10db..cedefaa34 100644 --- a/Session/Meta/Translations/sk.lproj/Localizable.strings +++ b/Session/Meta/Translations/sk.lproj/Localizable.strings @@ -598,3 +598,4 @@ "YOU_DISAPPERING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages"; +"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; diff --git a/Session/Meta/Translations/sv.lproj/Localizable.strings b/Session/Meta/Translations/sv.lproj/Localizable.strings index e4a138ec6..37babc3aa 100644 --- a/Session/Meta/Translations/sv.lproj/Localizable.strings +++ b/Session/Meta/Translations/sv.lproj/Localizable.strings @@ -598,3 +598,4 @@ "YOU_DISAPPERING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages"; +"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; diff --git a/Session/Meta/Translations/th.lproj/Localizable.strings b/Session/Meta/Translations/th.lproj/Localizable.strings index 5284c29e7..a6a7a01ed 100644 --- a/Session/Meta/Translations/th.lproj/Localizable.strings +++ b/Session/Meta/Translations/th.lproj/Localizable.strings @@ -598,3 +598,4 @@ "YOU_DISAPPERING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages"; +"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; diff --git a/Session/Meta/Translations/vi-VN.lproj/Localizable.strings b/Session/Meta/Translations/vi-VN.lproj/Localizable.strings index 0fe70b457..2f1c6a6e2 100644 --- a/Session/Meta/Translations/vi-VN.lproj/Localizable.strings +++ b/Session/Meta/Translations/vi-VN.lproj/Localizable.strings @@ -598,3 +598,4 @@ "YOU_DISAPPERING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages"; +"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; diff --git a/Session/Meta/Translations/zh-Hant.lproj/Localizable.strings b/Session/Meta/Translations/zh-Hant.lproj/Localizable.strings index 69fb8a348..38c6fdd9b 100644 --- a/Session/Meta/Translations/zh-Hant.lproj/Localizable.strings +++ b/Session/Meta/Translations/zh-Hant.lproj/Localizable.strings @@ -598,3 +598,4 @@ "YOU_DISAPPERING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages"; +"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; diff --git a/Session/Meta/Translations/zh_CN.lproj/Localizable.strings b/Session/Meta/Translations/zh_CN.lproj/Localizable.strings index 2b5bdb9fa..36d9f9931 100644 --- a/Session/Meta/Translations/zh_CN.lproj/Localizable.strings +++ b/Session/Meta/Translations/zh_CN.lproj/Localizable.strings @@ -598,3 +598,4 @@ "YOU_DISAPPERING_MESSAGES_INFO_ENABLE" = "You have set messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_UPDATE" = "You have changed messages to disappear %@ after they have been %@"; "YOU_DISAPPERING_MESSAGES_INFO_DISABLE" = "You have turned off disappearing messages"; +"MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; 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/SessionMessagingKit/Sending & Receiving/Pollers/OpenGroupPoller.swift b/SessionMessagingKit/Sending & Receiving/Pollers/OpenGroupPoller.swift index 0166e026c..48b8c0dff 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 } @@ -213,11 +221,12 @@ extension OpenGroupAPI { OpenGroupAPI.capabilities( db, server: server, + forceBlinded: true, using: dependencies ) } .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 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..