summaryrefslogtreecommitdiff
path: root/Hutch/Views/Builds
diff options
context:
space:
mode:
Diffstat (limited to 'Hutch/Views/Builds')
-rw-r--r--Hutch/Views/Builds/BuildListView.swift1
-rw-r--r--Hutch/Views/Builds/BuildListViewModel.swift35
-rw-r--r--Hutch/Views/Builds/BuildRowView.swift2
3 files changed, 29 insertions, 9 deletions
diff --git a/Hutch/Views/Builds/BuildListView.swift b/Hutch/Views/Builds/BuildListView.swift
index 6f3f934..d525918 100644
--- a/Hutch/Views/Builds/BuildListView.swift
+++ b/Hutch/Views/Builds/BuildListView.swift
@@ -137,6 +137,7 @@ struct BuildListView: View {
ForEach(viewModel.filteredJobs) { job in
NavigationLink(value: job) {
BuildRowView(job: job)
+ .equatable()
}
.contextMenu {
Button {
diff --git a/Hutch/Views/Builds/BuildListViewModel.swift b/Hutch/Views/Builds/BuildListViewModel.swift
index c6f8e49..643bacd 100644
--- a/Hutch/Views/Builds/BuildListViewModel.swift
+++ b/Hutch/Views/Builds/BuildListViewModel.swift
@@ -46,18 +46,33 @@ enum AutoRefreshInterval: Int, CaseIterable, Sendable {
final class BuildListViewModel {
private static let searchHistoryScopeID = "builds"
- private(set) var jobs: [JobSummary] = []
+ private(set) var jobs: [JobSummary] = [] {
+ didSet { updateFilteredJobs() }
+ }
private(set) var recentSearches: [ScopedSearchHistoryEntry]
private(set) var isLoading = false
private(set) var isLoadingMore = false
private(set) var isRefreshing = false
private(set) var isSubmitting = false
var error: String?
- var filter: BuildListFilter = .attention
- var searchText = ""
+ var filter: BuildListFilter = .attention {
+ didSet { updateFilteredJobs() }
+ }
+ var searchText = "" {
+ didSet { updateFilteredJobs() }
+ }
var repoFilter: String = "" {
- didSet { if repoFilter != oldValue { repoFilterDidChange() } }
+ didSet {
+ guard repoFilter != oldValue else { return }
+ repoFilterDidChange()
+ updateFilteredJobs()
+ }
}
+ // Cached filtered result. Updated whenever jobs, filter, searchText, or
+ // repoFilter changes. Only notifies observers when the content actually
+ // differs, which prevents the list from re-rendering on auto-refresh when
+ // no visible data changed.
+ private(set) var filteredJobs: [JobSummary] = []
private var cursor: String?
private var hasMore = true
@@ -83,14 +98,18 @@ final class BuildListViewModel {
return allTags.sorted { $0.localizedCaseInsensitiveCompare($1) == .orderedAscending }
}
- var filteredJobs: [JobSummary] {
+ private func updateFilteredJobs() {
var result = Self.filterJobs(jobs, filter: filter)
-
if !repoFilter.isEmpty {
result = result.filter { $0.tags.contains(repoFilter) }
}
-
- return Self.searchJobs(result, matching: searchText)
+ let updated = Self.searchJobs(result, matching: searchText)
+ // Skip the assignment (and the resulting observer notification) when the
+ // filtered list hasn't actually changed — e.g. on auto-refresh when no
+ // builds have been added or updated.
+ if updated != filteredJobs {
+ filteredJobs = updated
+ }
}
// MARK: - Auto-Refresh
diff --git a/Hutch/Views/Builds/BuildRowView.swift b/Hutch/Views/Builds/BuildRowView.swift
index 9602e5c..a490123 100644
--- a/Hutch/Views/Builds/BuildRowView.swift
+++ b/Hutch/Views/Builds/BuildRowView.swift
@@ -1,6 +1,6 @@
import SwiftUI
-struct BuildRowView: View {
+struct BuildRowView: View, Equatable {
let job: JobSummary
var body: some View {