a native ios client for gitbay

client ios swift

https://gitbay.org

gitbay/Repos/RepoSettingsViewModel.swift

ui-smoke
gitbay-ios/gitbay/Repos/RepoSettingsViewModel.swift history · blame · raw

102 lines · 3233 bytes

  1import Foundation
  2import Observation
  3
  4/// The repo settings screen: `repo settings show` for the admin knobs,
  5/// `repo show` for description/topics/visibility, and one write command
  6/// per control. Non-admins get the server's refusal verbatim.
  7@Observable
  8@MainActor
  9final class RepoSettingsViewModel {
 10
 11    nonisolated struct Loaded: Sendable, Hashable {
 12        let settings: RepoSettings
 13        let detail: RepoDetail
 14    }
 15
 16    private(set) var state: LoadState<Loaded> = .loading
 17    private(set) var actionError: String?
 18    private(set) var working = false
 19
 20    private let client: GitbayClient
 21    let repoPath: String
 22
 23    init(client: GitbayClient, repoPath: String) {
 24        self.client = client
 25        self.repoPath = repoPath
 26    }
 27
 28    func load() async {
 29        do {
 30            async let settings = client.read(
 31                ["repo", "settings", "show", repoPath], as: RepoSettings.self)
 32            async let detail = client.read(["repo", "show", repoPath], as: RepoDetail.self)
 33            state = .loaded(Loaded(settings: try await settings, detail: try await detail))
 34        } catch {
 35            state = .from(error)
 36        }
 37    }
 38
 39    // MARK: - Writes, one command per knob
 40
 41    func setDescription(_ text: String) async {
 42        await perform(["repo", "settings", "description", repoPath, text])
 43    }
 44
 45    func setWebsite(_ url: String) async {
 46        await perform(["repo", "settings", "website", repoPath, url])
 47    }
 48
 49    func setVisibility(_ visibility: String) async {
 50        await perform(["repo", "settings", "visibility", repoPath, visibility])
 51    }
 52
 53    func setGitDaemon(_ on: Bool) async {
 54        await perform(["repo", "settings", "git-daemon", repoPath, on ? "on" : "off"])
 55    }
 56
 57    func protectBranch(_ branch: String) async {
 58        await perform(["repo", "settings", "protect", repoPath, branch])
 59    }
 60
 61    func unprotectBranch(_ branch: String) async {
 62        await perform(["repo", "settings", "unprotect", repoPath, branch])
 63    }
 64
 65    func setRequireApprovals(_ count: Int) async {
 66        await perform(["repo", "settings", "require-approvals", repoPath, String(count)])
 67    }
 68
 69    func setRequireResolved(_ on: Bool) async {
 70        await perform(["repo", "settings", "require-resolved", repoPath, on ? "on" : "off"])
 71    }
 72
 73    func setRequireChecks(_ on: Bool) async {
 74        await perform(["repo", "settings", "require-checks", repoPath, on ? "on" : "off"])
 75    }
 76
 77    func setRequireSigned(_ on: Bool) async {
 78        await perform(["repo", "settings", "require-signed", repoPath, on ? "on" : "off"])
 79    }
 80
 81    func addTopic(_ topic: String) async {
 82        await perform(["repo", "topics", "add", repoPath, topic])
 83    }
 84
 85    func removeTopic(_ topic: String) async {
 86        await perform(["repo", "topics", "remove", repoPath, topic])
 87    }
 88
 89    private func perform(_ argv: [String]) async {
 90        working = true
 91        actionError = nil
 92        defer { working = false }
 93        do {
 94            try await client.run(argv)
 95            await load()
 96        } catch let error as GitbayError {
 97            actionError = error.userFacingMessage
 98        } catch {
 99            actionError = GitbayError.transport(error).userFacingMessage
100        }
101    }
102}