import Foundation import Observation /// `repo refs` — the branches and tags the server knows, so a ref is /// picked rather than typed. @Observable @MainActor final class RefsViewModel { private(set) var state: LoadState = .loading var searchText = "" private let client: GitbayClient let repoPath: String /// The repo's default branch, marked in the list. private(set) var defaultBranch: String? init(client: GitbayClient, repoPath: String) { self.client = client self.repoPath = repoPath } private func matching(_ refs: [RepoRef]) -> [RepoRef] { let query = searchText.trimmingCharacters(in: .whitespaces).lowercased() guard !query.isEmpty else { return refs } return refs.filter { $0.name.lowercased().contains(query) } } var branches: [RepoRef] { matching(state.value?.branches ?? []) } var tags: [RepoRef] { matching(state.value?.tags ?? []) } func load() async { do { async let refs = client.read(["repo", "refs", repoPath], as: RepoRefs.self) async let detail = try? client.read(["repo", "show", repoPath], as: RepoDetail.self) let loaded = try await refs defaultBranch = await detail?.defaultBranch state = (loaded.branches.isEmpty && loaded.tags.isEmpty) ? .empty("No branches or tags yet.") : .loaded(loaded) } catch { state = .from(error) } } }