summaryrefslogtreecommitdiff
path: root/Hutch/Views/Repositories/RepositoryListViewModel.swift
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-04-12 22:52:33 -0500
committerChristian Cleberg <[email protected]>2026-04-12 22:52:33 -0500
commit72f860e0e171f6aac4e7d896e7a571147dbcb5c5 (patch)
treec62c9c9325292f65e6f72372a38b35760cc937b1 /Hutch/Views/Repositories/RepositoryListViewModel.swift
parent576bb6c2432a15f5138771c06019b55fd2244e15 (diff)
downloadhutch-72f860e0e171f6aac4e7d896e7a571147dbcb5c5.tar.gz
hutch-72f860e0e171f6aac4e7d896e7a571147dbcb5c5.tar.bz2
hutch-72f860e0e171f6aac4e7d896e7a571147dbcb5c5.zip
feat: add search and recent queries
Implements: https://todo.sr.ht/~ccleberg/hutch/47 Implements: https://todo.sr.ht/~ccleberg/hutch/48
Diffstat (limited to 'Hutch/Views/Repositories/RepositoryListViewModel.swift')
-rw-r--r--Hutch/Views/Repositories/RepositoryListViewModel.swift36
1 files changed, 34 insertions, 2 deletions
diff --git a/Hutch/Views/Repositories/RepositoryListViewModel.swift b/Hutch/Views/Repositories/RepositoryListViewModel.swift
index 7a65441..0cfc8c3 100644
--- a/Hutch/Views/Repositories/RepositoryListViewModel.swift
+++ b/Hutch/Views/Repositories/RepositoryListViewModel.swift
@@ -25,9 +25,11 @@ enum RepositoryCreationService: String, CaseIterable, Identifiable, Sendable {
@Observable
@MainActor
final class RepositoryListViewModel {
+ private static let searchHistoryScopeID = "repositories"
private(set) var repositories: [RepositorySummary] = []
private(set) var latestBuildStatuses: [String: RepositoryBuildStatus] = [:]
+ private(set) var recentSearches: [ScopedSearchHistoryEntry]
private(set) var isLoading = false
private(set) var isLoadingMore = false
private(set) var isRefreshing = false
@@ -42,6 +44,7 @@ final class RepositoryListViewModel {
private(set) var hasLoadedSearchIndex = false
private var searchIndex: [RepositorySummary] = []
private let client: SRHTClient
+ private let defaults: UserDefaults
private var buildStatusTask: Task<Void, Never>?
private static let gitCacheKey = "git.repositories"
@@ -49,8 +52,13 @@ final class RepositoryListViewModel {
private static let buildsCacheKey = "builds.repository-status"
private static let minimumRemoteSearchLength = 3
- init(client: SRHTClient) {
+ init(client: SRHTClient, defaults: UserDefaults = .standard) {
self.client = client
+ self.defaults = defaults
+ self.recentSearches = ScopedSearchHistoryStore.load(
+ scopeID: Self.searchHistoryScopeID,
+ defaults: defaults
+ )
}
// MARK: - Queries
@@ -302,6 +310,26 @@ final class RepositoryListViewModel {
isSearching = false
}
+ func recordRecentSearch(_ query: String) {
+ ScopedSearchHistoryStore.record(
+ query: query,
+ scopeID: Self.searchHistoryScopeID,
+ defaults: defaults
+ )
+ recentSearches = ScopedSearchHistoryStore.load(
+ scopeID: Self.searchHistoryScopeID,
+ defaults: defaults
+ )
+ }
+
+ func clearRecentSearches() {
+ ScopedSearchHistoryStore.clear(
+ scopeID: Self.searchHistoryScopeID,
+ defaults: defaults
+ )
+ recentSearches = []
+ }
+
// MARK: - Private
/// Page shape matching the GraphQL response without generic constraints that
@@ -696,9 +724,13 @@ final class RepositoryListViewModel {
}
static func filterRepositories(_ repositories: [RepositorySummary], matching query: String) -> [RepositorySummary] {
- let lowercasedQuery = query.lowercased()
+ let lowercasedQuery = query.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
+ guard !lowercasedQuery.isEmpty else { return repositories }
+
return repositories.filter { repo in
repo.name.lowercased().contains(lowercasedQuery) ||
+ repo.owner.canonicalName.lowercased().contains(lowercasedQuery) ||
+ repo.defaultBranchName?.lowercased().contains(lowercasedQuery) ?? false ||
repo.description?.lowercased().contains(lowercasedQuery) ?? false
}
}