From e6b941ea8ad6babf69a966923f67b53ac83bedb4 Mon Sep 17 00:00:00 2001 From: Morgan Pretty Date: Mon, 28 Feb 2022 17:23:34 +1100 Subject: [PATCH 1/8] Fixed a number of tweaks and bugs with message requests Removed the "Back" text from the back buttons Removed the inset on the 'Path' settings button so the text remains horizontally centered Hid the settings button from message request threads Fixed an issue where the back button would remain visible in a conversation when the search field was visible Fixed an issue where the tintColor of the conversation search field didn't match the global search field Fixed an issue where sending an attachment response to a message request wouldn't approve the message request Updated the size and positioning of the message request 'Clear All' button to match the DM 'Next' button Updated the message request 'Clear All' button to start visible (so it's visible during the push animation) since that's the most likely state it'll be in Updated the 'Message Requests' cell to use the pinned background colour Updated the fallback for contact thread names to be a middle-truncated string (4 characters either side) --- .../ConversationVC+Interaction.swift | 68 ++++++++++++++----- Session/Conversations/ConversationVC.swift | 62 +++++++++++------ .../OWSConversationSettingsViewController.m | 18 +---- .../ConversationTitleView.swift | 10 ++- Session/Home/HomeVC.swift | 7 ++ .../MessageRequestsViewController.swift | 18 ++--- Session/Home/Views/MessageRequestsCell.swift | 2 +- Session/Settings/SettingsVC.swift | 4 +- Session/Shared/ConversationCell.swift | 15 ++-- SessionUIKit/Components/Button.swift | 5 +- .../UIViewController+Utilities.swift | 2 +- 11 files changed, 133 insertions(+), 78 deletions(-) diff --git a/Session/Conversations/ConversationVC+Interaction.swift b/Session/Conversations/ConversationVC+Interaction.swift index 33ef7e6dc..cec8846ca 100644 --- a/Session/Conversations/ConversationVC+Interaction.swift +++ b/Session/Conversations/ConversationVC+Interaction.swift @@ -10,6 +10,16 @@ extension ConversationVC : InputViewDelegate, MessageCellDelegate, ContextMenuAc ConversationTitleViewDelegate { func handleTitleViewTapped() { + // Don't take the user to settings for message requests + guard + let contactThread: TSContactThread = thread as? TSContactThread, + let contact: Contact = Storage.shared.getContact(with: contactThread.contactSessionID()), + contact.isApproved, + contact.didApproveMe + else { + return + } + openSettings() } @@ -292,32 +302,56 @@ extension ConversationVC : InputViewDelegate, MessageCellDelegate, ContextMenuAc func sendAttachments(_ attachments: [SignalAttachment], with text: String, onComplete: (() -> ())? = nil) { guard !showBlockedModalIfNeeded() else { return } + for attachment in attachments { if attachment.hasError { return showErrorAlert(for: attachment, onDismiss: onComplete) } } + let thread = self.thread + let sentTimestamp: UInt64 = NSDate.millisecondTimestamp() let message = VisibleMessage() - message.sentTimestamp = NSDate.millisecondTimestamp() + message.sentTimestamp = sentTimestamp message.text = replaceMentions(in: text) + + // Note: 'shouldBeVisible' is set to true the first time a thread is saved so we can + // use it to determine if the user is creating a new thread and update the 'isApproved' + // flags appropriately + let oldThreadShouldBeVisible: Bool = thread.shouldBeVisible let tsMessage = TSOutgoingMessage.from(message, associatedWith: thread) - Storage.write(with: { transaction in - tsMessage.save(with: transaction) - // The new message cell is inserted at this point, but the TSOutgoingMessage doesn't have its attachment yet - }, completion: { [weak self] in - Storage.write(with: { transaction in - MessageSender.send(message, with: attachments, in: thread, using: transaction) - }, completion: { [weak self] in - // At this point the TSOutgoingMessage should have its attachments set, so we can scroll to the bottom knowing - // the height of the new message cell - self?.scrollToBottom(isAnimated: false) - }) - self?.handleMessageSent() - - // Attachment successfully sent - dismiss the screen - onComplete?() - }) + + Storage.write( + with: { transaction in + tsMessage.save(with: transaction) + // The new message cell is inserted at this point, but the TSOutgoingMessage doesn't have its attachment yet + }, + completion: { [weak self] in + Storage.shared.write( + with: { transaction in + self?.approveMessageRequestIfNeeded( + for: self?.thread, + with: (transaction as! YapDatabaseReadWriteTransaction), + isNewThread: !oldThreadShouldBeVisible, + timestamp: (sentTimestamp - 1) // Set 1ms earlier as this is used for sorting + ) + }, + completion: { [weak self] in + Storage.write(with: { transaction in + MessageSender.send(message, with: attachments, in: thread, using: transaction) + }, completion: { [weak self] in + // At this point the TSOutgoingMessage should have its attachments set, so we can scroll to the bottom knowing + // the height of the new message cell + self?.scrollToBottom(isAnimated: false) + }) + self?.handleMessageSent() + + // Attachment successfully sent - dismiss the screen + onComplete?() + } + ) + } + ) } func handleMessageSent() { diff --git a/Session/Conversations/ConversationVC.swift b/Session/Conversations/ConversationVC.swift index 932f2c434..f3fee082f 100644 --- a/Session/Conversations/ConversationVC.swift +++ b/Session/Conversations/ConversationVC.swift @@ -1,5 +1,6 @@ import SessionUIKit import SessionMessagingKit +import UIKit // TODO: // • Slight paging glitch when scrolling up and loading more content @@ -465,30 +466,53 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, OWSConversat // MARK: Updating func updateNavBarButtons() { + // Back button (to appear on pushed screen) + let backButton = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil) + backButton.tintColor = Colors.text + navigationItem.backBarButtonItem = backButton + + navigationItem.hidesBackButton = isShowingSearchUI + if isShowingSearchUI { navigationItem.leftBarButtonItem = nil navigationItem.rightBarButtonItems = [] - } else { + } + else { + navigationItem.hidesBackButton = false navigationItem.leftBarButtonItem = UIViewController.createOWSBackButton(withTarget: self, selector: #selector(handleBackPressed)) - let rightBarButtonItem: UIBarButtonItem - if thread is TSContactThread { - let size = Values.verySmallProfilePictureSize - let profilePictureView = ProfilePictureView() - profilePictureView.accessibilityLabel = "Settings button" - profilePictureView.size = size - profilePictureView.update(for: thread) - profilePictureView.set(.width, to: size) - profilePictureView.set(.height, to: size) - let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(openSettings)) - profilePictureView.addGestureRecognizer(tapGestureRecognizer) - rightBarButtonItem = UIBarButtonItem(customView: profilePictureView) - } else { - rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "Gear"), style: .plain, target: self, action: #selector(openSettings)) + if let contactThread: TSContactThread = thread as? TSContactThread { + // Don't show the settings button for message requests + if let contact: Contact = Storage.shared.getContact(with: contactThread.contactSessionID()), contact.isApproved, contact.didApproveMe { + let size = Values.verySmallProfilePictureSize + let profilePictureView = ProfilePictureView() + profilePictureView.size = size + profilePictureView.update(for: thread) + profilePictureView.set(.width, to: size) + profilePictureView.set(.height, to: size) + + let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(openSettings)) + profilePictureView.addGestureRecognizer(tapGestureRecognizer) + + let rightBarButtonItem: UIBarButtonItem = UIBarButtonItem(customView: profilePictureView) + rightBarButtonItem.accessibilityLabel = "Settings button" + rightBarButtonItem.isAccessibilityElement = true + + navigationItem.rightBarButtonItem = rightBarButtonItem + } + else { + // Note: Adding an empty button because without it the title alignment is busted (Note: The size was + // taken from the layout inspector for the back button in Xcode + navigationItem.rightBarButtonItem = UIBarButtonItem(customView: UIView(frame: CGRect(x: 0, y: 0, width: 37, height: 44))) + } + } + else { + let rightBarButtonItem: UIBarButtonItem = UIBarButtonItem(image: UIImage(named: "Gear"), style: .plain, target: self, action: #selector(openSettings)) + rightBarButtonItem.accessibilityLabel = "Settings button" + rightBarButtonItem.isAccessibilityElement = true + + navigationItem.rightBarButtonItem = rightBarButtonItem } - rightBarButtonItem.accessibilityLabel = "Settings button" - rightBarButtonItem.isAccessibilityElement = true - navigationItem.rightBarButtonItem = rightBarButtonItem } } @@ -819,7 +843,7 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, OWSConversat let searchBar = searchController.uiSearchController.searchBar searchBar.searchBarStyle = .minimal searchBar.barStyle = .black - searchBar.tintColor = Colors.accent + searchBar.tintColor = Colors.text let searchIcon = UIImage(named: "searchbar_search")!.asTintedImage(color: Colors.searchBarPlaceholder) searchBar.setImage(searchIcon, for: .search, state: UIControl.State.normal) let clearIcon = UIImage(named: "searchbar_clear")!.asTintedImage(color: Colors.searchBarPlaceholder) diff --git a/Session/Conversations/Settings/OWSConversationSettingsViewController.m b/Session/Conversations/Settings/OWSConversationSettingsViewController.m index 5585b155d..fcfb6d588 100644 --- a/Session/Conversations/Settings/OWSConversationSettingsViewController.m +++ b/Session/Conversations/Settings/OWSConversationSettingsViewController.m @@ -277,7 +277,7 @@ CGFloat kIconViewLength = 24; contents.title = NSLocalizedString(@"CONVERSATION_SETTINGS", @"title for conversation settings screen"); BOOL isNoteToSelf = self.thread.isNoteToSelf; - + __weak OWSConversationSettingsViewController *weakSelf = self; OWSTableSection *section = [OWSTableSection new]; @@ -332,7 +332,7 @@ CGFloat kIconViewLength = 24; } actionBlock:^{ [weakSelf tappedConversationSearch]; }]]; - + // Disappearing messages if (![self isOpenGroup]) { [section addItem:[OWSTableItem itemWithCustomCellBlock:^{ @@ -358,13 +358,6 @@ CGFloat kIconViewLength = 24; switchView.on = strongSelf.disappearingMessagesConfiguration.isEnabled; [switchView addTarget:strongSelf action:@selector(disappearingMessagesSwitchValueDidChange:) forControlEvents:UIControlEventValueChanged]; - - // Disable Disappearing Messages if the conversation hasn't been approved - if (!self.thread.isGroupThread) { - TSContactThread *thread = (TSContactThread *)self.thread; - SNContact *contact = [LKStorage.shared getContactWithSessionID:thread.contactSessionID]; - [switchView setEnabled:(contact.isApproved && contact.didApproveMe)]; - } UIStackView *topRow = [[UIStackView alloc] initWithArrangedSubviews:@[ iconView, rowLabel, switchView ]]; @@ -438,13 +431,6 @@ CGFloat kIconViewLength = 24; [slider autoPinTrailingToSuperviewMargin]; [slider autoPinBottomToSuperviewMargin]; - // Disable Disappearing Messages slider if the conversation hasn't been approved (just in case) - if (!self.thread.isGroupThread) { - TSContactThread *thread = (TSContactThread *)self.thread; - SNContact *contact = [LKStorage.shared getContactWithSessionID:thread.contactSessionID]; - [slider setEnabled:(contact.isApproved && contact.didApproveMe)]; - } - cell.userInteractionEnabled = !strongSelf.hasLeftGroup; cell.accessibilityIdentifier = ACCESSIBILITY_IDENTIFIER_WITH_NAME( diff --git a/Session/Conversations/Views & Modals/ConversationTitleView.swift b/Session/Conversations/Views & Modals/ConversationTitleView.swift index d80912b29..a557e3666 100644 --- a/Session/Conversations/Views & Modals/ConversationTitleView.swift +++ b/Session/Conversations/Views & Modals/ConversationTitleView.swift @@ -73,13 +73,17 @@ final class ConversationTitleView : UIView { private func getTitle() -> String { if let thread = thread as? TSGroupThread { return thread.groupModel.groupName! - } else if thread.isNoteToSelf() { + } + else if thread.isNoteToSelf() { return "Note to Self" - } else { + } + else { let sessionID = (thread as! TSContactThread).contactSessionID() var result = sessionID Storage.read { transaction in - result = Storage.shared.getContact(with: sessionID)?.displayName(for: .regular) ?? "Anonymous" + let displayName: String = ((Storage.shared.getContact(with: sessionID)?.displayName(for: .regular)) ?? sessionID) + let middleTruncatedHexKey: String = "\(sessionID.prefix(4))...\(sessionID.suffix(4))" + result = (displayName == sessionID ? middleTruncatedHexKey : displayName) } return result } diff --git a/Session/Home/HomeVC.swift b/Session/Home/HomeVC.swift index f8635f167..01677bf05 100644 --- a/Session/Home/HomeVC.swift +++ b/Session/Home/HomeVC.swift @@ -393,11 +393,18 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv profilePictureViewContainer.addSubview(pathStatusView) pathStatusView.pin(.trailing, to: .trailing, of: profilePictureViewContainer) pathStatusView.pin(.bottom, to: .bottom, of: profilePictureViewContainer) + + // Back button (to appear on pushed screen) + let backButton = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil) + backButton.tintColor = Colors.text + navigationItem.backBarButtonItem = backButton + // Left bar button item let leftBarButtonItem = UIBarButtonItem(customView: profilePictureViewContainer) leftBarButtonItem.accessibilityLabel = "Settings button" leftBarButtonItem.isAccessibilityElement = true navigationItem.leftBarButtonItem = leftBarButtonItem + // Right bar button item - search button let rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .search, target: self, action: #selector(showSearchUI)) rightBarButtonItem.accessibilityLabel = "Search button" diff --git a/Session/Home/Message Requests/MessageRequestsViewController.swift b/Session/Home/Message Requests/MessageRequestsViewController.swift index dfb4e1b73..32e1fc46e 100644 --- a/Session/Home/Message Requests/MessageRequestsViewController.swift +++ b/Session/Home/Message Requests/MessageRequestsViewController.swift @@ -63,23 +63,16 @@ class MessageRequestsViewController: BaseVC, UITableViewDelegate, UITableViewDat return result }() - private lazy var clearAllButton: UIButton = { - let result: UIButton = UIButton() + private lazy var clearAllButton: Button = { + let result: Button = Button(style: .destructiveOutline, size: .large) result.translatesAutoresizingMaskIntoConstraints = false - result.clipsToBounds = true - result.titleLabel?.font = UIFont.boldSystemFont(ofSize: 18) result.setTitle(NSLocalizedString("MESSAGE_REQUESTS_CLEAR_ALL", comment: ""), for: .normal) - result.setTitleColor(Colors.destructive, for: .normal) result.setBackgroundImage( Colors.destructive .withAlphaComponent(isDarkMode ? 0.2 : 0.06) .toImage(isDarkMode: isDarkMode), for: .highlighted ) - result.isHidden = true - result.layer.cornerRadius = (NewConversationButtonSet.collapsedButtonSize / 2) - result.layer.borderColor = Colors.destructive.cgColor - result.layer.borderWidth = 1.5 result.addTarget(self, action: #selector(clearAllTapped), for: .touchUpInside) return result @@ -163,10 +156,11 @@ class MessageRequestsViewController: BaseVC, UITableViewDelegate, UITableViewDat clearAllButton.centerXAnchor.constraint(equalTo: view.centerXAnchor), clearAllButton.bottomAnchor.constraint( - equalTo: view.bottomAnchor, - constant: -Values.newConversationButtonBottomOffset // Negative due to how the constraint is set up + equalTo: view.safeAreaLayoutGuide.bottomAnchor, + constant: -Values.largeSpacing ), - clearAllButton.widthAnchor.constraint(equalToConstant: 155), + // Note: The '182' is to match the 'Next' button on the New DM page (which doesn't have a fixed width) + clearAllButton.widthAnchor.constraint(equalToConstant: 182), clearAllButton.heightAnchor.constraint(equalToConstant: NewConversationButtonSet.collapsedButtonSize) ]) } diff --git a/Session/Home/Views/MessageRequestsCell.swift b/Session/Home/Views/MessageRequestsCell.swift index 5229a9540..54002f721 100644 --- a/Session/Home/Views/MessageRequestsCell.swift +++ b/Session/Home/Views/MessageRequestsCell.swift @@ -76,7 +76,7 @@ class MessageRequestsCell: UITableViewCell { }() private func setUpViewHierarchy() { - backgroundColor = Colors.cellBackground + backgroundColor = Colors.cellPinned selectedBackgroundView = UIView() selectedBackgroundView?.backgroundColor = Colors.cellSelected diff --git a/Session/Settings/SettingsVC.swift b/Session/Settings/SettingsVC.swift index 46be1b4d7..72228f5a8 100644 --- a/Session/Settings/SettingsVC.swift +++ b/Session/Settings/SettingsVC.swift @@ -139,7 +139,7 @@ final class SettingsVC : BaseVC, AvatarViewHelperDelegate { setUpNavBarStyle() setNavBarTitle(NSLocalizedString("vc_settings_title", comment: "")) // Navigation bar buttons - let backButton = UIBarButtonItem(title: "Back", style: .plain, target: nil, action: nil) + let backButton = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil) backButton.tintColor = Colors.text navigationItem.backBarButtonItem = backButton updateNavigationBarButtons() @@ -254,8 +254,6 @@ final class SettingsVC : BaseVC, AvatarViewHelperDelegate { pathStatusView.pin(.leading, to: .trailing, of: pathButton.titleLabel!, withInset: Values.smallSpacing) pathStatusView.autoVCenterInSuperview() - pathButton.titleEdgeInsets = UIEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: Values.smallSpacing) - return [ getSeparator(), pathButton, diff --git a/Session/Shared/ConversationCell.swift b/Session/Shared/ConversationCell.swift index 3d56f4ecb..1e376ed3d 100644 --- a/Session/Shared/ConversationCell.swift +++ b/Session/Shared/ConversationCell.swift @@ -358,15 +358,20 @@ final class ConversationCell : UITableViewCell { if threadViewModel.isGroupThread { if threadViewModel.name.isEmpty { return "Unknown Group" - } else { + } + else { return threadViewModel.name } - } else { + } + else { if threadViewModel.threadRecord.isNoteToSelf() { return NSLocalizedString("NOTE_TO_SELF", comment: "") - } else { - let hexEncodedPublicKey = threadViewModel.contactSessionID! - return Storage.shared.getContact(with: hexEncodedPublicKey)?.displayName(for: .regular) ?? hexEncodedPublicKey + } + else { + let hexEncodedPublicKey: String = threadViewModel.contactSessionID! + let displayName: String = (Storage.shared.getContact(with: hexEncodedPublicKey)?.displayName(for: .regular) ?? hexEncodedPublicKey) + let middleTruncatedHexKey: String = "\(hexEncodedPublicKey.prefix(4))...\(hexEncodedPublicKey.suffix(4))" + return (displayName == hexEncodedPublicKey ? middleTruncatedHexKey : displayName) } } } diff --git a/SessionUIKit/Components/Button.swift b/SessionUIKit/Components/Button.swift index 93aaaf6f6..adb45f592 100644 --- a/SessionUIKit/Components/Button.swift +++ b/SessionUIKit/Components/Button.swift @@ -6,7 +6,7 @@ public final class Button : UIButton { private var heightConstraint: NSLayoutConstraint! public enum Style { - case unimportant, regular, prominentOutline, prominentFilled, regularBorderless + case unimportant, regular, prominentOutline, prominentFilled, regularBorderless, destructiveOutline } public enum Size { @@ -41,6 +41,7 @@ public final class Button : UIButton { case .prominentOutline: fillColor = UIColor.clear case .prominentFilled: fillColor = isLightMode ? Colors.text : Colors.accent case .regularBorderless: fillColor = UIColor.clear + case .destructiveOutline: fillColor = UIColor.clear } let borderColor: UIColor switch style { @@ -49,6 +50,7 @@ public final class Button : UIButton { case .prominentOutline: borderColor = isLightMode ? Colors.text : Colors.accent case .prominentFilled: borderColor = isLightMode ? Colors.text : Colors.accent case .regularBorderless: borderColor = UIColor.clear + case .destructiveOutline: borderColor = Colors.destructive } let textColor: UIColor switch style { @@ -57,6 +59,7 @@ public final class Button : UIButton { case .prominentOutline: textColor = isLightMode ? Colors.text : Colors.accent case .prominentFilled: textColor = isLightMode ? UIColor.white : Colors.text case .regularBorderless: textColor = Colors.text + case .destructiveOutline: textColor = Colors.destructive } let height: CGFloat switch size { diff --git a/SignalUtilitiesKit/Utilities/UIViewController+Utilities.swift b/SignalUtilitiesKit/Utilities/UIViewController+Utilities.swift index 582f9d38f..e5a0acb48 100644 --- a/SignalUtilitiesKit/Utilities/UIViewController+Utilities.swift +++ b/SignalUtilitiesKit/Utilities/UIViewController+Utilities.swift @@ -28,7 +28,7 @@ public final class ViewControllerUtilities : NSObject { } // Set up back button if hasCustomBackButton { - let backButton = UIBarButtonItem(title: "Back", style: .plain, target: nil, action: nil) + let backButton = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil) backButton.tintColor = Colors.text vc.navigationItem.backBarButtonItem = backButton } From b077061714ab9b431d263da32ae5bfe1aee34aa7 Mon Sep 17 00:00:00 2001 From: Morgan Pretty Date: Mon, 28 Feb 2022 17:29:17 +1100 Subject: [PATCH 2/8] Updated the code to parse an open group URL to handle a '/r/' before the room name --- SessionMessagingKit/Open Groups/OpenGroupManagerV2.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SessionMessagingKit/Open Groups/OpenGroupManagerV2.swift b/SessionMessagingKit/Open Groups/OpenGroupManagerV2.swift index 9e7f7fe73..852520d45 100644 --- a/SessionMessagingKit/Open Groups/OpenGroupManagerV2.swift +++ b/SessionMessagingKit/Open Groups/OpenGroupManagerV2.swift @@ -117,7 +117,8 @@ public final class OpenGroupManagerV2 : NSObject { // https://143.198.213.225:443/main?public_key=658d29b91892a2389505596b135e76a53db6e11d613a51dbd3d0816adffb231c // 143.198.213.255:80/main?public_key=658d29b91892a2389505596b135e76a53db6e11d613a51dbd3d0816adffb231c let useTLS = (url.scheme == "https") - let room = String(url.path.dropFirst()) // Drop the leading slash + let updatedPath = (url.path.starts(with: "/r/") ? url.path.substring(from: 2) : url.path) + let room = String(updatedPath.dropFirst()) // Drop the leading slash let queryParts = query.split(separator: "=") guard !room.isEmpty && !room.contains("/"), queryParts.count == 2, queryParts[0] == "public_key" else { return nil } let publicKey = String(queryParts[1]) From 110c7bb01a39d86e29293d14d08ff1a3bb4e00d6 Mon Sep 17 00:00:00 2001 From: Morgan Pretty Date: Tue, 1 Mar 2022 10:25:54 +1100 Subject: [PATCH 3/8] Addressed PR comments Moved the 'backBarButtonItem' into the BaseVC (and removed it for being duplicated in various view controllers) Removed a redundant line of code --- Session/Conversations/ConversationVC.swift | 6 ------ Session/Home/HomeVC.swift | 5 ----- Session/Settings/SettingsVC.swift | 3 --- Session/Shared/BaseVC.swift | 6 ++++++ 4 files changed, 6 insertions(+), 14 deletions(-) diff --git a/Session/Conversations/ConversationVC.swift b/Session/Conversations/ConversationVC.swift index f3fee082f..03d148f9a 100644 --- a/Session/Conversations/ConversationVC.swift +++ b/Session/Conversations/ConversationVC.swift @@ -466,11 +466,6 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, OWSConversat // MARK: Updating func updateNavBarButtons() { - // Back button (to appear on pushed screen) - let backButton = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil) - backButton.tintColor = Colors.text - navigationItem.backBarButtonItem = backButton - navigationItem.hidesBackButton = isShowingSearchUI if isShowingSearchUI { @@ -478,7 +473,6 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, OWSConversat navigationItem.rightBarButtonItems = [] } else { - navigationItem.hidesBackButton = false navigationItem.leftBarButtonItem = UIViewController.createOWSBackButton(withTarget: self, selector: #selector(handleBackPressed)) if let contactThread: TSContactThread = thread as? TSContactThread { diff --git a/Session/Home/HomeVC.swift b/Session/Home/HomeVC.swift index 01677bf05..3d3217e0f 100644 --- a/Session/Home/HomeVC.swift +++ b/Session/Home/HomeVC.swift @@ -394,11 +394,6 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv pathStatusView.pin(.trailing, to: .trailing, of: profilePictureViewContainer) pathStatusView.pin(.bottom, to: .bottom, of: profilePictureViewContainer) - // Back button (to appear on pushed screen) - let backButton = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil) - backButton.tintColor = Colors.text - navigationItem.backBarButtonItem = backButton - // Left bar button item let leftBarButtonItem = UIBarButtonItem(customView: profilePictureViewContainer) leftBarButtonItem.accessibilityLabel = "Settings button" diff --git a/Session/Settings/SettingsVC.swift b/Session/Settings/SettingsVC.swift index 72228f5a8..9641f53dd 100644 --- a/Session/Settings/SettingsVC.swift +++ b/Session/Settings/SettingsVC.swift @@ -139,9 +139,6 @@ final class SettingsVC : BaseVC, AvatarViewHelperDelegate { setUpNavBarStyle() setNavBarTitle(NSLocalizedString("vc_settings_title", comment: "")) // Navigation bar buttons - let backButton = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil) - backButton.tintColor = Colors.text - navigationItem.backBarButtonItem = backButton updateNavigationBarButtons() // Profile picture view let profilePictureTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(showEditProfilePictureUI)) diff --git a/Session/Shared/BaseVC.swift b/Session/Shared/BaseVC.swift index 1f2ad64d9..b0692e5b7 100644 --- a/Session/Shared/BaseVC.swift +++ b/Session/Shared/BaseVC.swift @@ -46,6 +46,7 @@ class BaseVC : UIViewController { internal func setUpNavBarStyle() { guard let navigationBar = navigationController?.navigationBar else { return } + if #available(iOS 15.0, *) { let appearance = UINavigationBarAppearance() appearance.configureWithOpaqueBackground() @@ -59,6 +60,11 @@ class BaseVC : UIViewController { navigationBar.isTranslucent = false navigationBar.barTintColor = Colors.navigationBarBackground } + + // Back button (to appear on pushed screen) + let backButton = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil) + backButton.tintColor = Colors.text + navigationItem.backBarButtonItem = backButton } internal func setNavBarTitle(_ title: String, customFontSize: CGFloat? = nil) { From f0f4128db23b48435f18988ab5b9d5ca48a1c87c Mon Sep 17 00:00:00 2001 From: Morgan Pretty Date: Tue, 1 Mar 2022 15:26:14 +1100 Subject: [PATCH 4/8] Fixed an issue where the MessageRequestResponse could fail to send but would be flagged locally as approved --- .../ConversationVC+Interaction.swift | 194 ++++++++++-------- 1 file changed, 111 insertions(+), 83 deletions(-) diff --git a/Session/Conversations/ConversationVC+Interaction.swift b/Session/Conversations/ConversationVC+Interaction.swift index cec8846ca..dbd3859ac 100644 --- a/Session/Conversations/ConversationVC+Interaction.swift +++ b/Session/Conversations/ConversationVC+Interaction.swift @@ -2,6 +2,7 @@ import UIKit import CoreServices import Photos import PhotosUI +import PromiseKit import SessionUtilitiesKit import SignalUtilitiesKit @@ -262,41 +263,48 @@ extension ConversationVC : InputViewDelegate, MessageCellDelegate, ContextMenuAc let linkPreviewDraft = snInputView.linkPreviewInfo?.draft let tsMessage = TSOutgoingMessage.from(message, associatedWith: thread) - viewModel.appendUnsavedOutgoingTextMessage(tsMessage) - Storage.write(with: { transaction in - message.linkPreview = VisibleMessage.LinkPreview.from(linkPreviewDraft, using: transaction) - }, completion: { [weak self] in - tsMessage.linkPreview = OWSLinkPreview.from(message.linkPreview) - - Storage.shared.write( - with: { transaction in - tsMessage.save(with: transaction as! YapDatabaseReadWriteTransaction) - }, - completion: { [weak self] in - // At this point the TSOutgoingMessage should have its link preview set, so we can scroll to the bottom knowing - // the height of the new message cell - self?.scrollToBottom(isAnimated: false) - } + let promise: Promise = self.approveMessageRequestIfNeeded( + for: self.thread, + with: transaction, + isNewThread: !oldThreadShouldBeVisible, + timestamp: (sentTimestamp - 1) // Set 1ms earlier as this is used for sorting ) - - Storage.shared.write( - with: { transaction in - self?.approveMessageRequestIfNeeded( - for: self?.thread, - with: (transaction as! YapDatabaseReadWriteTransaction), - isNewThread: !oldThreadShouldBeVisible, - timestamp: (sentTimestamp - 1) // Set 1ms earlier as this is used for sorting + .map { [weak self] _ in + self?.viewModel.appendUnsavedOutgoingTextMessage(tsMessage) + + Storage.write(with: { transaction in + message.linkPreview = VisibleMessage.LinkPreview.from(linkPreviewDraft, using: transaction) + }, completion: { [weak self] in + tsMessage.linkPreview = OWSLinkPreview.from(message.linkPreview) + + Storage.shared.write( + with: { transaction in + tsMessage.save(with: transaction as! YapDatabaseReadWriteTransaction) + }, + completion: { [weak self] in + // At this point the TSOutgoingMessage should have its link preview set, so we can scroll to the bottom knowing + // the height of the new message cell + self?.scrollToBottom(isAnimated: false) + } ) - }, - completion: { [weak self] in + Storage.shared.write { transaction in MessageSender.send(message, with: [], in: thread, using: transaction as! YapDatabaseReadWriteTransaction) } self?.handleMessageSent() - } - ) + }) + } + + // Show an error indicating that approving the thread failed + promise.catch(on: DispatchQueue.main) { [weak self] _ in + let alert = UIAlertController(title: "Session", message: "An error occurred when trying to accept this message request", preferredStyle: .alert) + alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) + self?.present(alert, animated: true, completion: nil) + } + + promise.retainUntilComplete() }) } @@ -321,20 +329,18 @@ extension ConversationVC : InputViewDelegate, MessageCellDelegate, ContextMenuAc let oldThreadShouldBeVisible: Bool = thread.shouldBeVisible let tsMessage = TSOutgoingMessage.from(message, associatedWith: thread) - Storage.write( - with: { transaction in - tsMessage.save(with: transaction) - // The new message cell is inserted at this point, but the TSOutgoingMessage doesn't have its attachment yet - }, - completion: { [weak self] in - Storage.shared.write( + Storage.write(with: { transaction in + let promise: Promise = self.approveMessageRequestIfNeeded( + for: self.thread, + with: transaction, + isNewThread: !oldThreadShouldBeVisible, + timestamp: (sentTimestamp - 1) // Set 1ms earlier as this is used for sorting + ) + .map { [weak self] _ in + Storage.write( with: { transaction in - self?.approveMessageRequestIfNeeded( - for: self?.thread, - with: (transaction as! YapDatabaseReadWriteTransaction), - isNewThread: !oldThreadShouldBeVisible, - timestamp: (sentTimestamp - 1) // Set 1ms earlier as this is used for sorting - ) + tsMessage.save(with: transaction) + // The new message cell is inserted at this point, but the TSOutgoingMessage doesn't have its attachment yet }, completion: { [weak self] in Storage.write(with: { transaction in @@ -351,7 +357,16 @@ extension ConversationVC : InputViewDelegate, MessageCellDelegate, ContextMenuAc } ) } - ) + + // Show an error indicating that approving the thread failed + promise.catch(on: DispatchQueue.main) { [weak self] _ in + let alert = UIAlertController(title: "Session", message: "An error occurred when trying to accept this message request", preferredStyle: .alert) + alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) + self?.present(alert, animated: true, completion: nil) + } + + promise.retainUntilComplete() + }) } func handleMessageSent() { @@ -1119,8 +1134,8 @@ extension ConversationVC { navigationController?.popToViewController(viewControllers[messageRequestsIndex - 1], animated: true) } - fileprivate func approveMessageRequestIfNeeded(for thread: TSThread?, with transaction: YapDatabaseReadWriteTransaction, isNewThread: Bool, timestamp: UInt64) { - guard let contactThread: TSContactThread = thread as? TSContactThread else { return } + fileprivate func approveMessageRequestIfNeeded(for thread: TSThread?, with transaction: YapDatabaseReadWriteTransaction, isNewThread: Bool, timestamp: UInt64) -> Promise { + guard let contactThread: TSContactThread = thread as? TSContactThread else { return Promise.value(()) } // If the contact doesn't exist then we should create it so we can store the 'isApproved' state // (it'll be updated with correct profile info if they accept the message request so this @@ -1128,64 +1143,77 @@ extension ConversationVC { let sessionId: String = contactThread.contactSessionID() let contact: Contact = (Storage.shared.getContact(with: sessionId) ?? Contact(sessionID: sessionId)) - if !contact.isApproved { - // Default 'didApproveMe' to true for the person approving the message request - contact.isApproved = true - contact.didApproveMe = (contact.didApproveMe || !isNewThread) - Storage.shared.setContact(contact, using: transaction) - - // If we aren't creating a new thread (ie. sending a message request) then send a - // messageRequestResponse back to the sender (this allows the sender to know that - // they have been approved and can now use this contact in closed groups) - if !isNewThread { + guard !contact.isApproved else { return Promise.value(()) } + + return Promise.value(()) + .then { _ -> Promise in + guard !isNewThread else { return Promise.value(()) } + + // If we aren't creating a new thread (ie. sending a message request) then send a + // messageRequestResponse back to the sender (this allows the sender to know that + // they have been approved and can now use this contact in closed groups) let messageRequestResponse: MessageRequestResponse = MessageRequestResponse( isApproved: true ) messageRequestResponse.sentTimestamp = timestamp - MessageSender.send(messageRequestResponse, in: contactThread, using: transaction) + return MessageSender.sendNonDurably(messageRequestResponse, in: contactThread, using: transaction) } - - // Hide the 'messageRequestView' since the request has been approved and force a config - // sync to propagate the contact approval state (both must run on the main thread) - DispatchQueue.main.async { [weak self] in - let messageRequestViewWasVisible: Bool = (self?.messageRequestView.isHidden == false) + .map { _ in + // Default 'didApproveMe' to true for the person approving the message request + contact.isApproved = true + contact.didApproveMe = (contact.didApproveMe || !isNewThread) + Storage.shared.setContact(contact, using: transaction) - UIView.animate(withDuration: 0.3) { - self?.messageRequestView.isHidden = true - self?.scrollButtonMessageRequestsBottomConstraint?.isActive = false - self?.scrollButtonBottomConstraint?.isActive = true + // Hide the 'messageRequestView' since the request has been approved and force a config + // sync to propagate the contact approval state (both must run on the main thread) + DispatchQueue.main.async { [weak self] in + let messageRequestViewWasVisible: Bool = (self?.messageRequestView.isHidden == false) - // Update the table content inset and offset to account for the dissapearance of - // the messageRequestsView - if messageRequestViewWasVisible { - let messageRequestsOffset: CGFloat = ((self?.messageRequestView.bounds.height ?? 0) + 16) - let oldContentInset: UIEdgeInsets = (self?.messagesTableView.contentInset ?? UIEdgeInsets.zero) - self?.messagesTableView.contentInset = UIEdgeInsets( - top: 0, - leading: 0, - bottom: max(oldContentInset.bottom - messageRequestsOffset, 0), - trailing: 0 - ) + UIView.animate(withDuration: 0.3) { + self?.messageRequestView.isHidden = true + self?.scrollButtonMessageRequestsBottomConstraint?.isActive = false + self?.scrollButtonBottomConstraint?.isActive = true + + // Update the table content inset and offset to account for the dissapearance of + // the messageRequestsView + if messageRequestViewWasVisible { + let messageRequestsOffset: CGFloat = ((self?.messageRequestView.bounds.height ?? 0) + 16) + let oldContentInset: UIEdgeInsets = (self?.messagesTableView.contentInset ?? UIEdgeInsets.zero) + self?.messagesTableView.contentInset = UIEdgeInsets( + top: 0, + leading: 0, + bottom: max(oldContentInset.bottom - messageRequestsOffset, 0), + trailing: 0 + ) + } + } + + // Send a sync message with the details of the contact + if let appDelegate = UIApplication.shared.delegate as? AppDelegate { + appDelegate.forceSyncConfigurationNowIfNeeded(with: transaction).retainUntilComplete() } - } - - // Send a sync message with the details of the contact - if let appDelegate = UIApplication.shared.delegate as? AppDelegate { - appDelegate.forceSyncConfigurationNowIfNeeded(with: transaction).retainUntilComplete() } } - } } @objc func acceptMessageRequest() { - Storage.write { [weak self] transaction in - self?.approveMessageRequestIfNeeded( - for: self?.thread, + Storage.write { transaction in + let promise: Promise = self.approveMessageRequestIfNeeded( + for: self.thread, with: transaction, isNewThread: false, timestamp: NSDate.millisecondTimestamp() ) + + // Show an error indicating that approving the thread failed + promise.catch(on: DispatchQueue.main) { [weak self] _ in + let alert = UIAlertController(title: "Session", message: "An error occurred when trying to accept this message request", preferredStyle: .alert) + alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) + self?.present(alert, animated: true, completion: nil) + } + + promise.retainUntilComplete() } } From 9251d98bde3224e4d0d22833b0f67dd9853358dd Mon Sep 17 00:00:00 2001 From: Morgan Pretty Date: Tue, 1 Mar 2022 16:48:47 +1100 Subject: [PATCH 5/8] Added a loading state when approving a message request Removed the 'presentTimer' logic from the 'ModalActivityIndicatorViewController' (the delay looked buggy, if it does have "blipping" issues then we can fix those separately) --- .../ConversationVC+Interaction.swift | 17 ++++++++- ...ModalActivityIndicatorViewController.swift | 38 +------------------ 2 files changed, 16 insertions(+), 39 deletions(-) diff --git a/Session/Conversations/ConversationVC+Interaction.swift b/Session/Conversations/ConversationVC+Interaction.swift index dbd3859ac..8dd7cef14 100644 --- a/Session/Conversations/ConversationVC+Interaction.swift +++ b/Session/Conversations/ConversationVC+Interaction.swift @@ -1146,18 +1146,31 @@ extension ConversationVC { guard !contact.isApproved else { return Promise.value(()) } return Promise.value(()) - .then { _ -> Promise in + .then { [weak self] _ -> Promise in guard !isNewThread else { return Promise.value(()) } + guard let strongSelf = self else { return Promise(error: MessageSender.Error.noThread) } // If we aren't creating a new thread (ie. sending a message request) then send a // messageRequestResponse back to the sender (this allows the sender to know that // they have been approved and can now use this contact in closed groups) + let (promise, seal) = Promise.pending() let messageRequestResponse: MessageRequestResponse = MessageRequestResponse( isApproved: true ) messageRequestResponse.sentTimestamp = timestamp - return MessageSender.sendNonDurably(messageRequestResponse, in: contactThread, using: transaction) + // Show a loading indicator + ModalActivityIndicatorViewController.present(fromViewController: strongSelf, canCancel: false) { _ in + seal.fulfill(()) + } + + return promise + .then { MessageSender.sendNonDurably(messageRequestResponse, in: contactThread, using: transaction) } + .map { _ in + if self?.presentedViewController is ModalActivityIndicatorViewController { + self?.dismiss(animated: true, completion: nil) // Dismiss the loader + } + } } .map { _ in // Default 'didApproveMe' to true for the person approving the message request diff --git a/SignalUtilitiesKit/Shared View Controllers/ModalActivityIndicatorViewController.swift b/SignalUtilitiesKit/Shared View Controllers/ModalActivityIndicatorViewController.swift index c99a28310..a38915a40 100644 --- a/SignalUtilitiesKit/Shared View Controllers/ModalActivityIndicatorViewController.swift +++ b/SignalUtilitiesKit/Shared View Controllers/ModalActivityIndicatorViewController.swift @@ -25,8 +25,6 @@ public class ModalActivityIndicatorViewController: OWSViewController { return result }() - var presentTimer: Timer? - var wasDimissed: Bool = false // MARK: Initializers @@ -127,41 +125,7 @@ public class ModalActivityIndicatorViewController: OWSViewController { self.spinner.startAnimating() - // Hide the the modal and wait for a second before revealing it, - // to avoid "blipping" in the modal during short blocking operations. - // - // NOTE: It will still intercept user interactions while hidden, as it - // should. - let kPresentationDelaySeconds = TimeInterval(1) - self.presentTimer?.invalidate() - self.presentTimer = Timer.weakScheduledTimer(withTimeInterval: kPresentationDelaySeconds, target: self, selector: #selector(presentTimerFired), userInfo: nil, repeats: false) - } - - public override func viewWillDisappear(_ animated: Bool) { - super.viewWillDisappear(animated) - - clearTimer() - } - - public override func viewDidDisappear(_ animated: Bool) { - super.viewDidDisappear(animated) - - self.spinner.stopAnimating() - - clearTimer() - } - - private func clearTimer() { - self.presentTimer?.invalidate() - self.presentTimer = nil - } - - @objc func presentTimerFired() { - AssertIsOnMainThread() - - clearTimer() - - // Fade in the modal. + // Fade in the modal UIView.animate(withDuration: 0.35) { self.view.layer.opacity = 1.0 } From 1b3f6c0ca6368c14ffe7b0f1a91aba85f37a40dd Mon Sep 17 00:00:00 2001 From: Morgan Pretty Date: Tue, 1 Mar 2022 17:25:53 +1100 Subject: [PATCH 6/8] Minor tweaks to the message request banner on the HomeVC Fixed the unread message counting for message requests Updated the message request banner to indicate the number of message requests with an unread message Updated the message request banner to automatically disappear if the user has no unread message requests Renamed a variable for ReadReceipt management to make it a bit more self-documenting (it looked like it would trigger a read receipt to be sent regardless of the setting) --- .../ConversationMessageMapping.swift | 2 +- Session/Conversations/ConversationVC.swift | 7 ++-- Session/Home/HomeVC.swift | 27 +++++++++++++--- .../Messages/Signal/TSIncomingMessage.m | 8 ++--- .../Messages/Signal/TSInfoMessage.m | 4 +-- .../MessageReceiver+Handling.swift | 2 +- .../Read Tracking/OWSReadReceiptManager.h | 2 +- .../Read Tracking/OWSReadReceiptManager.m | 8 ++--- .../Read Tracking/OWSReadTracking.h | 2 +- SessionMessagingKit/Threads/TSThread.m | 2 +- .../Messaging/OWSMessageUtils.h | 1 + .../Messaging/OWSMessageUtils.m | 32 +++++++++++++++++++ 12 files changed, 76 insertions(+), 21 deletions(-) diff --git a/Session/Conversations/ConversationMessageMapping.swift b/Session/Conversations/ConversationMessageMapping.swift index f48503948..7075edc57 100644 --- a/Session/Conversations/ConversationMessageMapping.swift +++ b/Session/Conversations/ConversationMessageMapping.swift @@ -229,7 +229,7 @@ public class ConversationMessageMapping: NSObject { let indexPtr: UnsafeMutablePointer = UnsafeMutablePointer.allocate(capacity: 1) let wasFound = view.getGroup(nil, index: indexPtr, forKey: uniqueId, inCollection: TSInteraction.collection()) guard wasFound else { - owsFailDebug("Could not find interaction.") + SNLog("Could not find interaction.") return nil } let index = indexPtr.pointee diff --git a/Session/Conversations/ConversationVC.swift b/Session/Conversations/ConversationVC.swift index 03d148f9a..ae14bfe0a 100644 --- a/Session/Conversations/ConversationVC.swift +++ b/Session/Conversations/ConversationVC.swift @@ -731,9 +731,12 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, OWSConversat } func markAllAsRead() { - guard !thread.isMessageRequest() else { return } guard let lastSortID = viewItems.last?.interaction.sortId else { return } - OWSReadReceiptManager.shared().markAsReadLocally(beforeSortId: lastSortID, thread: thread) + OWSReadReceiptManager.shared().markAsReadLocally( + beforeSortId: lastSortID, + thread: thread, + trySendReadReceipt: !thread.isMessageRequest() + ) SSKEnvironment.shared.disappearingMessagesJob.cleanupMessagesWhichFailedToStartExpiringFromNow() } diff --git a/Session/Home/HomeVC.swift b/Session/Home/HomeVC.swift index 3d3217e0f..fb307db18 100644 --- a/Session/Home/HomeVC.swift +++ b/Session/Home/HomeVC.swift @@ -6,6 +6,7 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv private var threads: YapDatabaseViewMappings! private var threadViewModelCache: [String:ThreadViewModel] = [:] // Thread ID to ThreadViewModel private var tableViewTopConstraint: NSLayoutConstraint! + private var unreadMessageRequestCount: UInt = 0 private var messageRequestCount: UInt { threads.numberOfItems(inGroup: TSMessageRequestGroup) @@ -196,7 +197,7 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv switch indexPath.section { case 0: let cell = tableView.dequeueReusableCell(withIdentifier: MessageRequestsCell.reuseIdentifier) as! MessageRequestsCell - cell.update(with: Int(messageRequestCount)) + cell.update(with: Int(unreadMessageRequestCount)) return cell default: @@ -263,6 +264,14 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv } } + // Update the number of unread message requests + unreadMessageRequestCount = OWSMessageUtils.sharedManager().unreadMessageRequestCount() + + // If there are no unread message requests then hide the message request banner + if unreadMessageRequestCount == 0 { + CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] = true + } + return reload() } } @@ -286,11 +295,21 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv // If we need to unhide the message request row and then re-insert it if !messageRequestChanges.isEmpty { - if tableView.numberOfRows(inSection: 0) == 1 && Int(messageRequestCount) <= 0 { + // Update the number of unread message requests + unreadMessageRequestCount = OWSMessageUtils.sharedManager().unreadMessageRequestCount() + + // If there are no unread message requests then hide the message request banner + if unreadMessageRequestCount == 0 && tableView.numberOfRows(inSection: 0) == 1 { + CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] = true tableView.deleteRows(at: [IndexPath(row: 0, section: 0)], with: .automatic) } - else if tableView.numberOfRows(inSection: 0) == 0 && Int(messageRequestCount) > 0 && !CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] { - tableView.insertRows(at: [IndexPath(row: 0, section: 0)], with: .automatic) + else { + if tableView.numberOfRows(inSection: 0) == 1 && Int(messageRequestCount) <= 0 { + tableView.deleteRows(at: [IndexPath(row: 0, section: 0)], with: .automatic) + } + else if tableView.numberOfRows(inSection: 0) == 0 && Int(messageRequestCount) > 0 && !CurrentAppContext().appUserDefaults()[.hasHiddenMessageRequests] { + tableView.insertRows(at: [IndexPath(row: 0, section: 0)], with: .automatic) + } } } diff --git a/SessionMessagingKit/Messages/Signal/TSIncomingMessage.m b/SessionMessagingKit/Messages/Signal/TSIncomingMessage.m index e80bf0bdb..a6578df0c 100644 --- a/SessionMessagingKit/Messages/Signal/TSIncomingMessage.m +++ b/SessionMessagingKit/Messages/Signal/TSIncomingMessage.m @@ -140,16 +140,16 @@ NS_ASSUME_NONNULL_BEGIN return YES; } -- (void)markAsReadNowWithSendReadReceipt:(BOOL)sendReadReceipt +- (void)markAsReadNowWithTrySendReadReceipt:(BOOL)trySendReadReceipt transaction:(YapDatabaseReadWriteTransaction *)transaction; { [self markAsReadAtTimestamp:[NSDate millisecondTimestamp] - sendReadReceipt:sendReadReceipt + trySendReadReceipt:trySendReadReceipt transaction:transaction]; } - (void)markAsReadAtTimestamp:(uint64_t)readTimestamp - sendReadReceipt:(BOOL)sendReadReceipt + trySendReadReceipt:(BOOL)trySendReadReceipt transaction:(YapDatabaseReadWriteTransaction *)transaction; { if (_read && readTimestamp >= self.expireStartedAt) { @@ -174,7 +174,7 @@ NS_ASSUME_NONNULL_BEGIN expirationStartedAt:readTimestamp transaction:transaction]; - if (sendReadReceipt) { + if (trySendReadReceipt) { [OWSReadReceiptManager.sharedManager messageWasReadLocally:self]; } } diff --git a/SessionMessagingKit/Messages/Signal/TSInfoMessage.m b/SessionMessagingKit/Messages/Signal/TSInfoMessage.m index 5785196a6..9d303a1bf 100644 --- a/SessionMessagingKit/Messages/Signal/TSInfoMessage.m +++ b/SessionMessagingKit/Messages/Signal/TSInfoMessage.m @@ -134,7 +134,7 @@ NSUInteger TSInfoMessageSchemaVersion = 1; } - (void)markAsReadAtTimestamp:(uint64_t)readTimestamp - sendReadReceipt:(BOOL)sendReadReceipt + trySendReadReceipt:(BOOL)trySendReadReceipt transaction:(YapDatabaseReadWriteTransaction *)transaction { if (_read) { @@ -144,7 +144,7 @@ NSUInteger TSInfoMessageSchemaVersion = 1; _read = YES; [self saveWithTransaction:transaction]; - // Ignore sendReadReceipt, it doesn't apply to info messages. + // Ignore trySendReadReceipt, it doesn't apply to info messages. } @end diff --git a/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift b/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift index de65ce5cf..ec7d226e6 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageReceiver+Handling.swift @@ -390,7 +390,7 @@ extension MessageReceiver { if let tsOutgoingMessage = TSMessage.fetch(uniqueId: tsMessageID, transaction: transaction) as? TSOutgoingMessage, let thread = TSThread.fetch(uniqueId: threadID, transaction: transaction) { // Mark previous messages as read if there is a sync message - OWSReadReceiptManager.shared().markAsReadLocally(beforeSortId: tsOutgoingMessage.sortId, thread: thread) + OWSReadReceiptManager.shared().markAsReadLocally(beforeSortId: tsOutgoingMessage.sortId, thread: thread, trySendReadReceipt: true) } // Update the contact's approval status of the current user if needed (if we are getting messages from diff --git a/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadReceiptManager.h b/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadReceiptManager.h index d2c07812b..c2dfddec5 100644 --- a/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadReceiptManager.h +++ b/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadReceiptManager.h @@ -45,7 +45,7 @@ extern NSString *const kIncomingMessageMarkedAsReadNotification; // This method can be called from any thread. - (void)messageWasReadLocally:(TSIncomingMessage *)message; -- (void)markAsReadLocallyBeforeSortId:(uint64_t)sortId thread:(TSThread *)thread; +- (void)markAsReadLocallyBeforeSortId:(uint64_t)sortId thread:(TSThread *)thread trySendReadReceipt:(BOOL)trySendReadReceipt; #pragma mark - Settings diff --git a/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadReceiptManager.m b/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadReceiptManager.m index 13a1b39c2..4517e2be4 100644 --- a/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadReceiptManager.m +++ b/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadReceiptManager.m @@ -180,13 +180,13 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE #pragma mark - Mark as Read Locally -- (void)markAsReadLocallyBeforeSortId:(uint64_t)sortId thread:(TSThread *)thread +- (void)markAsReadLocallyBeforeSortId:(uint64_t)sortId thread:(TSThread *)thread trySendReadReceipt:(BOOL)trySendReadReceipt { [LKStorage writeWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { [self markAsReadBeforeSortId:sortId thread:thread readTimestamp:[NSDate millisecondTimestamp] - wasLocal:YES + trySendReadReceipt:trySendReadReceipt transaction:transaction]; }]; } @@ -254,7 +254,7 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE - (void)markAsReadBeforeSortId:(uint64_t)sortId thread:(TSThread *)thread readTimestamp:(uint64_t)readTimestamp - wasLocal:(BOOL)wasLocal + trySendReadReceipt:(BOOL)trySendReadReceipt transaction:(YapDatabaseReadWriteTransaction *)transaction { NSMutableArray> *newlyReadList = [NSMutableArray new]; @@ -285,7 +285,7 @@ NSString *const OWSReadReceiptManagerAreReadReceiptsEnabled = @"areReadReceiptsE } for (id readItem in newlyReadList) { - [readItem markAsReadAtTimestamp:readTimestamp sendReadReceipt:wasLocal transaction:transaction]; + [readItem markAsReadAtTimestamp:readTimestamp trySendReadReceipt:trySendReadReceipt transaction:transaction]; } } diff --git a/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadTracking.h b/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadTracking.h index d8afaaa41..b08071959 100644 --- a/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadTracking.h +++ b/SessionMessagingKit/Sending & Receiving/Read Tracking/OWSReadTracking.h @@ -29,7 +29,7 @@ NS_ASSUME_NONNULL_BEGIN * Used both for *responding* to a remote read receipt and in response to the local user's activity. */ - (void)markAsReadAtTimestamp:(uint64_t)readTimestamp - sendReadReceipt:(BOOL)sendReadReceipt + trySendReadReceipt:(BOOL)trySendReadReceipt transaction:(YapDatabaseReadWriteTransaction *)transaction; @end diff --git a/SessionMessagingKit/Threads/TSThread.m b/SessionMessagingKit/Threads/TSThread.m index 91484bba7..00049a305 100644 --- a/SessionMessagingKit/Threads/TSThread.m +++ b/SessionMessagingKit/Threads/TSThread.m @@ -309,7 +309,7 @@ BOOL IsNoteToSelfEnabled(void) - (void)markAllAsReadWithTransaction:(YapDatabaseReadWriteTransaction *)transaction { for (id message in [self unseenMessagesWithTransaction:transaction]) { - [message markAsReadAtTimestamp:[NSDate ows_millisecondTimeStamp] sendReadReceipt:YES transaction:transaction]; + [message markAsReadAtTimestamp:[NSDate ows_millisecondTimeStamp] trySendReadReceipt:YES transaction:transaction]; } } diff --git a/SignalUtilitiesKit/Messaging/OWSMessageUtils.h b/SignalUtilitiesKit/Messaging/OWSMessageUtils.h index ef693b8dc..3069360bf 100644 --- a/SignalUtilitiesKit/Messaging/OWSMessageUtils.h +++ b/SignalUtilitiesKit/Messaging/OWSMessageUtils.h @@ -16,6 +16,7 @@ NS_ASSUME_NONNULL_BEGIN + (instancetype)sharedManager; - (NSUInteger)unreadMessagesCount; +- (NSUInteger)unreadMessageRequestCount; - (NSUInteger)unreadMessagesCountExcept:(TSThread *)thread; - (void)updateApplicationBadgeCount; diff --git a/SignalUtilitiesKit/Messaging/OWSMessageUtils.m b/SignalUtilitiesKit/Messaging/OWSMessageUtils.m index fe8d0a4d1..b07a80bf8 100644 --- a/SignalUtilitiesKit/Messaging/OWSMessageUtils.m +++ b/SignalUtilitiesKit/Messaging/OWSMessageUtils.m @@ -112,6 +112,38 @@ NS_ASSUME_NONNULL_BEGIN return numberOfItems; } +- (NSUInteger)unreadMessageRequestCount { + __block NSUInteger count = 0; + + [LKStorage readWithBlock:^(YapDatabaseReadTransaction *transaction) { + YapDatabaseViewTransaction *unreadMessages = [transaction ext:TSUnreadDatabaseViewExtensionName]; + NSArray *allGroups = [unreadMessages allGroups]; + // FIXME: Confusingly, `allGroups` includes contact threads as well + for (NSString *groupID in allGroups) { + TSThread *thread = [TSThread fetchObjectWithUniqueID:groupID transaction:transaction]; + + // Only increase the count for message requests + if (!thread.isMessageRequest) { continue; } + + [unreadMessages enumerateKeysAndObjectsInGroup:groupID + usingBlock:^(NSString *collection, NSString *key, id object, NSUInteger index, BOOL *stop) { + if (![object conformsToProtocol:@protocol(OWSReadTracking)]) { + return; + } + id unread = (id)object; + if (unread.read) { + NSLog(@"Found an already read message in the * unread * messages list."); + return; + } + count += 1; + *stop = YES; + }]; + } + }]; + + return count; +} + - (NSUInteger)unreadMessagesCountExcept:(TSThread *)thread { __block NSUInteger numberOfItems; From bdaae2b3470e64feae7e4ba5482b149747a2e8d1 Mon Sep 17 00:00:00 2001 From: Morgan Pretty Date: Wed, 2 Mar 2022 10:06:46 +1100 Subject: [PATCH 7/8] Moved the copy for the message request approval error into Localizable.strings --- Session/Conversations/ConversationVC+Interaction.swift | 4 ++-- Session/Meta/Translations/de.lproj/Localizable.strings | 1 + Session/Meta/Translations/en.lproj/Localizable.strings | 1 + Session/Meta/Translations/es.lproj/Localizable.strings | 1 + Session/Meta/Translations/fa.lproj/Localizable.strings | 1 + Session/Meta/Translations/fi.lproj/Localizable.strings | 1 + Session/Meta/Translations/fr.lproj/Localizable.strings | 1 + Session/Meta/Translations/hi.lproj/Localizable.strings | 1 + Session/Meta/Translations/hr.lproj/Localizable.strings | 1 + Session/Meta/Translations/id-ID.lproj/Localizable.strings | 1 + Session/Meta/Translations/it.lproj/Localizable.strings | 1 + Session/Meta/Translations/ja.lproj/Localizable.strings | 1 + Session/Meta/Translations/nl.lproj/Localizable.strings | 1 + Session/Meta/Translations/pl.lproj/Localizable.strings | 1 + Session/Meta/Translations/pt_BR.lproj/Localizable.strings | 1 + Session/Meta/Translations/ru.lproj/Localizable.strings | 1 + Session/Meta/Translations/si.lproj/Localizable.strings | 1 + Session/Meta/Translations/sk.lproj/Localizable.strings | 1 + Session/Meta/Translations/sv.lproj/Localizable.strings | 1 + Session/Meta/Translations/th.lproj/Localizable.strings | 1 + Session/Meta/Translations/vi-VN.lproj/Localizable.strings | 1 + Session/Meta/Translations/zh-Hant.lproj/Localizable.strings | 1 + Session/Meta/Translations/zh_CN.lproj/Localizable.strings | 1 + 23 files changed, 24 insertions(+), 2 deletions(-) diff --git a/Session/Conversations/ConversationVC+Interaction.swift b/Session/Conversations/ConversationVC+Interaction.swift index 8dd7cef14..82cb5afe7 100644 --- a/Session/Conversations/ConversationVC+Interaction.swift +++ b/Session/Conversations/ConversationVC+Interaction.swift @@ -1221,8 +1221,8 @@ extension ConversationVC { // Show an error indicating that approving the thread failed promise.catch(on: DispatchQueue.main) { [weak self] _ in - let alert = UIAlertController(title: "Session", message: "An error occurred when trying to accept this message request", preferredStyle: .alert) - alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) + let alert = UIAlertController(title: "Session", message: NSLocalizedString("MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE", comment: ""), preferredStyle: .alert) + alert.addAction(UIAlertAction(title: NSLocalizedString("BUTTON_OK", comment: ""), style: .default, handler: nil)) self?.present(alert, animated: true, completion: nil) } diff --git a/Session/Meta/Translations/de.lproj/Localizable.strings b/Session/Meta/Translations/de.lproj/Localizable.strings index 8f96b9859..8d14299fe 100644 --- a/Session/Meta/Translations/de.lproj/Localizable.strings +++ b/Session/Meta/Translations/de.lproj/Localizable.strings @@ -609,6 +609,7 @@ "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; +"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request"; "MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request."; "MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted."; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; diff --git a/Session/Meta/Translations/en.lproj/Localizable.strings b/Session/Meta/Translations/en.lproj/Localizable.strings index b3fe25911..dd2dc4c0a 100644 --- a/Session/Meta/Translations/en.lproj/Localizable.strings +++ b/Session/Meta/Translations/en.lproj/Localizable.strings @@ -619,6 +619,7 @@ "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; +"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request"; "MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request."; "MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted."; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; diff --git a/Session/Meta/Translations/es.lproj/Localizable.strings b/Session/Meta/Translations/es.lproj/Localizable.strings index 0e9317aec..e2cae0af0 100644 --- a/Session/Meta/Translations/es.lproj/Localizable.strings +++ b/Session/Meta/Translations/es.lproj/Localizable.strings @@ -609,6 +609,7 @@ "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; +"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request"; "MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request."; "MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted."; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; diff --git a/Session/Meta/Translations/fa.lproj/Localizable.strings b/Session/Meta/Translations/fa.lproj/Localizable.strings index 8574b6a04..afb0b7aa5 100644 --- a/Session/Meta/Translations/fa.lproj/Localizable.strings +++ b/Session/Meta/Translations/fa.lproj/Localizable.strings @@ -609,6 +609,7 @@ "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; +"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request"; "MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request."; "MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted."; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; diff --git a/Session/Meta/Translations/fi.lproj/Localizable.strings b/Session/Meta/Translations/fi.lproj/Localizable.strings index 1d7471f51..a7c91659e 100644 --- a/Session/Meta/Translations/fi.lproj/Localizable.strings +++ b/Session/Meta/Translations/fi.lproj/Localizable.strings @@ -609,6 +609,7 @@ "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; +"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request"; "MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request."; "MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted."; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; diff --git a/Session/Meta/Translations/fr.lproj/Localizable.strings b/Session/Meta/Translations/fr.lproj/Localizable.strings index a6b214ceb..b6f603107 100644 --- a/Session/Meta/Translations/fr.lproj/Localizable.strings +++ b/Session/Meta/Translations/fr.lproj/Localizable.strings @@ -609,6 +609,7 @@ "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; +"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request"; "MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request."; "MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted."; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; diff --git a/Session/Meta/Translations/hi.lproj/Localizable.strings b/Session/Meta/Translations/hi.lproj/Localizable.strings index f8c56eb4f..ad5464361 100644 --- a/Session/Meta/Translations/hi.lproj/Localizable.strings +++ b/Session/Meta/Translations/hi.lproj/Localizable.strings @@ -609,6 +609,7 @@ "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; +"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request"; "MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request."; "MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted."; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; diff --git a/Session/Meta/Translations/hr.lproj/Localizable.strings b/Session/Meta/Translations/hr.lproj/Localizable.strings index 800c669ca..274c1409f 100644 --- a/Session/Meta/Translations/hr.lproj/Localizable.strings +++ b/Session/Meta/Translations/hr.lproj/Localizable.strings @@ -609,6 +609,7 @@ "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; +"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request"; "MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request."; "MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted."; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; diff --git a/Session/Meta/Translations/id-ID.lproj/Localizable.strings b/Session/Meta/Translations/id-ID.lproj/Localizable.strings index 6974734bd..51a2ce572 100644 --- a/Session/Meta/Translations/id-ID.lproj/Localizable.strings +++ b/Session/Meta/Translations/id-ID.lproj/Localizable.strings @@ -609,6 +609,7 @@ "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; +"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request"; "MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request."; "MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted."; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; diff --git a/Session/Meta/Translations/it.lproj/Localizable.strings b/Session/Meta/Translations/it.lproj/Localizable.strings index 540cdb2b0..94b106407 100644 --- a/Session/Meta/Translations/it.lproj/Localizable.strings +++ b/Session/Meta/Translations/it.lproj/Localizable.strings @@ -609,6 +609,7 @@ "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; +"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request"; "MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request."; "MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted."; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; diff --git a/Session/Meta/Translations/ja.lproj/Localizable.strings b/Session/Meta/Translations/ja.lproj/Localizable.strings index e1ca6cc61..669895da7 100644 --- a/Session/Meta/Translations/ja.lproj/Localizable.strings +++ b/Session/Meta/Translations/ja.lproj/Localizable.strings @@ -609,6 +609,7 @@ "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; +"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request"; "MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request."; "MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted."; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; diff --git a/Session/Meta/Translations/nl.lproj/Localizable.strings b/Session/Meta/Translations/nl.lproj/Localizable.strings index 081045a66..5dc78f656 100644 --- a/Session/Meta/Translations/nl.lproj/Localizable.strings +++ b/Session/Meta/Translations/nl.lproj/Localizable.strings @@ -609,6 +609,7 @@ "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; +"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request"; "MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request."; "MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted."; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; diff --git a/Session/Meta/Translations/pl.lproj/Localizable.strings b/Session/Meta/Translations/pl.lproj/Localizable.strings index 7602b2a50..0b5bc1226 100644 --- a/Session/Meta/Translations/pl.lproj/Localizable.strings +++ b/Session/Meta/Translations/pl.lproj/Localizable.strings @@ -609,6 +609,7 @@ "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; +"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request"; "MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request."; "MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted."; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; diff --git a/Session/Meta/Translations/pt_BR.lproj/Localizable.strings b/Session/Meta/Translations/pt_BR.lproj/Localizable.strings index 62cfa2db2..4973175a1 100644 --- a/Session/Meta/Translations/pt_BR.lproj/Localizable.strings +++ b/Session/Meta/Translations/pt_BR.lproj/Localizable.strings @@ -609,6 +609,7 @@ "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; +"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request"; "MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request."; "MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted."; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; diff --git a/Session/Meta/Translations/ru.lproj/Localizable.strings b/Session/Meta/Translations/ru.lproj/Localizable.strings index e47932db1..4388acc6e 100644 --- a/Session/Meta/Translations/ru.lproj/Localizable.strings +++ b/Session/Meta/Translations/ru.lproj/Localizable.strings @@ -609,6 +609,7 @@ "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; +"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request"; "MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request."; "MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted."; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; diff --git a/Session/Meta/Translations/si.lproj/Localizable.strings b/Session/Meta/Translations/si.lproj/Localizable.strings index 7f4297832..d29e33206 100644 --- a/Session/Meta/Translations/si.lproj/Localizable.strings +++ b/Session/Meta/Translations/si.lproj/Localizable.strings @@ -610,6 +610,7 @@ "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; +"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request"; "MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request."; "MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted."; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; diff --git a/Session/Meta/Translations/sk.lproj/Localizable.strings b/Session/Meta/Translations/sk.lproj/Localizable.strings index 8c46a741b..c595f40ac 100644 --- a/Session/Meta/Translations/sk.lproj/Localizable.strings +++ b/Session/Meta/Translations/sk.lproj/Localizable.strings @@ -609,6 +609,7 @@ "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; +"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request"; "MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request."; "MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted."; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; diff --git a/Session/Meta/Translations/sv.lproj/Localizable.strings b/Session/Meta/Translations/sv.lproj/Localizable.strings index 9f4917279..a6c77c0b9 100644 --- a/Session/Meta/Translations/sv.lproj/Localizable.strings +++ b/Session/Meta/Translations/sv.lproj/Localizable.strings @@ -609,6 +609,7 @@ "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; +"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request"; "MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request."; "MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted."; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; diff --git a/Session/Meta/Translations/th.lproj/Localizable.strings b/Session/Meta/Translations/th.lproj/Localizable.strings index 3ee9c078d..445668fec 100644 --- a/Session/Meta/Translations/th.lproj/Localizable.strings +++ b/Session/Meta/Translations/th.lproj/Localizable.strings @@ -609,6 +609,7 @@ "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; +"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request"; "MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request."; "MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted."; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; diff --git a/Session/Meta/Translations/vi-VN.lproj/Localizable.strings b/Session/Meta/Translations/vi-VN.lproj/Localizable.strings index 5a0131436..a68dda3ec 100644 --- a/Session/Meta/Translations/vi-VN.lproj/Localizable.strings +++ b/Session/Meta/Translations/vi-VN.lproj/Localizable.strings @@ -609,6 +609,7 @@ "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; +"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request"; "MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request."; "MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted."; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; diff --git a/Session/Meta/Translations/zh-Hant.lproj/Localizable.strings b/Session/Meta/Translations/zh-Hant.lproj/Localizable.strings index 4c9fc2786..14c99a466 100644 --- a/Session/Meta/Translations/zh-Hant.lproj/Localizable.strings +++ b/Session/Meta/Translations/zh-Hant.lproj/Localizable.strings @@ -609,6 +609,7 @@ "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; +"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request"; "MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request."; "MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted."; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; diff --git a/Session/Meta/Translations/zh_CN.lproj/Localizable.strings b/Session/Meta/Translations/zh_CN.lproj/Localizable.strings index 0d09f4d0e..e32e365b9 100644 --- a/Session/Meta/Translations/zh_CN.lproj/Localizable.strings +++ b/Session/Meta/Translations/zh_CN.lproj/Localizable.strings @@ -609,6 +609,7 @@ "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_TITLE" = "Are you sure you want to clear all message requests?"; "MESSAGE_REQUESTS_CLEAR_ALL_CONFIRMATION_ACTON" = "Clear"; "MESSAGE_REQUESTS_DELETE_CONFIRMATION_ACTON" = "Are you sure you want to delete this message request?"; +"MESSAGE_REQUESTS_APPROVAL_ERROR_MESSAGE" = "An error occurred when trying to accept this message request"; "MESSAGE_REQUESTS_INFO" = "Sending a message to this user will automatically accept their message request."; "MESSAGE_REQUESTS_ACCEPTED" = "Your message request has been accepted."; "MESSAGE_REQUESTS_NOTIFICATION" = "You have a new message request"; From 167d68870a7a43204488e611f91296db78c14fb9 Mon Sep 17 00:00:00 2001 From: Ryan Zhao Date: Wed, 2 Mar 2022 10:50:15 +1100 Subject: [PATCH 8/8] show conversation settings button after approving message requests --- Session/Conversations/ConversationVC+Interaction.swift | 3 +++ Session/Home/HomeVC.swift | 1 + 2 files changed, 4 insertions(+) diff --git a/Session/Conversations/ConversationVC+Interaction.swift b/Session/Conversations/ConversationVC+Interaction.swift index 82cb5afe7..15e3cfdae 100644 --- a/Session/Conversations/ConversationVC+Interaction.swift +++ b/Session/Conversations/ConversationVC+Interaction.swift @@ -1201,6 +1201,9 @@ extension ConversationVC { ) } } + + // Update UI + self?.updateNavBarButtons() // Send a sync message with the details of the contact if let appDelegate = UIApplication.shared.delegate as? AppDelegate { diff --git a/Session/Home/HomeVC.swift b/Session/Home/HomeVC.swift index fb307db18..bea05f1f0 100644 --- a/Session/Home/HomeVC.swift +++ b/Session/Home/HomeVC.swift @@ -563,6 +563,7 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv @objc private func openSettings() { let settingsVC = SettingsVC() let navigationController = OWSNavigationController(rootViewController: settingsVC) + navigationController.modalPresentationStyle = .fullScreen present(navigationController, animated: true, completion: nil) }