krz/hutch
an ios client for sourcehut
clone: git clone https://gitbay.org/krz/hutch.git
v2.6.0: Hutch/Views/Repositories/ReferencesListView.swift · raw
1import SwiftUI
2
3struct ReferencesListView: View {
4 let viewModel: RepositoryDetailViewModel
5
6 var body: some View {
7 List {
8 if !viewModel.branches.isEmpty {
9 Section("Branches") {
10 ForEach(viewModel.branches, id: \.name) { ref in
11 ReferenceRow(reference: ref, prefix: "refs/heads/")
12 }
13 }
14 }
15
16 if !viewModel.tags.isEmpty {
17 Section("Tags") {
18 ForEach(viewModel.tags, id: \.name) { ref in
19 ReferenceRow(reference: ref, prefix: "refs/tags/")
20 }
21 }
22 }
23 }
24 .listStyle(.insetGrouped)
25 .overlay {
26 if viewModel.isLoadingRefs, viewModel.branches.isEmpty, viewModel.tags.isEmpty {
27 SRHTLoadingStateView(message: "Loading references…")
28 } else if let error = viewModel.error, viewModel.branches.isEmpty, viewModel.tags.isEmpty {
29 SRHTErrorStateView(
30 title: "Couldn't Load References",
31 message: error,
32 retryAction: { await viewModel.loadReferences() }
33 )
34 } else if viewModel.branches.isEmpty, viewModel.tags.isEmpty {
35 ContentUnavailableView(
36 "No References",
37 systemImage: "arrow.triangle.branch",
38 description: Text("This repository has no branches or tags.")
39 )
40 }
41 }
42 .task {
43 if viewModel.branches.isEmpty, viewModel.tags.isEmpty {
44 await viewModel.loadReferences()
45 }
46 }
47 .refreshable {
48 await viewModel.loadReferences()
49 }
50 }
51}
52
53private struct ReferenceRow: View {
54 let reference: Reference
55 let prefix: String
56
57 var body: some View {
58 HStack {
59 Label {
60 Text(shortName)
61 .font(.body.monospaced())
62 } icon: {
63 Image(systemName: icon)
64 .foregroundStyle(iconColor)
65 }
66
67 Spacer()
68
69 Text(String((reference.target ?? "").prefix(8)))
70 .font(.caption.monospaced())
71 .foregroundStyle(.secondary)
72 }
73 }
74
75 private var shortName: String {
76 if reference.name.hasPrefix(prefix) {
77 String(reference.name.dropFirst(prefix.count))
78 } else {
79 reference.name
80 }
81 }
82
83 private var icon: String {
84 prefix.contains("tags") ? "tag" : "arrow.triangle.branch"
85 }
86
87 private var iconColor: Color {
88 prefix.contains("tags") ? .orange : .blue
89 }
90}