diff options
| author | Christian Cleberg <[email protected]> | 2026-04-02 00:17:30 -0500 |
|---|---|---|
| committer | Christian Cleberg <[email protected]> | 2026-04-02 00:17:30 -0500 |
| commit | 7f79cadf99ecf014834855e2e4a5c7d60dd709ac (patch) | |
| tree | e1435c08b416390064e0d2772d6a7703a1737db1 /Hutch/Views/Lookup/UserProfileViewModel.swift | |
| parent | cd19a6fb24ebd5550068a28c0daefd07697bebda (diff) | |
| download | hutch-2.9.0.tar.gz hutch-2.9.0.tar.bz2 hutch-2.9.0.zip | |
feat: browse user repositories and trackers from profilev2.9.0
Diffstat (limited to 'Hutch/Views/Lookup/UserProfileViewModel.swift')
| -rw-r--r-- | Hutch/Views/Lookup/UserProfileViewModel.swift | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/Hutch/Views/Lookup/UserProfileViewModel.swift b/Hutch/Views/Lookup/UserProfileViewModel.swift new file mode 100644 index 0000000..bec79fb --- /dev/null +++ b/Hutch/Views/Lookup/UserProfileViewModel.swift @@ -0,0 +1,151 @@ +import Foundation + +@Observable +@MainActor +final class UserProfileViewModel { + private(set) var repositories: [RepositorySummary] = [] + private(set) var trackers: [TrackerSummary] = [] + private(set) var isLoadingRepositories = false + private(set) var isLoadingTrackers = false + var repositoriesError: String? + var trackersError: String? + + private let client: SRHTClient + let ownerUsername: String + + init(ownerUsername: String, client: SRHTClient) { + self.ownerUsername = ownerUsername + self.client = client + } + + func loadRepositories() async { + isLoadingRepositories = true + repositoriesError = nil + defer { isLoadingRepositories = false } + + do { + let result = try await client.execute( + service: .git, + query: Self.repositoriesQuery, + variables: ["owner": ownerUsername], + responseType: UserRepositoriesResponse.self + ) + repositories = result.user.repositories.results.map { $0.repositorySummary(service: .git) } + } catch { + repositoriesError = error.userFacingMessage + } + } + + func loadTrackers() async { + isLoadingTrackers = true + trackersError = nil + defer { isLoadingTrackers = false } + + do { + let result = try await client.execute( + service: .todo, + query: Self.trackersQuery, + variables: ["owner": ownerUsername], + responseType: UserTrackersResponse.self + ) + trackers = result.user.trackers.results + } catch { + trackersError = error.userFacingMessage + } + } + + private static let repositoriesQuery = """ + query userRepositories($owner: String!) { + user(username: $owner) { + repositories { + results { + id + rid + name + description + visibility + updated + owner { canonicalName } + HEAD { name target } + } + cursor + } + } + } + """ + + private static let trackersQuery = """ + query userTrackers($owner: String!) { + user(username: $owner) { + trackers { + results { + id + rid + name + description + visibility + updated + owner { canonicalName } + } + cursor + } + } + } + """ + + private struct UserRepositoriesResponse: Decodable, Sendable { + let user: UserRepositoriesContainer + } + + private struct UserRepositoriesContainer: Decodable, Sendable { + let repositories: RepositoriesPage + } + + private struct RepositoriesPage: Decodable, Sendable { + let results: [RepositoryPayload] + let cursor: String? + } + + private struct RepositoryPayload: Decodable, Sendable { + let id: Int + let rid: String + let name: String + let description: String? + let visibility: Visibility + let updated: Date + let owner: Entity + let head: Reference? + + enum CodingKeys: String, CodingKey { + case id, rid, name, description, visibility, updated, owner + case head = "HEAD" + } + + func repositorySummary(service: SRHTService) -> RepositorySummary { + RepositorySummary( + id: id, + rid: rid, + service: service, + name: name, + description: description, + visibility: visibility, + updated: updated, + owner: owner, + head: head + ) + } + } + + private struct UserTrackersResponse: Decodable, Sendable { + let user: UserTrackersContainer + } + + private struct UserTrackersContainer: Decodable, Sendable { + let trackers: TrackersPage + } + + private struct TrackersPage: Decodable, Sendable { + let results: [TrackerSummary] + let cursor: String? + } +} |
