krz/hutch
an ios client for sourcehut
clone: git clone https://gitbay.org/krz/hutch.git
v2.1: Hutch/Views/Repositories/RepositoryRowView.swift · raw
1import SwiftUI
2
3struct RepositoryRowView: View {
4 let repository: RepositorySummary
5 let buildStatus: RepositoryBuildStatus
6
7 var body: some View {
8 VStack(alignment: .leading, spacing: 4) {
9 HStack(alignment: .firstTextBaseline) {
10 Text(repository.name)
11 .font(.headline)
12
13 Spacer()
14
15 if repository.service == .hg {
16 Text("HG")
17 .font(.caption2.weight(.medium))
18 .padding(.horizontal, 6)
19 .padding(.vertical, 2)
20 .background(Color.cyan.opacity(0.15), in: Capsule())
21 .foregroundStyle(.cyan)
22 }
23
24 if buildStatus != .none {
25 RepositoryBuildStatusIndicator(status: buildStatus)
26 }
27 VisibilityBadge(visibility: repository.visibility)
28 }
29
30 Text(repository.owner.canonicalName)
31 .font(.subheadline)
32 .foregroundStyle(.secondary)
33
34 if let description = repository.description,
35 !description.isEmpty {
36 Text(description)
37 .font(.subheadline)
38 .foregroundStyle(.secondary)
39 .lineLimit(2)
40 }
41
42 HStack(spacing: 12) {
43 if let head = repository.head {
44 Label(head.name, systemImage: "arrow.triangle.branch")
45 .font(.caption)
46 .foregroundStyle(.secondary)
47 }
48
49 Spacer()
50
51 Text(repository.updated.relativeDescription)
52 .font(.caption)
53 .foregroundStyle(.tertiary)
54 }
55 }
56 .padding(.vertical, 2)
57 }
58}
59
60private struct RepositoryBuildStatusIndicator: View {
61 let status: RepositoryBuildStatus
62
63 var body: some View {
64 Circle()
65 .fill(color)
66 .frame(width: 8, height: 8)
67 .overlay {
68 Circle()
69 .strokeBorder(.primary.opacity(0.08))
70 }
71 .accessibilityLabel(accessibilityLabel)
72 }
73
74 private var color: Color {
75 switch status {
76 case .success:
77 .green
78 case .failed:
79 .red
80 case .running:
81 .orange
82 case .none:
83 .clear
84 }
85 }
86
87 private var accessibilityLabel: String {
88 switch status {
89 case .success:
90 "Latest build succeeded"
91 case .failed:
92 "Latest build failed"
93 case .running:
94 "Latest build is running"
95 case .none:
96 "No recent builds"
97 }
98 }
99}
100
101// MARK: - VisibilityBadge
102
103struct VisibilityBadge: View {
104 let visibility: Visibility
105
106 var body: some View {
107 Text(label)
108 .font(.caption2.weight(.medium))
109 .padding(.horizontal, 6)
110 .padding(.vertical, 2)
111 .background(color.opacity(0.15), in: Capsule())
112 .foregroundStyle(color)
113 }
114
115 private var label: String {
116 switch visibility {
117 case .public: "PUBLIC"
118 case .unlisted: "UNLISTED"
119 case .private: "PRIVATE"
120 }
121 }
122
123 private var color: Color {
124 switch visibility {
125 case .public: .green
126 case .unlisted: .orange
127 case .private: .red
128 }
129 }
130}