From 2ae0ae40d4c98eb5994e058bc1daaf3c91488ab2 Mon Sep 17 00:00:00 2001 From: Ryan Zhao Date: Mon, 28 Feb 2022 15:22:38 +1100 Subject: [PATCH] minor improvements to reduce the database read on UI thread --- Session/Conversations/ConversationVC.swift | 19 ++++++----- .../Content Views/QuoteView.swift | 33 +++++-------------- .../Message Cells/VisibleMessageCell.swift | 2 +- 3 files changed, 20 insertions(+), 34 deletions(-) diff --git a/Session/Conversations/ConversationVC.swift b/Session/Conversations/ConversationVC.swift index 4be6e8d13..e41658545 100644 --- a/Session/Conversations/ConversationVC.swift +++ b/Session/Conversations/ConversationVC.swift @@ -11,6 +11,7 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, OWSConversat let threadStartedAsMessageRequest: Bool let focusedMessageID: String? // This is used for global search var focusedMessageIndexPath: IndexPath? + var initialUnreadCount: UInt = 0 var unreadViewItems: [ConversationViewItem] = [] var scrollButtonBottomConstraint: NSLayoutConstraint? var scrollButtonMessageRequestsBottomConstraint: NSLayoutConstraint? @@ -276,11 +277,10 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, OWSConversat self.threadStartedAsMessageRequest = thread.isMessageRequest() self.focusedMessageID = focusedMessageID super.init(nibName: nil, bundle: nil) - var unreadCount: UInt = 0 Storage.read { transaction in - unreadCount = self.thread.unreadMessageCount(transaction: transaction) + self.initialUnreadCount = self.thread.unreadMessageCount(transaction: transaction) } - let clampedUnreadCount = min(unreadCount, UInt(kConversationInitialMaxRangeSize), UInt(viewItems.endIndex)) + let clampedUnreadCount = min(self.initialUnreadCount, UInt(kConversationInitialMaxRangeSize), UInt(viewItems.endIndex)) unreadViewItems = clampedUnreadCount != 0 ? [ConversationViewItem](viewItems[viewItems.endIndex - Int(clampedUnreadCount) ..< viewItems.endIndex]) : [] } @@ -289,6 +289,7 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, OWSConversat } override func viewDidLoad() { + SNLog("Ryan: Conversation VC starts loading at \(NSDate.ows_millisecondTimeStamp())") super.viewDidLoad() // Gradient setUpGradientBackground() @@ -391,27 +392,26 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, OWSConversat if let v2OpenGroup = Storage.shared.getV2OpenGroup(for: thread.uniqueId!) { OpenGroupAPIV2.getMemberCount(for: v2OpenGroup.room, on: v2OpenGroup.server).retainUntilComplete() } + + SNLog("Ryan: Conversation VC ends loading at \(NSDate.ows_millisecondTimeStamp())") } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() if !didFinishInitialLayout { // Scroll to the last unread message if possible; otherwise scroll to the bottom. - var unreadCount: UInt = 0 - Storage.read { transaction in - unreadCount = self.thread.unreadMessageCount(transaction: transaction) - } // When the unread message count is more than the number of view items of a page, // the screen will scroll to the bottom instead of the first unread message. // unreadIndicatorIndex is calculated during loading of the viewItems, so it's // supposed to be accurate. DispatchQueue.main.async { + SNLog("Ryan: Conversation VC starts layout subviews at \(NSDate.ows_millisecondTimeStamp())") if let focusedMessageID = self.focusedMessageID { self.scrollToInteraction(with: focusedMessageID, isAnimated: false, highlighted: true) } else { let firstUnreadMessageIndex = self.viewModel.viewState.unreadIndicatorIndex?.intValue ?? (self.viewItems.count - self.unreadViewItems.count) - if unreadCount > 0, let viewItem = self.viewItems[ifValid: firstUnreadMessageIndex], let interactionID = viewItem.interaction.uniqueId { + if self.initialUnreadCount > 0, let viewItem = self.viewItems[ifValid: firstUnreadMessageIndex], let interactionID = viewItem.interaction.uniqueId { self.scrollToInteraction(with: interactionID, position: .top, isAnimated: false) self.unreadCountView.alpha = self.scrollButton.alpha } else { @@ -419,11 +419,13 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, OWSConversat } } self.scrollButton.alpha = self.getScrollButtonOpacity() + SNLog("Ryan: Conversation VC ends layout subviews at \(NSDate.ows_millisecondTimeStamp())") } } } override func viewDidAppear(_ animated: Bool) { + SNLog("Ryan: Conversation VC did appear at \(NSDate.ows_millisecondTimeStamp())") super.viewDidAppear(animated) highlightFocusedMessageIfNeeded() didFinishInitialLayout = true @@ -777,6 +779,7 @@ final class ConversationVC : BaseVC, ConversationViewModelDelegate, OWSConversat let isMainAppAndActive = CurrentAppContext().isMainAppAndActive guard isMainAppAndActive && viewModel.canLoadMoreItems() && !isLoadingMore && messagesTableView.contentOffset.y < ConversationVC.loadMoreThreshold else { return } + print("Ryan: auto loading more") isLoadingMore = true viewModel.loadAnotherPageOfMessages() } diff --git a/Session/Conversations/Message Cells/Content Views/QuoteView.swift b/Session/Conversations/Message Cells/Content Views/QuoteView.swift index a32e07724..efd23a388 100644 --- a/Session/Conversations/Message Cells/Content Views/QuoteView.swift +++ b/Session/Conversations/Message Cells/Content Views/QuoteView.swift @@ -1,6 +1,7 @@ final class QuoteView : UIView { private let mode: Mode + private let thread: TSThread private let direction: Direction private let hInset: CGFloat private let maxWidth: CGFloat @@ -34,25 +35,6 @@ final class QuoteView : UIView { } } - private var threadID: String { - switch mode { - case .regular(let viewItem): return viewItem.interaction.uniqueThreadId - case .draft(let model): return model.threadId - } - } - - private var isGroupThread: Bool { - switch mode { - case .regular(let viewItem): return viewItem.isGroupThread - case .draft(let model): - var result = false - Storage.read { transaction in - result = TSThread.fetch(uniqueId: model.threadId, transaction: transaction)?.isGroupThread() ?? false - } - return result - } - } - private var authorID: String { switch mode { case .regular(let viewItem): return viewItem.quotedReply!.authorId @@ -93,8 +75,9 @@ final class QuoteView : UIView { static let cancelButtonSize: CGFloat = 33 // MARK: Lifecycle - init(for viewItem: ConversationViewItem, direction: Direction, hInset: CGFloat, maxWidth: CGFloat) { + init(for viewItem: ConversationViewItem, in thread: TSThread?, direction: Direction, hInset: CGFloat, maxWidth: CGFloat) { self.mode = .regular(viewItem) + self.thread = thread ?? TSThread.fetch(uniqueId: viewItem.interaction.uniqueThreadId)! self.maxWidth = maxWidth self.direction = direction self.hInset = hInset @@ -105,6 +88,7 @@ final class QuoteView : UIView { init(for model: OWSQuotedReplyModel, direction: Direction, hInset: CGFloat, maxWidth: CGFloat, delegate: QuoteViewDelegate) { self.mode = .draft(model) + self.thread = TSThread.fetch(uniqueId: model.threadId)! self.maxWidth = maxWidth self.direction = direction self.hInset = hInset @@ -188,16 +172,15 @@ final class QuoteView : UIView { bodyLabel.lineBreakMode = .byTruncatingTail let isOutgoing = (direction == .outgoing) bodyLabel.font = .systemFont(ofSize: Values.smallFontSize) - bodyLabel.attributedText = given(body) { MentionUtilities.highlightMentions(in: $0, isOutgoingMessage: isOutgoing, threadID: threadID, attributes: [:]) } - ?? given(attachments.first?.contentType) { NSAttributedString(string: MIMETypeUtil.isAudio($0) ? "Audio" : "Document") } ?? NSAttributedString(string: "Document") + bodyLabel.attributedText = given(body) { MentionUtilities.highlightMentions(in: $0, isOutgoingMessage: isOutgoing, threadID: thread.uniqueId!, attributes: [:]) } ?? given(attachments.first?.contentType) { NSAttributedString(string: MIMETypeUtil.isAudio($0) ? "Audio" : "Document") } ?? NSAttributedString(string: "Document") bodyLabel.textColor = textColor let bodyLabelSize = bodyLabel.systemLayoutSizeFitting(availableSpace) // Label stack view var authorLabelHeight: CGFloat? - if isGroupThread { + if let groupThread = thread as? TSGroupThread { let authorLabel = UILabel() authorLabel.lineBreakMode = .byTruncatingTail - let context: Contact.Context = (TSGroupThread.fetch(uniqueId: threadID)?.isOpenGroup == true) ? .openGroup : .regular + let context: Contact.Context = groupThread.isOpenGroup ? .openGroup : .regular authorLabel.text = Storage.shared.getContact(with: authorID)?.displayName(for: context) ?? authorID authorLabel.textColor = textColor authorLabel.font = .boldSystemFont(ofSize: Values.smallFontSize) @@ -225,7 +208,7 @@ final class QuoteView : UIView { // Constraints contentView.addSubview(mainStackView) mainStackView.pin(to: contentView) - if !isGroupThread { + if !thread.isGroupThread() { bodyLabel.set(.width, to: bodyLabelSize.width) } let bodyLabelHeight = bodyLabelSize.height.clamp(0, maxBodyLabelHeight) diff --git a/Session/Conversations/Message Cells/VisibleMessageCell.swift b/Session/Conversations/Message Cells/VisibleMessageCell.swift index 19fa3748a..25fdd3dc5 100644 --- a/Session/Conversations/Message Cells/VisibleMessageCell.swift +++ b/Session/Conversations/Message Cells/VisibleMessageCell.swift @@ -335,7 +335,7 @@ final class VisibleMessageCell : MessageCell, LinkPreviewViewDelegate { if viewItem.quotedReply != nil { let direction: QuoteView.Direction = isOutgoing ? .outgoing : .incoming let hInset: CGFloat = 2 - let quoteView = QuoteView(for: viewItem, direction: direction, hInset: hInset, maxWidth: maxWidth) + let quoteView = QuoteView(for: viewItem, in: thread, direction: direction, hInset: hInset, maxWidth: maxWidth) let quoteViewContainer = UIView(wrapping: quoteView, withInsets: UIEdgeInsets(top: 0, leading: hInset, bottom: 0, trailing: hInset)) stackView.addArrangedSubview(quoteViewContainer) }