]> git.ipfire.org Git - thirdparty/wireguard-apple.git/commitdiff
macOS: Log view: Fix autoscroll to end of log
authorRoopesh Chander <roop@roopc.net>
Mon, 1 Apr 2019 17:06:16 +0000 (22:36 +0530)
committerRoopesh Chander <roop@roopc.net>
Mon, 1 Apr 2019 17:37:48 +0000 (23:07 +0530)
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>
WireGuard/WireGuard/UI/macOS/ViewController/LogViewController.swift

index ddc8c318c5c3b63c381cfefd9474eff286bfdc60..3f3a14bffaf141585b0045f866b1cb9f15be40ae 100644 (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)
         }
     }