gitbay/Repos/WebhookViewModels.swift

v1.4.0
gitbay-ios/gitbay/Repos/WebhookViewModels.swift history · blame · raw

105 lines · 3263 bytes

  1import Foundation
  2import Observation
  3
  4/// `webhook list`, `webhook add` and `webhook remove` for one repository.
  5@Observable
  6@MainActor
  7final class WebhookListViewModel {
  8
  9    private(set) var state: LoadState<[Webhook]> = .loading
 10    private(set) var actionError: String?
 11    private(set) var working = false
 12
 13    private let client: GitbayClient
 14    let repoPath: String
 15
 16    init(client: GitbayClient, repoPath: String) {
 17        self.client = client
 18        self.repoPath = repoPath
 19    }
 20
 21    func load() async {
 22        state = .loading
 23        do {
 24            let hooks = try await client.readList(["webhook", "list", repoPath], of: Webhook.self)
 25            state = hooks.isEmpty ? .empty("No webhooks yet.") : .loaded(hooks)
 26        } catch {
 27            state = .from(error)
 28        }
 29    }
 30
 31    /// `webhook add <repo> <url> [--secret <s>] [--events <e>]` — an empty
 32    /// secret or event list is left out, so the server applies its default.
 33    func add(url: String, secret: String, events: String) async -> Bool {
 34        let url = url.trimmingCharacters(in: .whitespaces)
 35        guard !url.isEmpty else { return false }
 36        var argv = ["webhook", "add", repoPath, url]
 37        let secret = secret.trimmingCharacters(in: .whitespaces)
 38        if !secret.isEmpty { argv += ["--secret", secret] }
 39        let events = events.trimmingCharacters(in: .whitespaces)
 40        if !events.isEmpty { argv += ["--events", events] }
 41        await perform(argv)
 42        return actionError == nil
 43    }
 44
 45    func remove(id: Int64) async {
 46        await perform(["webhook", "remove", repoPath, String(id)])
 47    }
 48
 49    private func perform(_ argv: [String]) async {
 50        working = true
 51        actionError = nil
 52        defer { working = false }
 53        do {
 54            try await client.run(argv)
 55            await load()
 56        } catch let error as GitbayError {
 57            actionError = error.userFacingMessage
 58        } catch {
 59            actionError = GitbayError.transport(error).userFacingMessage
 60        }
 61    }
 62}
 63
 64/// `webhook deliveries` and `webhook redeliver`.
 65@Observable
 66@MainActor
 67final class WebhookDeliveriesViewModel {
 68
 69    private(set) var state: LoadState<[WebhookDelivery]> = .loading
 70    private(set) var actionError: String?
 71    private(set) var working = false
 72
 73    private let client: GitbayClient
 74    let repoPath: String
 75
 76    init(client: GitbayClient, repoPath: String) {
 77        self.client = client
 78        self.repoPath = repoPath
 79    }
 80
 81    func load() async {
 82        state = .loading
 83        do {
 84            let rows = try await client.readList(
 85                ["webhook", "deliveries", repoPath], of: WebhookDelivery.self)
 86            state = rows.isEmpty ? .empty("No deliveries yet.") : .loaded(rows)
 87        } catch {
 88            state = .from(error)
 89        }
 90    }
 91
 92    func redeliver(id: Int64) async {
 93        working = true
 94        actionError = nil
 95        defer { working = false }
 96        do {
 97            try await client.run(["webhook", "redeliver", repoPath, String(id)])
 98            await load()
 99        } catch let error as GitbayError {
100            actionError = error.userFacingMessage
101        } catch {
102            actionError = GitbayError.transport(error).userFacingMessage
103        }
104    }
105}