gitbay/Views/Repos/RefsView.swift
76 lines · 2462 bytes
1import SwiftUI
2
3/// Branches and tags. Tapping one browses the repository at that ref.
4struct RefsView: View {
5
6 @State private var model: RefsViewModel
7
8 init(client: GitbayClient, repo: String) {
9 _model = State(initialValue: RefsViewModel(client: client, repoPath: repo))
10 }
11
12 var body: some View {
13 List {
14 Section {
15 NavigationLink(value: RepoRoute.compare(
16 repo: model.repoPath, defaultBranch: model.defaultBranch
17 )) {
18 Label("Compare", systemImage: "arrow.left.arrow.right")
19 }
20 }
21 if !model.branches.isEmpty {
22 Section("Branches") {
23 ForEach(model.branches) { ref in
24 NavigationLink(value: RepoRoute.tree(
25 repo: model.repoPath, directory: "", ref: ref.name
26 )) {
27 RefRow(ref: ref, isDefault: ref.name == model.defaultBranch)
28 }
29 }
30 }
31 }
32 if !model.tags.isEmpty {
33 Section("Tags") {
34 ForEach(model.tags) { ref in
35 NavigationLink(value: RepoRoute.tree(
36 repo: model.repoPath, directory: "", ref: ref.name
37 )) {
38 RefRow(ref: ref, isDefault: false)
39 }
40 }
41 }
42 }
43 }
44 .overlay {
45 LoadStateOverlay(
46 state: model.state,
47 isEmpty: model.branches.isEmpty && model.tags.isEmpty
48 )
49 }
50 .searchable(text: Bindable(model).searchText, prompt: "Filter refs")
51 .navigationTitle("Branches & Tags")
52 .navigationBarTitleDisplayMode(.inline)
53 .task { await model.load() }
54 .refreshable { await model.load() }
55 }
56}
57
58private struct RefRow: View {
59 let ref: RepoRef
60 let isDefault: Bool
61
62 var body: some View {
63 HStack(spacing: 8) {
64 Text(ref.name)
65 .font(.gbSans(.subheadline))
66 .lineLimit(1)
67 if isDefault {
68 GBChip("default", .gbAccent)
69 }
70 Spacer()
71 Text(String(ref.sha.prefix(10)))
72 .font(.gbMono(.caption2))
73 .foregroundStyle(.tertiary)
74 }
75 }
76}