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:
parent
a74dd24578
commit
0043233872
|
@ -76,6 +76,7 @@ class LogViewController: NSViewController {
|
||||||
let logViewHelper: LogViewHelper?
|
let logViewHelper: LogViewHelper?
|
||||||
var logEntries = [LogViewHelper.LogEntry]()
|
var logEntries = [LogViewHelper.LogEntry]()
|
||||||
var isFetchingLogEntries = false
|
var isFetchingLogEntries = false
|
||||||
|
var isInScrolledToEndMode = true
|
||||||
|
|
||||||
private var updateLogEntriesTimer: Timer?
|
private var updateLogEntriesTimer: Timer?
|
||||||
|
|
||||||
|
@ -103,6 +104,21 @@ class LogViewController: NSViewController {
|
||||||
clipView.documentView = tableView
|
clipView.documentView = tableView
|
||||||
scrollView.contentView = clipView
|
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 margin: CGFloat = 20
|
||||||
let internalSpacing: CGFloat = 10
|
let internalSpacing: CGFloat = 10
|
||||||
|
|
||||||
|
@ -155,14 +171,9 @@ class LogViewController: NSViewController {
|
||||||
self.saveButton.isEnabled = true
|
self.saveButton.isEnabled = true
|
||||||
}
|
}
|
||||||
guard !fetchedLogEntries.isEmpty else { return }
|
guard !fetchedLogEntries.isEmpty else { return }
|
||||||
let numOfEntries = self.logEntries.count
|
let oldCount = self.logEntries.count
|
||||||
let lastVisibleRowIndex = self.tableView.row(at: NSPoint(x: 0, y: self.scrollView.contentView.documentVisibleRect.maxY - 1))
|
|
||||||
let isScrolledToEnd = lastVisibleRowIndex == numOfEntries - 1
|
|
||||||
self.logEntries.append(contentsOf: fetchedLogEntries)
|
self.logEntries.append(contentsOf: fetchedLogEntries)
|
||||||
self.tableView.insertRows(at: IndexSet(integersIn: numOfEntries ..< numOfEntries + fetchedLogEntries.count), withAnimation: .slideDown)
|
self.tableView.insertRows(at: IndexSet(integersIn: oldCount ..< oldCount + fetchedLogEntries.count), withAnimation: .slideDown)
|
||||||
if isScrolledToEnd {
|
|
||||||
self.tableView.scrollRowToVisible(self.logEntries.count - 1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue