gitbay/Snippets/SnippetListViewModel.swift

36835f99e6d463f3e18c5c3fc3562bb92513f52b
gitbay-ios/gitbay/Snippets/SnippetListViewModel.swift history · blame · raw

65 lines · 2380 bytes

3 symbols in this file
 1import Foundation
 2import Observation
 3
 4/// `snippet list` — the caller's own snippets at every visibility, or an
 5/// owner's public ones — paginated, plus `snippet create`.
 6@Observable
 7@MainActor
 8final class SnippetListViewModel {
 9
10    let list: PagedListModel<Snippet>
11    /// nil lists the caller's own.
12    let owner: String?
13    private(set) var actionError: String?
14    private(set) var working = false
15
16    private let client: GitbayClient
17
18    init(client: GitbayClient, owner: String?) {
19        self.client = client
20        self.owner = owner
21        list = PagedListModel(
22            client: client,
23            argv: ["snippet", "list"] + (owner.map { [$0] } ?? []),
24            emptyMessage: owner == nil
25                ? "No snippets yet. Create one from the + button."
26                : "\(owner ?? "") has no public snippets."
27        )
28    }
29
30    var state: LoadState<[Snippet]> { list.state }
31
32    func load() async {
33        await list.reload()
34    }
35
36    /// `snippet create <filename> [--description <d>] [--visibility <v>]
37    /// < file` — the file is bare stdin. An empty description sends no
38    /// flag. Returns the created snippet, or nil with `actionError` set.
39    func create(filename: String, description: String, visibility: String, content: String) async -> Snippet? {
40        var argv = ["snippet", "create", filename.trimmingCharacters(in: .whitespaces)]
41        let description = description.trimmingCharacters(in: .whitespacesAndNewlines)
42        if !description.isEmpty { argv += ["--description", description] }
43        argv += ["--visibility", visibility]
44        working = true
45        actionError = nil
46        defer { working = false }
47        do {
48            let created = try await client.run(argv, stdin: content, as: Snippet.self)
49            await list.reload()
50            return created
51        } catch let error as GitbayError {
52            // Exit 2 here is the server validating the file name, the
53            // size or the per-account cap — written for the person.
54            if case .usage(let message) = error, !message.isEmpty {
55                actionError = message
56            } else {
57                actionError = error.userFacingMessage
58            }
59            return nil
60        } catch {
61            actionError = GitbayError.transport(error).userFacingMessage
62            return nil
63        }
64    }
65}