a native ios client for gitbay

client ios swift

https://gitbay.org

gitbay/Repos/FileViewModel.swift

main
gitbay-ios/gitbay/Repos/FileViewModel.swift history · blame · raw

71 lines · 2396 bytes

 1import Foundation
 2import Observation
 3
 4/// One file via `repo cat`: text renders (highlighted when the language is
 5/// known), binary says so, truncated says so  never a guess.
 6@Observable
 7@MainActor
 8final class FileViewModel {
 9
10    private(set) var state: LoadState<FileContent> = .loading
11    private(set) var actionError: String?
12    private(set) var working = false
13
14    private let client: GitbayClient
15    let repoPath: String
16    let filePath: String
17    let ref: String?
18
19    init(client: GitbayClient, repoPath: String, filePath: String, ref: String? = nil) {
20        self.client = client
21        self.repoPath = repoPath
22        self.filePath = filePath
23        self.ref = ref
24    }
25
26    var fileName: String {
27        String(filePath.split(separator: "/").last ?? "")
28    }
29
30    func load() async {
31        var argv = ["repo", "cat", repoPath, filePath]
32        if let ref { argv.append(contentsOf: ["--ref", ref]) }
33        do {
34            state = .loaded(try await client.read(argv, as: FileContent.self))
35        } catch {
36            state = .from(error)
37        }
38    }
39
40    /// The branch an edit commits to. `repo cat` echoes the ref it read,
41    /// so editing writes back to whatever is on screen.
42    var editableBranch: String? {
43        guard let file = state.value, !file.binary, !file.isTruncated else { return nil }
44        return file.ref
45    }
46
47    /// `repo commit-file`  the server refuses when the repository wants
48    /// signed commits, when the account has no verified email, or when
49    /// the repo is archived, and says which.
50    func commit(content: String, message: String) async -> Bool {
51        guard let branch = editableBranch else { return false }
52        working = true
53        actionError = nil
54        defer { working = false }
55        var argv = ["repo", "commit-file", repoPath, filePath, "--ref", branch, "--file", "-"]
56        let trimmed = message.trimmingCharacters(in: .whitespacesAndNewlines)
57        if !trimmed.isEmpty {
58            argv.append(contentsOf: ["--message", trimmed])
59        }
60        do {
61            try await client.run(argv, stdin: content)
62            await load()
63            return true
64        } catch let error as GitbayError {
65            actionError = error.userFacingMessage
66        } catch {
67            actionError = GitbayError.transport(error).userFacingMessage
68        }
69        return false
70    }
71}