a native ios client for gitbay

client ios swift

https://gitbay.org

gitbay/Discovery/ProfileViewModel.swift

ui-smoke
gitbay-ios/gitbay/Discovery/ProfileViewModel.swift history · blame · raw

72 lines · 2174 bytes

 1import Foundation
 2import Observation
 3
 4/// `profile show <name>`  the whole profile in one read: description,
 5/// links, org membership (or an org's members), the repositories the
 6/// account may see, and a year of activity.
 7@Observable
 8@MainActor
 9final class ProfileViewModel {
10
11    nonisolated struct Profile: Decodable, Sendable, Hashable {
12        let name: String
13        let kind: String // user | org
14        let description: String?
15        let website: String?
16        let orgs: [Member]?
17        let members: [Member]?
18        let repos: [Repo]
19        let activity: [Day]?
20        let activityTotal: Int
21
22        enum CodingKeys: String, CodingKey {
23            case name, kind, description, website, orgs, members, repos, activity
24            case activityTotal = "activity_total"
25        }
26
27        var isOrg: Bool { kind == "org" }
28
29        nonisolated struct Member: Decodable, Sendable, Hashable, Identifiable {
30            let name: String
31            let role: String?
32            var id: String { name }
33        }
34
35        nonisolated struct Repo: Decodable, Sendable, Hashable, Identifiable {
36            let path: String
37            let visibility: String
38            let description: String?
39            let archived: Bool?
40
41            var id: String { path }
42            var isPrivate: Bool { visibility == "private" }
43            var isArchived: Bool { archived ?? false }
44            var name: String { String(path.split(separator: "/").last ?? "") }
45        }
46
47        /// One day's contributions. Days with none are omitted, so the
48        /// calendar is filled in by the view.
49        nonisolated struct Day: Decodable, Sendable, Hashable {
50            let date: String
51            let count: Int
52        }
53    }
54
55    private(set) var state: LoadState<Profile> = .loading
56
57    private let client: GitbayClient
58    let name: String
59
60    init(client: GitbayClient, name: String) {
61        self.client = client
62        self.name = name
63    }
64
65    func load() async {
66        do {
67            state = .loaded(try await client.read(["profile", "show", name], as: Profile.self))
68        } catch {
69            state = .from(error)
70        }
71    }
72}