Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ extension UpdateTableViewController {
if sender.stringValue.isEmpty {
searchQuery = nil
}
self.scheduleTableViewUpdate(with: self.snapshot.updated(with: searchQuery), animated: false)
self.scheduleSnapshotUpdate(withApps: self.snapshot.apps, filterQuery: searchQuery, animated: false)

// Reload all visible lists
self.scrubber?.reloadData()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,19 @@ import Cocoa
*/
class UpdateTableViewController: NSViewController, NSMenuItemValidation, NSTableViewDataSource, NSTableViewDelegate, NSMenuDelegate, Observer {

private struct SnapshotUpdateRequest {
let apps: [App]
let configuration: AppListSnapshot.Configuration
let animated: Bool
}

var id = UUID()

/// Background queue used to prepare expensive snapshots without blocking the main thread.
private let snapshotQueue = DispatchQueue(label: "UpdateTableViewController.snapshot", qos: .userInitiated)
private var pendingSnapshotUpdate: SnapshotUpdateRequest?
private var snapshotUpdateInProgress = false

/// The array holding the apps that have an update available.
var snapshot: AppListSnapshot = AppListSnapshot(withApps: [], filterQuery: nil) {
didSet {
Expand Down Expand Up @@ -73,8 +84,7 @@ class UpdateTableViewController: NSViewController, NSMenuItemValidation, NSTable
AppListSettings.shared.add(self, handler: self.updateSnapshot)

UpdateCheckCoordinator.shared.appProvider.addObserver(self) { newValue in
self.scheduleTableViewUpdate(with: AppListSnapshot(withApps: newValue, filterQuery: self.snapshot.filterQuery), animated: true)
self.updateTitleAndBatch()
self.scheduleSnapshotUpdate(withApps: newValue, filterQuery: self.snapshot.filterQuery, animated: true)
}

if #available(macOS 11, *) {
Expand Down Expand Up @@ -104,8 +114,7 @@ class UpdateTableViewController: NSViewController, NSMenuItemValidation, NSTable
@IBOutlet weak var tableView: NSTableView!

func updateSnapshot() {
self.scheduleTableViewUpdate(with: self.snapshot.updated(), animated: true)
self.updateTitleAndBatch()
self.scheduleSnapshotUpdate(withApps: self.snapshot.apps, filterQuery: self.snapshot.filterQuery, animated: true)
}


Expand Down Expand Up @@ -251,6 +260,40 @@ class UpdateTableViewController: NSViewController, NSMenuItemValidation, NSTable
/// Whether a table view update is currently ongoing.
private var tableViewUpdateInProgress = false

func scheduleSnapshotUpdate(withApps apps: [App], filterQuery: String?, animated: Bool) {
let request = SnapshotUpdateRequest(
apps: apps,
configuration: AppListSnapshot.Configuration(filterQuery: filterQuery),
animated: animated
)
pendingSnapshotUpdate = request
startNextSnapshotUpdateIfNeeded()
}

private func startNextSnapshotUpdateIfNeeded() {
guard !snapshotUpdateInProgress, let request = pendingSnapshotUpdate else { return }
pendingSnapshotUpdate = nil
snapshotUpdateInProgress = true

snapshotQueue.async {
let snapshot = AppListSnapshot(withApps: request.apps, configuration: request.configuration)

DispatchQueue.main.async {
let shouldAnimate = request.animated && self.shouldAnimateTransition(from: self.snapshot, to: snapshot)
self.scheduleTableViewUpdate(with: snapshot, animated: shouldAnimate)
self.updateTitleAndBatch()
self.snapshotUpdateInProgress = false
self.startNextSnapshotUpdateIfNeeded()
}
}
}

private func shouldAnimateTransition(from oldSnapshot: AppListSnapshot, to newSnapshot: AppListSnapshot) -> Bool {
let maxEntryCount = max(oldSnapshot.entries.count, newSnapshot.entries.count)
let delta = abs(oldSnapshot.entries.count - newSnapshot.entries.count)
return maxEntryCount <= 150 && delta <= 30
}

/// Schedules a table view update with the given snapshot.
func scheduleTableViewUpdate(with snapshot: AppListSnapshot, animated: Bool) {
self.newSnapshot = snapshot
Expand Down
2 changes: 1 addition & 1 deletion Latest/Interface/Main Window/Views/UpdateButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ class UpdateButton: NSButton {
switch state {
case .none:
if let app = self.app, self.showActionButton {
self.updateInterfaceVisibility(with: app.updateAvailable ? .update : .open)
self.updateInterfaceVisibility(with: app.updateAvailable ? (app.canPerformUpdate ? .update : .open) : .open)
} else {
self.updateInterfaceVisibility(with: .none)
}
Expand Down
Loading