From 5c05fbbbb67071cd59cd6b6cdc355f63671ca31f Mon Sep 17 00:00:00 2001 From: Morgan Pretty Date: Mon, 16 Jan 2023 15:46:51 +1100 Subject: [PATCH 1/4] Added the updated delivery status UI Updated the create closed group screen to cancel the search field when tapping outside of it (previously required tapping the cancel button) --- Session/Closed Groups/NewClosedGroupVC.swift | 23 +++++++++-- .../Message Cells/VisibleMessageCell.swift | 38 ++++++++++++++++--- .../Translations/de.lproj/Localizable.strings | 4 ++ .../Translations/en.lproj/Localizable.strings | 4 ++ .../Translations/es.lproj/Localizable.strings | 4 ++ .../Translations/fa.lproj/Localizable.strings | 4 ++ .../Translations/fi.lproj/Localizable.strings | 4 ++ .../Translations/fr.lproj/Localizable.strings | 4 ++ .../Translations/hi.lproj/Localizable.strings | 4 ++ .../Translations/hr.lproj/Localizable.strings | 4 ++ .../id-ID.lproj/Localizable.strings | 4 ++ .../Translations/it.lproj/Localizable.strings | 4 ++ .../Translations/ja.lproj/Localizable.strings | 4 ++ .../Translations/nl.lproj/Localizable.strings | 4 ++ .../Translations/pl.lproj/Localizable.strings | 4 ++ .../pt_BR.lproj/Localizable.strings | 4 ++ .../Translations/ru.lproj/Localizable.strings | 4 ++ .../Translations/si.lproj/Localizable.strings | 4 ++ .../Translations/sk.lproj/Localizable.strings | 4 ++ .../Translations/sv.lproj/Localizable.strings | 4 ++ .../Translations/th.lproj/Localizable.strings | 4 ++ .../vi-VN.lproj/Localizable.strings | 4 ++ .../zh-Hant.lproj/Localizable.strings | 4 ++ .../zh_CN.lproj/Localizable.strings | 4 ++ Session/Shared/FullConversationCell.swift | 1 - .../Database/Models/RecipientState.swift | 33 +++++++++++++--- .../Themes/Theme+ClassicDark.swift | 1 + .../Themes/Theme+ClassicLight.swift | 1 + .../Style Guide/Themes/Theme+OceanDark.swift | 1 + .../Style Guide/Themes/Theme+OceanLight.swift | 1 + SessionUIKit/Style Guide/Themes/Theme.swift | 1 + 31 files changed, 171 insertions(+), 17 deletions(-) diff --git a/Session/Closed Groups/NewClosedGroupVC.swift b/Session/Closed Groups/NewClosedGroupVC.swift index 49ed7ae16..1d9f66159 100644 --- a/Session/Closed Groups/NewClosedGroupVC.swift +++ b/Session/Closed Groups/NewClosedGroupVC.swift @@ -9,15 +9,17 @@ import SessionMessagingKit import SignalUtilitiesKit private protocol TableViewTouchDelegate { - func tableViewWasTouched(_ tableView: TableView) + func tableViewWasTouched(_ tableView: TableView, withView hitView: UIView?) } private final class TableView: UITableView { var touchDelegate: TableViewTouchDelegate? override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { - touchDelegate?.tableViewWasTouched(self) - return super.hitTest(point, with: event) + let resultingView: UIView? = super.hitTest(point, with: event) + touchDelegate?.tableViewWasTouched(self, withView: resultingView) + + return resultingView } } @@ -275,10 +277,23 @@ final class NewClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegate ) } - fileprivate func tableViewWasTouched(_ tableView: TableView) { + fileprivate func tableViewWasTouched(_ tableView: TableView, withView hitView: UIView?) { if nameTextField.isFirstResponder { nameTextField.resignFirstResponder() } + else if searchBar.isFirstResponder { + var hitSuperview: UIView? = hitView?.superview + + while hitSuperview != nil && hitSuperview != searchBar { + hitSuperview = hitSuperview?.superview + } + + // If the user hit the cancel button then do nothing (we want to let the cancel + // button remove the focus or it will instantly refocus) + if hitSuperview == searchBar { return } + + searchBar.resignFirstResponder() + } } @objc private func close() { diff --git a/Session/Conversations/Message Cells/VisibleMessageCell.swift b/Session/Conversations/Message Cells/VisibleMessageCell.swift index 45145bb22..3a9d4d33f 100644 --- a/Session/Conversations/Message Cells/VisibleMessageCell.swift +++ b/Session/Conversations/Message Cells/VisibleMessageCell.swift @@ -142,18 +142,33 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate { private lazy var reactionContainerView = ReactionContainerView() + internal lazy var messageStatusContainerView: UIView = { + let result = UIView() + + return result + }() + + internal lazy var messageStatusLabel: UILabel = { + let result = UILabel() + result.accessibilityLabel = "Message sent status" + result.font = .systemFont(ofSize: Values.verySmallFontSize) + result.themeTextColor = .messageBubble_deliveryStatus + + return result + }() + internal lazy var messageStatusImageView: UIImageView = { let result = UIImageView() result.accessibilityLabel = "Message sent status tick" result.contentMode = .scaleAspectFit - result.layer.cornerRadius = VisibleMessageCell.messageStatusImageViewSize / 2 - result.layer.masksToBounds = true + result.themeTintColor = .messageBubble_deliveryStatus + return result }() // MARK: - Settings - private static let messageStatusImageViewSize: CGFloat = 16 + private static let messageStatusImageViewSize: CGFloat = 12 private static let authorLabelBottomSpacing: CGFloat = 4 private static let groupThreadHSpacing: CGFloat = 12 private static let profilePictureSize = Values.verySmallProfilePictureSize @@ -236,13 +251,22 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate { underBubbleStackView.pin(.bottom, to: .bottom, of: self) underBubbleStackView.addArrangedSubview(reactionContainerView) - underBubbleStackView.addArrangedSubview(messageStatusImageView) + underBubbleStackView.addArrangedSubview(messageStatusContainerView) + + messageStatusContainerView.addSubview(messageStatusLabel) + messageStatusContainerView.addSubview(messageStatusImageView) reactionContainerView.widthAnchor .constraint(lessThanOrEqualTo: underBubbleStackView.widthAnchor) .isActive = true + messageStatusImageView.pin(.top, to: .top, of: messageStatusContainerView) + messageStatusImageView.pin(.bottom, to: .bottom, of: messageStatusContainerView) + messageStatusImageView.pin(.trailing, to: .trailing, of: messageStatusContainerView) messageStatusImageView.set(.width, to: VisibleMessageCell.messageStatusImageViewSize) messageStatusImageView.set(.height, to: VisibleMessageCell.messageStatusImageViewSize) + messageStatusLabel.center(.vertical, in: messageStatusContainerView) + messageStatusLabel.pin(.leading, to: .leading, of: messageStatusContainerView) + messageStatusLabel.pin(.trailing, to: .leading, of: messageStatusImageView, withInset: -2) } override func setUpGestureRecognizers() { @@ -389,13 +413,15 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate { ) // Message status image view - let (image, tintColor) = cellViewModel.state.statusIconInfo( + let (image, statusText, tintColor) = cellViewModel.state.statusIconInfo( variant: cellViewModel.variant, hasAtLeastOneReadReceipt: cellViewModel.hasAtLeastOneReadReceipt ) + messageStatusLabel.text = statusText + messageStatusLabel.themeTextColor = tintColor messageStatusImageView.image = image messageStatusImageView.themeTintColor = tintColor - messageStatusImageView.isHidden = ( + messageStatusContainerView.isHidden = ( cellViewModel.variant != .standardOutgoing || cellViewModel.variant == .infoCall || ( diff --git a/Session/Meta/Translations/de.lproj/Localizable.strings b/Session/Meta/Translations/de.lproj/Localizable.strings index 8d583d798..f78f8bea5 100644 --- a/Session/Meta/Translations/de.lproj/Localizable.strings +++ b/Session/Meta/Translations/de.lproj/Localizable.strings @@ -596,3 +596,7 @@ "MESSAGE_STATE_READ" = "Read"; "MESSAGE_STATE_SENT" = "Sent"; "MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; +"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending"; +"MESSAGE_DELIVERY_STATUS_SENT" = "Sent"; +"MESSAGE_DELIVERY_STATUS_READ" = "Read"; +"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send"; diff --git a/Session/Meta/Translations/en.lproj/Localizable.strings b/Session/Meta/Translations/en.lproj/Localizable.strings index 3829aceab..a48be8c05 100644 --- a/Session/Meta/Translations/en.lproj/Localizable.strings +++ b/Session/Meta/Translations/en.lproj/Localizable.strings @@ -596,3 +596,7 @@ "MESSAGE_STATE_READ" = "Read"; "MESSAGE_STATE_SENT" = "Sent"; "MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; +"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending"; +"MESSAGE_DELIVERY_STATUS_SENT" = "Sent"; +"MESSAGE_DELIVERY_STATUS_READ" = "Read"; +"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send"; diff --git a/Session/Meta/Translations/es.lproj/Localizable.strings b/Session/Meta/Translations/es.lproj/Localizable.strings index 31d0bc578..b821c73d7 100644 --- a/Session/Meta/Translations/es.lproj/Localizable.strings +++ b/Session/Meta/Translations/es.lproj/Localizable.strings @@ -596,3 +596,7 @@ "MESSAGE_STATE_READ" = "Read"; "MESSAGE_STATE_SENT" = "Sent"; "MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; +"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending"; +"MESSAGE_DELIVERY_STATUS_SENT" = "Sent"; +"MESSAGE_DELIVERY_STATUS_READ" = "Read"; +"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send"; diff --git a/Session/Meta/Translations/fa.lproj/Localizable.strings b/Session/Meta/Translations/fa.lproj/Localizable.strings index 75cc6f737..c3310be12 100644 --- a/Session/Meta/Translations/fa.lproj/Localizable.strings +++ b/Session/Meta/Translations/fa.lproj/Localizable.strings @@ -596,3 +596,7 @@ "MESSAGE_STATE_READ" = "خوانده شد"; "MESSAGE_STATE_SENT" = "ارسال شد"; "MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; +"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending"; +"MESSAGE_DELIVERY_STATUS_SENT" = "Sent"; +"MESSAGE_DELIVERY_STATUS_READ" = "Read"; +"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send"; diff --git a/Session/Meta/Translations/fi.lproj/Localizable.strings b/Session/Meta/Translations/fi.lproj/Localizable.strings index 92e2e6a11..36eb30b77 100644 --- a/Session/Meta/Translations/fi.lproj/Localizable.strings +++ b/Session/Meta/Translations/fi.lproj/Localizable.strings @@ -596,3 +596,7 @@ "MESSAGE_STATE_READ" = "Read"; "MESSAGE_STATE_SENT" = "Sent"; "MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; +"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending"; +"MESSAGE_DELIVERY_STATUS_SENT" = "Sent"; +"MESSAGE_DELIVERY_STATUS_READ" = "Read"; +"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send"; diff --git a/Session/Meta/Translations/fr.lproj/Localizable.strings b/Session/Meta/Translations/fr.lproj/Localizable.strings index 17c7b0dff..5a3b51d7a 100644 --- a/Session/Meta/Translations/fr.lproj/Localizable.strings +++ b/Session/Meta/Translations/fr.lproj/Localizable.strings @@ -596,3 +596,7 @@ "MESSAGE_STATE_READ" = "Read"; "MESSAGE_STATE_SENT" = "Sent"; "MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; +"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending"; +"MESSAGE_DELIVERY_STATUS_SENT" = "Sent"; +"MESSAGE_DELIVERY_STATUS_READ" = "Read"; +"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send"; diff --git a/Session/Meta/Translations/hi.lproj/Localizable.strings b/Session/Meta/Translations/hi.lproj/Localizable.strings index 8bab51375..3d29a1e30 100644 --- a/Session/Meta/Translations/hi.lproj/Localizable.strings +++ b/Session/Meta/Translations/hi.lproj/Localizable.strings @@ -596,3 +596,7 @@ "MESSAGE_STATE_READ" = "Read"; "MESSAGE_STATE_SENT" = "Sent"; "MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; +"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending"; +"MESSAGE_DELIVERY_STATUS_SENT" = "Sent"; +"MESSAGE_DELIVERY_STATUS_READ" = "Read"; +"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send"; diff --git a/Session/Meta/Translations/hr.lproj/Localizable.strings b/Session/Meta/Translations/hr.lproj/Localizable.strings index 8af92e999..facd36892 100644 --- a/Session/Meta/Translations/hr.lproj/Localizable.strings +++ b/Session/Meta/Translations/hr.lproj/Localizable.strings @@ -596,3 +596,7 @@ "MESSAGE_STATE_READ" = "Read"; "MESSAGE_STATE_SENT" = "Sent"; "MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; +"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending"; +"MESSAGE_DELIVERY_STATUS_SENT" = "Sent"; +"MESSAGE_DELIVERY_STATUS_READ" = "Read"; +"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send"; diff --git a/Session/Meta/Translations/id-ID.lproj/Localizable.strings b/Session/Meta/Translations/id-ID.lproj/Localizable.strings index 5ff981ef7..2ad901a50 100644 --- a/Session/Meta/Translations/id-ID.lproj/Localizable.strings +++ b/Session/Meta/Translations/id-ID.lproj/Localizable.strings @@ -596,3 +596,7 @@ "MESSAGE_STATE_READ" = "Read"; "MESSAGE_STATE_SENT" = "Sent"; "MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; +"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending"; +"MESSAGE_DELIVERY_STATUS_SENT" = "Sent"; +"MESSAGE_DELIVERY_STATUS_READ" = "Read"; +"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send"; diff --git a/Session/Meta/Translations/it.lproj/Localizable.strings b/Session/Meta/Translations/it.lproj/Localizable.strings index f6725544a..28e2d7ba4 100644 --- a/Session/Meta/Translations/it.lproj/Localizable.strings +++ b/Session/Meta/Translations/it.lproj/Localizable.strings @@ -596,3 +596,7 @@ "MESSAGE_STATE_READ" = "Read"; "MESSAGE_STATE_SENT" = "Sent"; "MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; +"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending"; +"MESSAGE_DELIVERY_STATUS_SENT" = "Sent"; +"MESSAGE_DELIVERY_STATUS_READ" = "Read"; +"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send"; diff --git a/Session/Meta/Translations/ja.lproj/Localizable.strings b/Session/Meta/Translations/ja.lproj/Localizable.strings index 6319ef7fd..76c151cd7 100644 --- a/Session/Meta/Translations/ja.lproj/Localizable.strings +++ b/Session/Meta/Translations/ja.lproj/Localizable.strings @@ -596,3 +596,7 @@ "MESSAGE_STATE_READ" = "Read"; "MESSAGE_STATE_SENT" = "Sent"; "MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; +"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending"; +"MESSAGE_DELIVERY_STATUS_SENT" = "Sent"; +"MESSAGE_DELIVERY_STATUS_READ" = "Read"; +"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send"; diff --git a/Session/Meta/Translations/nl.lproj/Localizable.strings b/Session/Meta/Translations/nl.lproj/Localizable.strings index 284441372..7889ee1b9 100644 --- a/Session/Meta/Translations/nl.lproj/Localizable.strings +++ b/Session/Meta/Translations/nl.lproj/Localizable.strings @@ -596,3 +596,7 @@ "MESSAGE_STATE_READ" = "Read"; "MESSAGE_STATE_SENT" = "Sent"; "MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; +"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending"; +"MESSAGE_DELIVERY_STATUS_SENT" = "Sent"; +"MESSAGE_DELIVERY_STATUS_READ" = "Read"; +"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send"; diff --git a/Session/Meta/Translations/pl.lproj/Localizable.strings b/Session/Meta/Translations/pl.lproj/Localizable.strings index ab8b48d0b..29f3a0fa1 100644 --- a/Session/Meta/Translations/pl.lproj/Localizable.strings +++ b/Session/Meta/Translations/pl.lproj/Localizable.strings @@ -596,3 +596,7 @@ "MESSAGE_STATE_READ" = "Read"; "MESSAGE_STATE_SENT" = "Sent"; "MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; +"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending"; +"MESSAGE_DELIVERY_STATUS_SENT" = "Sent"; +"MESSAGE_DELIVERY_STATUS_READ" = "Read"; +"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send"; diff --git a/Session/Meta/Translations/pt_BR.lproj/Localizable.strings b/Session/Meta/Translations/pt_BR.lproj/Localizable.strings index cd772f650..f833144bf 100644 --- a/Session/Meta/Translations/pt_BR.lproj/Localizable.strings +++ b/Session/Meta/Translations/pt_BR.lproj/Localizable.strings @@ -596,3 +596,7 @@ "MESSAGE_STATE_READ" = "Read"; "MESSAGE_STATE_SENT" = "Sent"; "MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; +"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending"; +"MESSAGE_DELIVERY_STATUS_SENT" = "Sent"; +"MESSAGE_DELIVERY_STATUS_READ" = "Read"; +"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send"; diff --git a/Session/Meta/Translations/ru.lproj/Localizable.strings b/Session/Meta/Translations/ru.lproj/Localizable.strings index 632e50aa4..a268d3598 100644 --- a/Session/Meta/Translations/ru.lproj/Localizable.strings +++ b/Session/Meta/Translations/ru.lproj/Localizable.strings @@ -596,3 +596,7 @@ "MESSAGE_STATE_READ" = "Read"; "MESSAGE_STATE_SENT" = "Sent"; "MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; +"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending"; +"MESSAGE_DELIVERY_STATUS_SENT" = "Sent"; +"MESSAGE_DELIVERY_STATUS_READ" = "Read"; +"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send"; diff --git a/Session/Meta/Translations/si.lproj/Localizable.strings b/Session/Meta/Translations/si.lproj/Localizable.strings index 753687545..42673e0d0 100644 --- a/Session/Meta/Translations/si.lproj/Localizable.strings +++ b/Session/Meta/Translations/si.lproj/Localizable.strings @@ -596,3 +596,7 @@ "MESSAGE_STATE_READ" = "Read"; "MESSAGE_STATE_SENT" = "Sent"; "MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; +"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending"; +"MESSAGE_DELIVERY_STATUS_SENT" = "Sent"; +"MESSAGE_DELIVERY_STATUS_READ" = "Read"; +"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send"; diff --git a/Session/Meta/Translations/sk.lproj/Localizable.strings b/Session/Meta/Translations/sk.lproj/Localizable.strings index 1388f0536..5815b0cb6 100644 --- a/Session/Meta/Translations/sk.lproj/Localizable.strings +++ b/Session/Meta/Translations/sk.lproj/Localizable.strings @@ -596,3 +596,7 @@ "MESSAGE_STATE_READ" = "Read"; "MESSAGE_STATE_SENT" = "Sent"; "MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; +"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending"; +"MESSAGE_DELIVERY_STATUS_SENT" = "Sent"; +"MESSAGE_DELIVERY_STATUS_READ" = "Read"; +"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send"; diff --git a/Session/Meta/Translations/sv.lproj/Localizable.strings b/Session/Meta/Translations/sv.lproj/Localizable.strings index 2af704369..eebfc3140 100644 --- a/Session/Meta/Translations/sv.lproj/Localizable.strings +++ b/Session/Meta/Translations/sv.lproj/Localizable.strings @@ -596,3 +596,7 @@ "MESSAGE_STATE_READ" = "Read"; "MESSAGE_STATE_SENT" = "Sent"; "MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; +"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending"; +"MESSAGE_DELIVERY_STATUS_SENT" = "Sent"; +"MESSAGE_DELIVERY_STATUS_READ" = "Read"; +"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send"; diff --git a/Session/Meta/Translations/th.lproj/Localizable.strings b/Session/Meta/Translations/th.lproj/Localizable.strings index 24910f380..6921bf21e 100644 --- a/Session/Meta/Translations/th.lproj/Localizable.strings +++ b/Session/Meta/Translations/th.lproj/Localizable.strings @@ -596,3 +596,7 @@ "MESSAGE_STATE_READ" = "Read"; "MESSAGE_STATE_SENT" = "Sent"; "MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; +"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending"; +"MESSAGE_DELIVERY_STATUS_SENT" = "Sent"; +"MESSAGE_DELIVERY_STATUS_READ" = "Read"; +"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send"; diff --git a/Session/Meta/Translations/vi-VN.lproj/Localizable.strings b/Session/Meta/Translations/vi-VN.lproj/Localizable.strings index 6a27510bc..410798536 100644 --- a/Session/Meta/Translations/vi-VN.lproj/Localizable.strings +++ b/Session/Meta/Translations/vi-VN.lproj/Localizable.strings @@ -596,3 +596,7 @@ "MESSAGE_STATE_READ" = "Read"; "MESSAGE_STATE_SENT" = "Sent"; "MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; +"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending"; +"MESSAGE_DELIVERY_STATUS_SENT" = "Sent"; +"MESSAGE_DELIVERY_STATUS_READ" = "Read"; +"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send"; diff --git a/Session/Meta/Translations/zh-Hant.lproj/Localizable.strings b/Session/Meta/Translations/zh-Hant.lproj/Localizable.strings index d408fc648..381e074e1 100644 --- a/Session/Meta/Translations/zh-Hant.lproj/Localizable.strings +++ b/Session/Meta/Translations/zh-Hant.lproj/Localizable.strings @@ -596,3 +596,7 @@ "MESSAGE_STATE_READ" = "Read"; "MESSAGE_STATE_SENT" = "Sent"; "MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; +"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending"; +"MESSAGE_DELIVERY_STATUS_SENT" = "Sent"; +"MESSAGE_DELIVERY_STATUS_READ" = "Read"; +"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send"; diff --git a/Session/Meta/Translations/zh_CN.lproj/Localizable.strings b/Session/Meta/Translations/zh_CN.lproj/Localizable.strings index f391b1784..862b7d3d0 100644 --- a/Session/Meta/Translations/zh_CN.lproj/Localizable.strings +++ b/Session/Meta/Translations/zh_CN.lproj/Localizable.strings @@ -596,3 +596,7 @@ "MESSAGE_STATE_READ" = "Read"; "MESSAGE_STATE_SENT" = "Sent"; "MESSAGE_REQUEST_PENDING_APPROVAL_INFO" = "You will be able to send voice messages and attachments once the recipient has approved this message request"; +"MESSAGE_DELIVERY_STATUS_SENDING" = "Sending"; +"MESSAGE_DELIVERY_STATUS_SENT" = "Sent"; +"MESSAGE_DELIVERY_STATUS_READ" = "Read"; +"MESSAGE_DELIVERY_STATUS_FAILED" = "Failed to send"; diff --git a/Session/Shared/FullConversationCell.swift b/Session/Shared/FullConversationCell.swift index 521f968d1..11fa90c97 100644 --- a/Session/Shared/FullConversationCell.swift +++ b/Session/Shared/FullConversationCell.swift @@ -104,7 +104,6 @@ public final class FullConversationCell: UITableViewCell { let result: UIImageView = UIImageView() result.clipsToBounds = true result.contentMode = .scaleAspectFit - result.layer.cornerRadius = (FullConversationCell.statusIndicatorSize / 2) return result }() diff --git a/SessionMessagingKit/Database/Models/RecipientState.swift b/SessionMessagingKit/Database/Models/RecipientState.swift index bed9a84f2..929a5cb8c 100644 --- a/SessionMessagingKit/Database/Models/RecipientState.swift +++ b/SessionMessagingKit/Database/Models/RecipientState.swift @@ -65,16 +65,37 @@ public struct RecipientState: Codable, Equatable, FetchableRecord, PersistableRe } } - public func statusIconInfo(variant: Interaction.Variant, hasAtLeastOneReadReceipt: Bool) -> (image: UIImage?, themeTintColor: ThemeValue) { - guard variant == .standardOutgoing else { return (nil, .textPrimary) } + public func statusIconInfo(variant: Interaction.Variant, hasAtLeastOneReadReceipt: Bool) -> (image: UIImage?, text: String?, themeTintColor: ThemeValue) { + guard variant == .standardOutgoing else { return (nil, nil, .textPrimary) } switch (self, hasAtLeastOneReadReceipt) { - case (.sending, _): return (UIImage(systemName: "ellipsis.circle"), .textPrimary) + case (.sending, _): + return ( + UIImage(systemName: "ellipsis.circle"), + "MESSAGE_DELIVERY_STATUS_SENDING".localized(), + .messageBubble_deliveryStatus + ) + case (.sent, false), (.skipped, _): - return (UIImage(systemName: "checkmark.circle"), .textPrimary) + return ( + UIImage(systemName: "checkmark.circle"), + "MESSAGE_DELIVERY_STATUS_SENT".localized(), + .messageBubble_deliveryStatus + ) + + case (.sent, true): + return ( + UIImage(systemName: "eye.fill"), + "MESSAGE_DELIVERY_STATUS_READ".localized(), + .messageBubble_deliveryStatus + ) - case (.sent, true): return (UIImage(systemName: "checkmark.circle.fill"), .textPrimary) - case (.failed, _): return (UIImage(systemName: "exclamationmark.circle"), .danger) + case (.failed, _): + return ( + UIImage(systemName: "exclamationmark.triangle"), + "MESSAGE_DELIVERY_STATUS_FAILED".localized(), + .danger + ) } } } diff --git a/SessionUIKit/Style Guide/Themes/Theme+ClassicDark.swift b/SessionUIKit/Style Guide/Themes/Theme+ClassicDark.swift index 61ed9914e..99ef6bd21 100644 --- a/SessionUIKit/Style Guide/Themes/Theme+ClassicDark.swift +++ b/SessionUIKit/Style Guide/Themes/Theme+ClassicDark.swift @@ -34,6 +34,7 @@ internal enum Theme_ClassicDark: ThemeColors { .messageBubble_outgoingText: .classicDark0, .messageBubble_incomingText: .classicDark6, .messageBubble_overlay: .black_06, + .messageBubble_deliveryStatus: .classicDark5, // MenuButton .menuButton_background: .primary, diff --git a/SessionUIKit/Style Guide/Themes/Theme+ClassicLight.swift b/SessionUIKit/Style Guide/Themes/Theme+ClassicLight.swift index d2554fc0d..6e7e7dc32 100644 --- a/SessionUIKit/Style Guide/Themes/Theme+ClassicLight.swift +++ b/SessionUIKit/Style Guide/Themes/Theme+ClassicLight.swift @@ -34,6 +34,7 @@ internal enum Theme_ClassicLight: ThemeColors { .messageBubble_outgoingText: .classicLight0, .messageBubble_incomingText: .classicLight0, .messageBubble_overlay: .black_06, + .messageBubble_deliveryStatus: .classicLight1, // MenuButton .menuButton_background: .primary, diff --git a/SessionUIKit/Style Guide/Themes/Theme+OceanDark.swift b/SessionUIKit/Style Guide/Themes/Theme+OceanDark.swift index 1775bfed0..e01656c8f 100644 --- a/SessionUIKit/Style Guide/Themes/Theme+OceanDark.swift +++ b/SessionUIKit/Style Guide/Themes/Theme+OceanDark.swift @@ -34,6 +34,7 @@ internal enum Theme_OceanDark: ThemeColors { .messageBubble_outgoingText: .oceanDark0, .messageBubble_incomingText: .oceanDark7, .messageBubble_overlay: .black_06, + .messageBubble_deliveryStatus: .oceanDark5, // MenuButton .menuButton_background: .primary, diff --git a/SessionUIKit/Style Guide/Themes/Theme+OceanLight.swift b/SessionUIKit/Style Guide/Themes/Theme+OceanLight.swift index c22f4fb34..649028a1e 100644 --- a/SessionUIKit/Style Guide/Themes/Theme+OceanLight.swift +++ b/SessionUIKit/Style Guide/Themes/Theme+OceanLight.swift @@ -34,6 +34,7 @@ internal enum Theme_OceanLight: ThemeColors { .messageBubble_outgoingText: .oceanLight1, .messageBubble_incomingText: .oceanLight1, .messageBubble_overlay: .black_06, + .messageBubble_deliveryStatus: .oceanLight2, // MenuButton .menuButton_background: .primary, diff --git a/SessionUIKit/Style Guide/Themes/Theme.swift b/SessionUIKit/Style Guide/Themes/Theme.swift index d81a5a3bf..ca0a620d9 100644 --- a/SessionUIKit/Style Guide/Themes/Theme.swift +++ b/SessionUIKit/Style Guide/Themes/Theme.swift @@ -122,6 +122,7 @@ public indirect enum ThemeValue: Hashable { case messageBubble_outgoingText case messageBubble_incomingText case messageBubble_overlay + case messageBubble_deliveryStatus // MenuButton case menuButton_background From d38a44515d29125782dca0d26bf4b050f48dd192 Mon Sep 17 00:00:00 2001 From: Morgan Pretty Date: Tue, 24 Jan 2023 17:25:46 +1100 Subject: [PATCH 2/4] Made some tweaks to help properly stop the JobRunner --- SessionUtilitiesKit/JobRunner/JobRunner.swift | 30 ++++++++++++++----- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/SessionUtilitiesKit/JobRunner/JobRunner.swift b/SessionUtilitiesKit/JobRunner/JobRunner.swift index 065ad3ba1..7d604f0ba 100644 --- a/SessionUtilitiesKit/JobRunner/JobRunner.swift +++ b/SessionUtilitiesKit/JobRunner/JobRunner.swift @@ -111,6 +111,7 @@ public final class JobRunner { fileprivate static var perSessionJobsCompleted: Atomic> = Atomic([]) private static var hasCompletedInitialBecomeActive: Atomic = Atomic(false) private static var shutdownBackgroundTask: Atomic = Atomic(nil) + fileprivate static var canStartQueues: Atomic = Atomic(false) // MARK: - Configuration @@ -161,6 +162,9 @@ public final class JobRunner { queues.wrappedValue[job.variant]?.upsert(job, canStartJob: canStartJob) + // Don't start the queue if the job can't be started + guard canStartJob else { return } + // Start the job runner if needed db.afterNextTransaction { _ in queues.wrappedValue[job.variant]?.start() @@ -188,15 +192,13 @@ public final class JobRunner { queues.wrappedValue[updatedJob.variant]?.insert(updatedJob, before: otherJob) - // Start the job runner if needed - db.afterNextTransaction { _ in - queues.wrappedValue[updatedJob.variant]?.start() - } - return (jobId, updatedJob) } public static func appDidFinishLaunching() { + // Flag that the JobRunner can start it's queues + JobRunner.canStartQueues.mutate { $0 = true } + // Note: 'appDidBecomeActive' will run on first launch anyway so we can // leave those jobs out and can wait until then to start the JobRunner let jobsToRun: (blocking: [Job], nonBlocking: [Job]) = Storage.shared @@ -242,6 +244,9 @@ public final class JobRunner { } public static func appDidBecomeActive() { + // Flag that the JobRunner can start it's queues + JobRunner.canStartQueues.mutate { $0 = true } + // If we have a running "sutdownBackgroundTask" then we want to cancel it as otherwise it // can result in the database being suspended and us being unable to interact with it at all shutdownBackgroundTask.mutate { @@ -291,6 +296,11 @@ public final class JobRunner { exceptForVariant: Job.Variant? = nil, onComplete: (() -> ())? = nil ) { + // Inform the JobRunner that it can't start any queues (this is to prevent queues from + // rescheduling themselves while in the background, when the app restarts or becomes active + // the JobRunenr will update this flag) + JobRunner.canStartQueues.mutate { $0 = false } + // Stop all queues except for the one containing the `exceptForVariant` queues.wrappedValue .values @@ -632,6 +642,7 @@ private final class JobQueue { fileprivate func start(force: Bool = false) { // We only want the JobRunner to run in the main app guard CurrentAppContext().isMainApp else { return } + guard JobRunner.canStartQueues.wrappedValue else { return } guard force || !isRunning.wrappedValue else { return } // The JobRunner runs synchronously we need to ensure this doesn't start @@ -852,8 +863,9 @@ private final class JobQueue { .fetchOne(db) } - // If there are no remaining jobs the trigger the 'onQueueDrained' callback and stop - guard let nextJobTimestamp: TimeInterval = nextJobTimestamp else { + // If there are no remaining jobs or the JobRunner isn't allowed to start any queues then trigger + // the 'onQueueDrained' callback and stop + guard let nextJobTimestamp: TimeInterval = nextJobTimestamp, JobRunner.canStartQueues.wrappedValue else { if executionType != .concurrent || jobsCurrentlyRunning.wrappedValue.isEmpty { self.onQueueDrained?() } @@ -1064,6 +1076,8 @@ private final class JobQueue { queue = queue.filter { !dependantJobIds.contains($0.id ?? -1) } } } + + performCleanUp(for: job, result: .failed) return } @@ -1082,7 +1096,7 @@ private final class JobQueue { try job.dependantJobs .updateAll( db, - Job.Columns.failureCount.set(to: job.failureCount), + Job.Columns.failureCount.set(to: (job.failureCount + 1)), Job.Columns.nextRunTimestamp.set(to: (nextRunTimestamp + (1 / 1000))) ) From 5659b55eae221df278e900e1a6bd08a15756095a Mon Sep 17 00:00:00 2001 From: Morgan Pretty Date: Tue, 24 Jan 2023 17:37:30 +1100 Subject: [PATCH 3/4] Fixed a bug where a stale flag was used to determine how to send a push notification --- SessionMessagingKit/Sending & Receiving/MessageSender.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SessionMessagingKit/Sending & Receiving/MessageSender.swift b/SessionMessagingKit/Sending & Receiving/MessageSender.swift index ead951cbb..5cf680554 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageSender.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageSender.swift @@ -66,7 +66,6 @@ public final class MessageSender { ) throws -> Promise { let (promise, seal) = Promise.pending() let userPublicKey: String = getUserHexEncodedPublicKey(db) - let isMainAppActive: Bool = (UserDefaults.sharedLokiProject?[.isMainAppActive]).defaulting(to: false) let messageSendTimestamp: Int64 = SnodeAPI.currentOffsetTimestampMs() // Set the timestamp, sender and recipient @@ -261,6 +260,8 @@ public final class MessageSender { behaviour: .runOnce, details: NotifyPushServerJob.Details(message: snodeMessage) ) + let isMainAppActive: Bool = (UserDefaults.sharedLokiProject?[.isMainAppActive]) + .defaulting(to: false) if isMainAppActive { JobRunner.add(db, job: job) From 41f1b14066ff87049867350c70eaa2504efc6005 Mon Sep 17 00:00:00 2001 From: ryanzhao Date: Fri, 27 Jan 2023 16:09:20 +1100 Subject: [PATCH 4/4] bump up version & build number --- Session.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Session.xcodeproj/project.pbxproj b/Session.xcodeproj/project.pbxproj index 16253cb68..bcf48899c 100644 --- a/Session.xcodeproj/project.pbxproj +++ b/Session.xcodeproj/project.pbxproj @@ -7212,7 +7212,7 @@ "$(SRCROOT)", ); LLVM_LTO = NO; - MARKETING_VERSION = 2.2.4; + MARKETING_VERSION = 2.2.5; OTHER_LDFLAGS = "$(inherited)"; OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\""; PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger"; @@ -7284,7 +7284,7 @@ "$(SRCROOT)", ); LLVM_LTO = NO; - MARKETING_VERSION = 2.2.4; + MARKETING_VERSION = 2.2.5; OTHER_LDFLAGS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger"; PRODUCT_NAME = Session;