a native ios client for gitbay

client ios swift

https://gitbay.org

gitbay/Repos/TreeViewModel.swift

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

48 lines · 1514 bytes

 1import Foundation
 2import Observation
 3
 4/// One directory of `repo tree`. Navigation pushes a new instance per
 5/// level, so back is free and each level revalidates independently.
 6@Observable
 7@MainActor
 8final class TreeViewModel {
 9
10    private(set) var state: LoadState<TreeListing> = .loading
11
12    private let client: GitbayClient
13    let repoPath: String
14    let directory: String
15    let ref: String?
16
17    init(client: GitbayClient, repoPath: String, directory: String = "", ref: String? = nil) {
18        self.client = client
19        self.repoPath = repoPath
20        self.directory = directory
21        self.ref = ref
22    }
23
24    /// Directories first, then files, both alphabetically  the ordering
25    /// every forge uses.
26    var entries: [TreeEntry] {
27        guard let listing = state.value else { return [] }
28        return listing.entries.sorted {
29            if $0.isDirectory != $1.isDirectory { return $0.isDirectory }
30            return $0.name.localizedStandardCompare($1.name) == .orderedAscending
31        }
32    }
33
34    func load() async {
35        var argv = ["repo", "tree", repoPath]
36        if !directory.isEmpty { argv.append(directory) }
37        if let ref { argv.append(contentsOf: ["--ref", ref]) }
38        do {
39            state = .loaded(try await client.read(argv, as: TreeListing.self))
40        } catch {
41            state = .from(error)
42        }
43    }
44
45    func childDirectory(_ entry: TreeEntry) -> String {
46        directory.isEmpty ? entry.name : "\(directory)/\(entry.name)"
47    }
48}