gitbay/Issues/LabelListViewModel.swift

v1.0.7
gitbay-ios/gitbay/Issues/LabelListViewModel.swift history · blame · raw

61 lines · 1902 bytes

 1import Foundation
 2import Observation
 3
 4/// `label list <repo>`, plus the two commands that change the set:
 5/// `label set` creates one or recolours it, `label remove` takes it off
 6/// the repository and off every issue that carried it.
 7@Observable
 8@MainActor
 9final class LabelListViewModel {
10
11    private(set) var state: LoadState<[IssueLabel]> = .loading
12    private(set) var actionError: String?
13    private(set) var working = false
14
15    private let client: GitbayClient
16    let repoPath: String
17
18    init(client: GitbayClient, repoPath: String) {
19        self.client = client
20        self.repoPath = repoPath
21    }
22
23    func load() async {
24        state = .loading
25        do {
26            let labels = try await client.readList(
27                ["label", "list", repoPath], of: IssueLabel.self
28            )
29            state = labels.isEmpty ? .empty("No labels yet.") : .loaded(labels)
30        } catch {
31            state = .from(error)
32        }
33    }
34
35    /// Create a label or set its colour. A nil colour omits `--color`
36    /// entirely, which the server reads as "make sure it exists" and
37    /// leaves any colour it already had; an empty string clears it.
38    func setLabel(_ name: String, color: String?) async {
39        var argv = ["label", "set", repoPath, name]
40        if let color { argv.append(contentsOf: ["--color", color]) }
41        await perform(argv)
42    }
43
44    func remove(_ name: String) async {
45        await perform(["label", "remove", repoPath, name])
46    }
47
48    private func perform(_ argv: [String]) async {
49        working = true
50        actionError = nil
51        defer { working = false }
52        do {
53            try await client.run(argv)
54            await load()
55        } catch let error as GitbayError {
56            actionError = error.userFacingMessage
57        } catch {
58            actionError = GitbayError.transport(error).userFacingMessage
59        }
60    }
61}