diff --git a/Session/Conversations/ConversationVC+Interaction.swift b/Session/Conversations/ConversationVC+Interaction.swift index 60a4bc81a..867493c82 100644 --- a/Session/Conversations/ConversationVC+Interaction.swift +++ b/Session/Conversations/ConversationVC+Interaction.swift @@ -21,6 +21,41 @@ extension ConversationVC: AttachmentApprovalViewControllerDelegate, GifPickerViewControllerDelegate { + // MARK: - Mark as read + func markVisibleMessagesAsRead() { + // Note: For the 'tableVisualBottom' we remove the 'Values.mediumSpacing' as that is the distance + // the table content appears above the input view + let tableVisualBottom: CGFloat = (tableView.frame.maxY - (tableView.contentInset.bottom - Values.mediumSpacing)) + + if + let visibleIndexPaths: [IndexPath] = self.tableView.indexPathsForVisibleRows, + let messagesSection: Int = visibleIndexPaths + .first(where: { self.viewModel.interactionData[$0.section].model == .messages })? + .section, + let newestCellViewModel: MessageViewModel = visibleIndexPaths + .sorted() + .filter({ $0.section == messagesSection }) + .compactMap({ indexPath -> (frame: CGRect, cellViewModel: MessageViewModel)? in + guard let frame: CGRect = tableView.cellForRow(at: indexPath)?.frame else { + return nil + } + + return ( + view.convert(frame, from: tableView), + self.viewModel.interactionData[indexPath.section].elements[indexPath.row] + ) + }) + // Exclude messages that are partially off the bottom of the screen + .filter({ $0.frame.maxY <= tableVisualBottom }) + .last? + .cellViewModel + { + self.viewModel.markAsRead(beforeInclusive: newestCellViewModel.id) + } + } + + // MARK: - Open Settings + @objc func handleTitleViewTapped() { // Don't take the user to settings for unapproved threads guard viewModel.threadData.threadRequiresApproval == false else { return } diff --git a/Session/Conversations/ConversationVC.swift b/Session/Conversations/ConversationVC.swift index e9773e920..2d52bcc68 100644 --- a/Session/Conversations/ConversationVC.swift +++ b/Session/Conversations/ConversationVC.swift @@ -994,6 +994,8 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl else { self.scrollToBottom(isAnimated: false) } + + self.markVisibleMessagesAsRead() self.scrollButton.alpha = self.getScrollButtonOpacity() self.unreadCountView.alpha = self.scrollButton.alpha @@ -1435,36 +1437,7 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl // We want to mark messages as read while we scroll, so grab the newest message and mark // everything older as read - // - // Note: For the 'tableVisualBottom' we remove the 'Values.mediumSpacing' as that is the distance - // the table content appears above the input view - let tableVisualBottom: CGFloat = (tableView.frame.maxY - (tableView.contentInset.bottom - Values.mediumSpacing)) - - if - let visibleIndexPaths: [IndexPath] = self.tableView.indexPathsForVisibleRows, - let messagesSection: Int = visibleIndexPaths - .first(where: { self.viewModel.interactionData[$0.section].model == .messages })? - .section, - let newestCellViewModel: MessageViewModel = visibleIndexPaths - .sorted() - .filter({ $0.section == messagesSection }) - .compactMap({ indexPath -> (frame: CGRect, cellViewModel: MessageViewModel)? in - guard let frame: CGRect = tableView.cellForRow(at: indexPath)?.frame else { - return nil - } - - return ( - view.convert(frame, from: tableView), - self.viewModel.interactionData[indexPath.section].elements[indexPath.row] - ) - }) - // Exclude messages that are partially off the bottom of the screen - .filter({ $0.frame.maxY <= tableVisualBottom }) - .last? - .cellViewModel - { - self.viewModel.markAsRead(beforeInclusive: newestCellViewModel.id) - } + self.markVisibleMessagesAsRead() } func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {