From 4a29ad1f4fcd68b6ed47d3b86db7b3a3be22f0b9 Mon Sep 17 00:00:00 2001 From: Morgan Pretty Date: Wed, 22 Jun 2022 18:32:17 +1000 Subject: [PATCH] Fixed a few bugs with scrolling behaviour on the conversation screen Fixed a couple of bugs with in-conversation search --- Session.xcodeproj/project.pbxproj | 8 +- .../Conversations/ConversationSearch.swift | 15 ++- Session/Conversations/ConversationVC.swift | 119 ++++++++---------- .../Types/PagedDatabaseObserver.swift | 2 +- 4 files changed, 66 insertions(+), 78 deletions(-) diff --git a/Session.xcodeproj/project.pbxproj b/Session.xcodeproj/project.pbxproj index a47bfd9a7..19b991c44 100644 --- a/Session.xcodeproj/project.pbxproj +++ b/Session.xcodeproj/project.pbxproj @@ -6818,7 +6818,7 @@ CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CURRENT_PROJECT_VERSION = 346; + CURRENT_PROJECT_VERSION = 350; DEVELOPMENT_TEAM = SUQ8J2PCT7; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -6857,7 +6857,7 @@ "$(SRCROOT)", ); LLVM_LTO = NO; - MARKETING_VERSION = 1.12.9; + MARKETING_VERSION = 2.0.0; OTHER_LDFLAGS = "$(inherited)"; OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\""; PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger"; @@ -6890,7 +6890,7 @@ CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CURRENT_PROJECT_VERSION = 346; + CURRENT_PROJECT_VERSION = 350; DEVELOPMENT_TEAM = SUQ8J2PCT7; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -6929,7 +6929,7 @@ "$(SRCROOT)", ); LLVM_LTO = NO; - MARKETING_VERSION = 1.12.9; + MARKETING_VERSION = 2.0.0; OTHER_LDFLAGS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger"; PRODUCT_NAME = Session; diff --git a/Session/Conversations/ConversationSearch.swift b/Session/Conversations/ConversationSearch.swift index c0c0b6279..f1e365b37 100644 --- a/Session/Conversations/ConversationSearch.swift +++ b/Session/Conversations/ConversationSearch.swift @@ -218,12 +218,15 @@ public final class SearchResultsBar: UIView { } func updateResults(results: [Int64]?) { - if let results: [Int64] = results, !results.isEmpty { - currentIndex = min(currentIndex ?? 0, results.count - 1) - } - else { - currentIndex = nil - } + currentIndex = { + guard let results: [Int64] = results, !results.isEmpty else { return nil } + + if let currentIndex: Int = currentIndex { + return max(0, min(currentIndex, results.count - 1)) + } + + return 0 + }() self.results = results diff --git a/Session/Conversations/ConversationVC.swift b/Session/Conversations/ConversationVC.swift index 993c9e8b0..3ac99bbdb 100644 --- a/Session/Conversations/ConversationVC.swift +++ b/Session/Conversations/ConversationVC.swift @@ -715,10 +715,10 @@ final class ConversationVC: BaseVC, OWSConversationSettingsViewDelegate, Convers // If anything was inserted at the top then we need to maintain the current // offset so always return a 'top' insert location - switch (insertedAtTop, insertedAtBot) { - case (true, _): return .top - case (false, true): return .bottom - case (false, false): return .other + switch (insertedAtTop, insertedAtBot, isLoadingMore) { + case (true, _, true), (true, false, false): return .top + case (false, true, _): return .bottom + case (false, false, _), (true, true, false): return .other } }(), wasCloseToBottom: isCloseToBottom, @@ -737,7 +737,7 @@ final class ConversationVC: BaseVC, OWSConversationSettingsViewDelegate, Convers /// /// Unfortunately the UITableView also does some weird things when updating (where it won't have updated it's internal data until /// after it performs the next layout); the below code checks a condition on layout and if it passes it calls a closure - if itemChangeInfo.insertLocation != .none { + if itemChangeInfo.insertLocation == .top { let cellSorting: (MessageCell, MessageCell) -> Bool = { lhs, rhs -> Bool in if !lhs.isHidden && rhs.isHidden { return true } if lhs.isHidden && !rhs.isHidden { return false } @@ -750,9 +750,12 @@ final class ConversationVC: BaseVC, OWSConversationSettingsViewDelegate, Convers .first(where: { cell -> Bool in cell.viewModel?.id == itemChangeInfo.visibleInteractionId })? .frame) .defaulting(to: self.tableView.rectForRow(at: itemChangeInfo.oldVisibleIndexPath)) - let oldContentSize: CGSize = self.tableView.contentSize - let oldOffsetFromTop: CGFloat = (self.tableView.contentOffset.y - oldRect.minY) - let oldOffsetFromBottom: CGFloat = (oldContentSize.height - self.tableView.contentOffset.y) + + // The the user triggered the 'scrollToTop' animation (by tapping in the nav bar) then we + // need to stop the animation before attempting to lock the offset (otherwise things break) + if itemChangeInfo.firstIndexIsVisible { + self.tableView.setContentOffset(self.tableView.contentOffset, animated: false) + } // Wait until the tableView has completed a layout and reported the correct number of // sections/rows and then update the contentOffset @@ -763,63 +766,26 @@ final class ConversationVC: BaseVC, OWSConversationSettingsViewDelegate, Convers }, then: { [weak self] in UIView.performWithoutAnimation { - self?.tableView.scrollToRow( - at: (itemChangeInfo.insertLocation == .top ? - itemChangeInfo.visibleIndexPath : - itemChangeInfo.lastVisibleIndexPath - ), - at: (itemChangeInfo.insertLocation == .top ? - .top : - .bottom - ), - animated: false - ) - self?.tableView.layoutIfNeeded() - - let newContentSize: CGSize = (self?.tableView.contentSize) - .defaulting(to: oldContentSize) - - /// **Note:** I wasn't able to get a prober equation to handle both "insert" and "insert at top off screen", it - /// seems that the 'contentOffset' value won't expose negative values (eg. when you over-scroll and trigger - /// the bounce effect) and this results in requiring the conditional logic below - if itemChangeInfo.insertLocation == .top { - let newRect: CGRect = (self?.tableView.subviews - .compactMap { $0 as? MessageCell } - .sorted(by: cellSorting) - .first(where: { $0.viewModel?.id == itemChangeInfo.visibleInteractionId })? - .frame) - .defaulting(to: oldRect) - let heightDiff: CGFloat = (oldRect.height - newRect.height) - - if itemChangeInfo.firstIndexIsVisible { - self?.tableView.contentOffset.y = (newRect.minY - (oldRect.minY + heightDiff)) + let calculatedRowHeights: CGFloat = (0..: TransactionObserver where let targetIndex: Int = maybeIndex.map({ max(0, min(totalCount, $0)) }), ( targetIndex < currentPageInfo.pageOffset || - targetIndex > cacheCurrentEndIndex + targetIndex >= cacheCurrentEndIndex ) else { return nil }