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)
pull/567/head
Morgan Pretty 2 years ago
parent f8c0700ba0
commit e6b941ea8a

@ -10,6 +10,16 @@ extension ConversationVC : InputViewDelegate, MessageCellDelegate, ContextMenuAc
ConversationTitleViewDelegate { ConversationTitleViewDelegate {
func handleTitleViewTapped() { 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() openSettings()
} }
@ -292,32 +302,56 @@ extension ConversationVC : InputViewDelegate, MessageCellDelegate, ContextMenuAc
func sendAttachments(_ attachments: [SignalAttachment], with text: String, onComplete: (() -> ())? = nil) { func sendAttachments(_ attachments: [SignalAttachment], with text: String, onComplete: (() -> ())? = nil) {
guard !showBlockedModalIfNeeded() else { return } guard !showBlockedModalIfNeeded() else { return }
for attachment in attachments { for attachment in attachments {
if attachment.hasError { if attachment.hasError {
return showErrorAlert(for: attachment, onDismiss: onComplete) return showErrorAlert(for: attachment, onDismiss: onComplete)
} }
} }
let thread = self.thread let thread = self.thread
let sentTimestamp: UInt64 = NSDate.millisecondTimestamp()
let message = VisibleMessage() let message = VisibleMessage()
message.sentTimestamp = NSDate.millisecondTimestamp() message.sentTimestamp = sentTimestamp
message.text = replaceMentions(in: text) 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) let tsMessage = TSOutgoingMessage.from(message, associatedWith: thread)
Storage.write(with: { transaction in
tsMessage.save(with: transaction) Storage.write(
// The new message cell is inserted at this point, but the TSOutgoingMessage doesn't have its attachment yet with: { transaction in
}, completion: { [weak self] in tsMessage.save(with: transaction)
Storage.write(with: { transaction in // The new message cell is inserted at this point, but the TSOutgoingMessage doesn't have its attachment yet
MessageSender.send(message, with: attachments, in: thread, using: transaction) },
}, completion: { [weak self] in completion: { [weak self] in
// At this point the TSOutgoingMessage should have its attachments set, so we can scroll to the bottom knowing Storage.shared.write(
// the height of the new message cell with: { transaction in
self?.scrollToBottom(isAnimated: false) self?.approveMessageRequestIfNeeded(
}) for: self?.thread,
self?.handleMessageSent() with: (transaction as! YapDatabaseReadWriteTransaction),
isNewThread: !oldThreadShouldBeVisible,
// Attachment successfully sent - dismiss the screen timestamp: (sentTimestamp - 1) // Set 1ms earlier as this is used for sorting
onComplete?() )
}) },
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() { func handleMessageSent() {

@ -1,5 +1,6 @@
import SessionUIKit import SessionUIKit
import SessionMessagingKit import SessionMessagingKit
import UIKit
// TODO: // TODO:
// Slight paging glitch when scrolling up and loading more content // Slight paging glitch when scrolling up and loading more content
@ -465,30 +466,53 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, OWSConversat
// MARK: Updating // MARK: Updating
func updateNavBarButtons() { 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 { if isShowingSearchUI {
navigationItem.leftBarButtonItem = nil navigationItem.leftBarButtonItem = nil
navigationItem.rightBarButtonItems = [] navigationItem.rightBarButtonItems = []
} else { }
else {
navigationItem.hidesBackButton = false
navigationItem.leftBarButtonItem = UIViewController.createOWSBackButton(withTarget: self, selector: #selector(handleBackPressed)) navigationItem.leftBarButtonItem = UIViewController.createOWSBackButton(withTarget: self, selector: #selector(handleBackPressed))
let rightBarButtonItem: UIBarButtonItem if let contactThread: TSContactThread = thread as? TSContactThread {
if thread is TSContactThread { // Don't show the settings button for message requests
let size = Values.verySmallProfilePictureSize if let contact: Contact = Storage.shared.getContact(with: contactThread.contactSessionID()), contact.isApproved, contact.didApproveMe {
let profilePictureView = ProfilePictureView() let size = Values.verySmallProfilePictureSize
profilePictureView.accessibilityLabel = "Settings button" let profilePictureView = ProfilePictureView()
profilePictureView.size = size profilePictureView.size = size
profilePictureView.update(for: thread) profilePictureView.update(for: thread)
profilePictureView.set(.width, to: size) profilePictureView.set(.width, to: size)
profilePictureView.set(.height, to: size) profilePictureView.set(.height, to: size)
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(openSettings))
profilePictureView.addGestureRecognizer(tapGestureRecognizer) let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(openSettings))
rightBarButtonItem = UIBarButtonItem(customView: profilePictureView) profilePictureView.addGestureRecognizer(tapGestureRecognizer)
} else {
rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "Gear"), style: .plain, target: self, action: #selector(openSettings)) 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 let searchBar = searchController.uiSearchController.searchBar
searchBar.searchBarStyle = .minimal searchBar.searchBarStyle = .minimal
searchBar.barStyle = .black searchBar.barStyle = .black
searchBar.tintColor = Colors.accent searchBar.tintColor = Colors.text
let searchIcon = UIImage(named: "searchbar_search")!.asTintedImage(color: Colors.searchBarPlaceholder) let searchIcon = UIImage(named: "searchbar_search")!.asTintedImage(color: Colors.searchBarPlaceholder)
searchBar.setImage(searchIcon, for: .search, state: UIControl.State.normal) searchBar.setImage(searchIcon, for: .search, state: UIControl.State.normal)
let clearIcon = UIImage(named: "searchbar_clear")!.asTintedImage(color: Colors.searchBarPlaceholder) let clearIcon = UIImage(named: "searchbar_clear")!.asTintedImage(color: Colors.searchBarPlaceholder)

@ -277,7 +277,7 @@ CGFloat kIconViewLength = 24;
contents.title = NSLocalizedString(@"CONVERSATION_SETTINGS", @"title for conversation settings screen"); contents.title = NSLocalizedString(@"CONVERSATION_SETTINGS", @"title for conversation settings screen");
BOOL isNoteToSelf = self.thread.isNoteToSelf; BOOL isNoteToSelf = self.thread.isNoteToSelf;
__weak OWSConversationSettingsViewController *weakSelf = self; __weak OWSConversationSettingsViewController *weakSelf = self;
OWSTableSection *section = [OWSTableSection new]; OWSTableSection *section = [OWSTableSection new];
@ -332,7 +332,7 @@ CGFloat kIconViewLength = 24;
} actionBlock:^{ } actionBlock:^{
[weakSelf tappedConversationSearch]; [weakSelf tappedConversationSearch];
}]]; }]];
// Disappearing messages // Disappearing messages
if (![self isOpenGroup]) { if (![self isOpenGroup]) {
[section addItem:[OWSTableItem itemWithCustomCellBlock:^{ [section addItem:[OWSTableItem itemWithCustomCellBlock:^{
@ -358,13 +358,6 @@ CGFloat kIconViewLength = 24;
switchView.on = strongSelf.disappearingMessagesConfiguration.isEnabled; switchView.on = strongSelf.disappearingMessagesConfiguration.isEnabled;
[switchView addTarget:strongSelf action:@selector(disappearingMessagesSwitchValueDidChange:) [switchView addTarget:strongSelf action:@selector(disappearingMessagesSwitchValueDidChange:)
forControlEvents:UIControlEventValueChanged]; 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 *topRow =
[[UIStackView alloc] initWithArrangedSubviews:@[ iconView, rowLabel, switchView ]]; [[UIStackView alloc] initWithArrangedSubviews:@[ iconView, rowLabel, switchView ]];
@ -438,13 +431,6 @@ CGFloat kIconViewLength = 24;
[slider autoPinTrailingToSuperviewMargin]; [slider autoPinTrailingToSuperviewMargin];
[slider autoPinBottomToSuperviewMargin]; [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.userInteractionEnabled = !strongSelf.hasLeftGroup;
cell.accessibilityIdentifier = ACCESSIBILITY_IDENTIFIER_WITH_NAME( cell.accessibilityIdentifier = ACCESSIBILITY_IDENTIFIER_WITH_NAME(

@ -73,13 +73,17 @@ final class ConversationTitleView : UIView {
private func getTitle() -> String { private func getTitle() -> String {
if let thread = thread as? TSGroupThread { if let thread = thread as? TSGroupThread {
return thread.groupModel.groupName! return thread.groupModel.groupName!
} else if thread.isNoteToSelf() { }
else if thread.isNoteToSelf() {
return "Note to Self" return "Note to Self"
} else { }
else {
let sessionID = (thread as! TSContactThread).contactSessionID() let sessionID = (thread as! TSContactThread).contactSessionID()
var result = sessionID var result = sessionID
Storage.read { transaction in 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 return result
} }

@ -393,11 +393,18 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv
profilePictureViewContainer.addSubview(pathStatusView) profilePictureViewContainer.addSubview(pathStatusView)
pathStatusView.pin(.trailing, to: .trailing, of: profilePictureViewContainer) pathStatusView.pin(.trailing, to: .trailing, of: profilePictureViewContainer)
pathStatusView.pin(.bottom, to: .bottom, 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 // Left bar button item
let leftBarButtonItem = UIBarButtonItem(customView: profilePictureViewContainer) let leftBarButtonItem = UIBarButtonItem(customView: profilePictureViewContainer)
leftBarButtonItem.accessibilityLabel = "Settings button" leftBarButtonItem.accessibilityLabel = "Settings button"
leftBarButtonItem.isAccessibilityElement = true leftBarButtonItem.isAccessibilityElement = true
navigationItem.leftBarButtonItem = leftBarButtonItem navigationItem.leftBarButtonItem = leftBarButtonItem
// Right bar button item - search button // Right bar button item - search button
let rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .search, target: self, action: #selector(showSearchUI)) let rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .search, target: self, action: #selector(showSearchUI))
rightBarButtonItem.accessibilityLabel = "Search button" rightBarButtonItem.accessibilityLabel = "Search button"

@ -63,23 +63,16 @@ class MessageRequestsViewController: BaseVC, UITableViewDelegate, UITableViewDat
return result return result
}() }()
private lazy var clearAllButton: UIButton = { private lazy var clearAllButton: Button = {
let result: UIButton = UIButton() let result: Button = Button(style: .destructiveOutline, size: .large)
result.translatesAutoresizingMaskIntoConstraints = false result.translatesAutoresizingMaskIntoConstraints = false
result.clipsToBounds = true
result.titleLabel?.font = UIFont.boldSystemFont(ofSize: 18)
result.setTitle(NSLocalizedString("MESSAGE_REQUESTS_CLEAR_ALL", comment: ""), for: .normal) result.setTitle(NSLocalizedString("MESSAGE_REQUESTS_CLEAR_ALL", comment: ""), for: .normal)
result.setTitleColor(Colors.destructive, for: .normal)
result.setBackgroundImage( result.setBackgroundImage(
Colors.destructive Colors.destructive
.withAlphaComponent(isDarkMode ? 0.2 : 0.06) .withAlphaComponent(isDarkMode ? 0.2 : 0.06)
.toImage(isDarkMode: isDarkMode), .toImage(isDarkMode: isDarkMode),
for: .highlighted 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) result.addTarget(self, action: #selector(clearAllTapped), for: .touchUpInside)
return result return result
@ -163,10 +156,11 @@ class MessageRequestsViewController: BaseVC, UITableViewDelegate, UITableViewDat
clearAllButton.centerXAnchor.constraint(equalTo: view.centerXAnchor), clearAllButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
clearAllButton.bottomAnchor.constraint( clearAllButton.bottomAnchor.constraint(
equalTo: view.bottomAnchor, equalTo: view.safeAreaLayoutGuide.bottomAnchor,
constant: -Values.newConversationButtonBottomOffset // Negative due to how the constraint is set up 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) clearAllButton.heightAnchor.constraint(equalToConstant: NewConversationButtonSet.collapsedButtonSize)
]) ])
} }

@ -76,7 +76,7 @@ class MessageRequestsCell: UITableViewCell {
}() }()
private func setUpViewHierarchy() { private func setUpViewHierarchy() {
backgroundColor = Colors.cellBackground backgroundColor = Colors.cellPinned
selectedBackgroundView = UIView() selectedBackgroundView = UIView()
selectedBackgroundView?.backgroundColor = Colors.cellSelected selectedBackgroundView?.backgroundColor = Colors.cellSelected

@ -139,7 +139,7 @@ final class SettingsVC : BaseVC, AvatarViewHelperDelegate {
setUpNavBarStyle() setUpNavBarStyle()
setNavBarTitle(NSLocalizedString("vc_settings_title", comment: "")) setNavBarTitle(NSLocalizedString("vc_settings_title", comment: ""))
// Navigation bar buttons // 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 backButton.tintColor = Colors.text
navigationItem.backBarButtonItem = backButton navigationItem.backBarButtonItem = backButton
updateNavigationBarButtons() updateNavigationBarButtons()
@ -254,8 +254,6 @@ final class SettingsVC : BaseVC, AvatarViewHelperDelegate {
pathStatusView.pin(.leading, to: .trailing, of: pathButton.titleLabel!, withInset: Values.smallSpacing) pathStatusView.pin(.leading, to: .trailing, of: pathButton.titleLabel!, withInset: Values.smallSpacing)
pathStatusView.autoVCenterInSuperview() pathStatusView.autoVCenterInSuperview()
pathButton.titleEdgeInsets = UIEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: Values.smallSpacing)
return [ return [
getSeparator(), getSeparator(),
pathButton, pathButton,

@ -358,15 +358,20 @@ final class ConversationCell : UITableViewCell {
if threadViewModel.isGroupThread { if threadViewModel.isGroupThread {
if threadViewModel.name.isEmpty { if threadViewModel.name.isEmpty {
return "Unknown Group" return "Unknown Group"
} else { }
else {
return threadViewModel.name return threadViewModel.name
} }
} else { }
else {
if threadViewModel.threadRecord.isNoteToSelf() { if threadViewModel.threadRecord.isNoteToSelf() {
return NSLocalizedString("NOTE_TO_SELF", comment: "") return NSLocalizedString("NOTE_TO_SELF", comment: "")
} else { }
let hexEncodedPublicKey = threadViewModel.contactSessionID! else {
return Storage.shared.getContact(with: hexEncodedPublicKey)?.displayName(for: .regular) ?? hexEncodedPublicKey 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)
} }
} }
} }

@ -6,7 +6,7 @@ public final class Button : UIButton {
private var heightConstraint: NSLayoutConstraint! private var heightConstraint: NSLayoutConstraint!
public enum Style { public enum Style {
case unimportant, regular, prominentOutline, prominentFilled, regularBorderless case unimportant, regular, prominentOutline, prominentFilled, regularBorderless, destructiveOutline
} }
public enum Size { public enum Size {
@ -41,6 +41,7 @@ public final class Button : UIButton {
case .prominentOutline: fillColor = UIColor.clear case .prominentOutline: fillColor = UIColor.clear
case .prominentFilled: fillColor = isLightMode ? Colors.text : Colors.accent case .prominentFilled: fillColor = isLightMode ? Colors.text : Colors.accent
case .regularBorderless: fillColor = UIColor.clear case .regularBorderless: fillColor = UIColor.clear
case .destructiveOutline: fillColor = UIColor.clear
} }
let borderColor: UIColor let borderColor: UIColor
switch style { switch style {
@ -49,6 +50,7 @@ public final class Button : UIButton {
case .prominentOutline: borderColor = isLightMode ? Colors.text : Colors.accent case .prominentOutline: borderColor = isLightMode ? Colors.text : Colors.accent
case .prominentFilled: borderColor = isLightMode ? Colors.text : Colors.accent case .prominentFilled: borderColor = isLightMode ? Colors.text : Colors.accent
case .regularBorderless: borderColor = UIColor.clear case .regularBorderless: borderColor = UIColor.clear
case .destructiveOutline: borderColor = Colors.destructive
} }
let textColor: UIColor let textColor: UIColor
switch style { switch style {
@ -57,6 +59,7 @@ public final class Button : UIButton {
case .prominentOutline: textColor = isLightMode ? Colors.text : Colors.accent case .prominentOutline: textColor = isLightMode ? Colors.text : Colors.accent
case .prominentFilled: textColor = isLightMode ? UIColor.white : Colors.text case .prominentFilled: textColor = isLightMode ? UIColor.white : Colors.text
case .regularBorderless: textColor = Colors.text case .regularBorderless: textColor = Colors.text
case .destructiveOutline: textColor = Colors.destructive
} }
let height: CGFloat let height: CGFloat
switch size { switch size {

@ -28,7 +28,7 @@ public final class ViewControllerUtilities : NSObject {
} }
// Set up back button // Set up back button
if hasCustomBackButton { 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 backButton.tintColor = Colors.text
vc.navigationItem.backBarButtonItem = backButton vc.navigationItem.backBarButtonItem = backButton
} }

Loading…
Cancel
Save