krz/hutch

an ios client for sourcehut

clone: git clone https://gitbay.org/krz/hutch.git

v2: 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}