macOS: Log view: Fix autoscroll to end of log

Looks like the tableview doesn't know how much to scroll to get to the
end when we use usesAutomaticRowHeights. So we wait for the tableview
to realize its frame has changed and then scroll to the bottom of the
frame explicitly.

Also, we keep track of whether the scroll view is scrolled to the end or
not every time scrolling happens, not just when we add log entries to
the table.

Signed-off-by: Roopesh Chander <roop@roopc.net>
This commit is contained in:
Roopesh Chander 2019-04-01 22:36:16 +05:30
parent a74dd24578
commit 0043233872
1 changed files with 18 additions and 7 deletions

View File

@ -76,6 +76,7 @@ class LogViewController: NSViewController {
let logViewHelper: LogViewHelper?
var logEntries = [LogViewHelper.LogEntry]()
var isFetchingLogEntries = false
var isInScrolledToEndMode = true
private var updateLogEntriesTimer: Timer?
@ -103,6 +104,21 @@ class LogViewController: NSViewController {
clipView.documentView = tableView
scrollView.contentView = clipView
_ = NotificationCenter.default.addObserver(forName: NSView.boundsDidChangeNotification, object: clipView, queue: OperationQueue.main) { [weak self] _ in
guard let self = self else { return }
let lastVisibleRowIndex = self.tableView.row(at: NSPoint(x: 0, y: self.scrollView.contentView.documentVisibleRect.maxY - 1))
self.isInScrolledToEndMode = lastVisibleRowIndex < 0 || lastVisibleRowIndex == self.logEntries.count - 1
}
_ = NotificationCenter.default.addObserver(forName: NSView.frameDidChangeNotification, object: tableView, queue: OperationQueue.main) { [weak self] _ in
guard let self = self else { return }
if self.isInScrolledToEndMode {
DispatchQueue.main.async {
self.tableView.scroll(NSPoint(x: 0, y: self.tableView.frame.maxY - clipView.documentVisibleRect.height))
}
}
}
let margin: CGFloat = 20
let internalSpacing: CGFloat = 10
@ -155,14 +171,9 @@ class LogViewController: NSViewController {
self.saveButton.isEnabled = true
}
guard !fetchedLogEntries.isEmpty else { return }
let numOfEntries = self.logEntries.count
let lastVisibleRowIndex = self.tableView.row(at: NSPoint(x: 0, y: self.scrollView.contentView.documentVisibleRect.maxY - 1))
let isScrolledToEnd = lastVisibleRowIndex == numOfEntries - 1
let oldCount = self.logEntries.count
self.logEntries.append(contentsOf: fetchedLogEntries)
self.tableView.insertRows(at: IndexSet(integersIn: numOfEntries ..< numOfEntries + fetchedLogEntries.count), withAnimation: .slideDown)
if isScrolledToEnd {
self.tableView.scrollRowToVisible(self.logEntries.count - 1)
}
self.tableView.insertRows(at: IndexSet(integersIn: oldCount ..< oldCount + fetchedLogEntries.count), withAnimation: .slideDown)
}
}