krz/hutch

an ios client for sourcehut

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

v3.3.1: Hutch/Views/Repositories/RepositorySummarySupport.swift · raw

  1import SwiftUI
  2
  3enum RepositoryBuildStatus: Sendable {
  4    case success
  5    case failed
  6    case running
  7    case none
  8}
  9
 10struct RepositoryCloneURLs {
 11    let readOnly: String
 12    let readWrite: String
 13}
 14
 15func repositoryCloneURLs(for repository: RepositorySummary) -> RepositoryCloneURLs {
 16    let owner = repository.owner.canonicalName
 17    let name = repository.name
 18
 19    switch repository.service {
 20    case .git:
 21        return RepositoryCloneURLs(
 22            readOnly: "https://git.sr.ht/\(owner)/\(name)",
 23            readWrite: "git@git.sr.ht:\(owner)/\(name)"
 24        )
 25    case .hg:
 26        return RepositoryCloneURLs(
 27            readOnly: "https://hg.sr.ht/\(owner)/\(name)",
 28            readWrite: "ssh://hg@hg.sr.ht/\(owner)/\(name)"
 29        )
 30    default:
 31        return RepositoryCloneURLs(
 32            readOnly: "https://\(repository.service.rawValue).sr.ht/\(owner)/\(name)",
 33            readWrite: ""
 34        )
 35    }
 36}
 37
 38func repositoryVisibilityLabel(_ visibility: Visibility) -> String {
 39    switch visibility {
 40    case .publicVisibility:
 41        return "Public"
 42    case .unlisted:
 43        return "Unlisted"
 44    case .privateVisibility:
 45        return "Private"
 46    }
 47}
 48
 49func repositoryForgeLabel(_ service: SRHTService) -> String {
 50    switch service {
 51    case .git:
 52        return "GIT"
 53    case .hg:
 54        return "HG"
 55    default:
 56        return service.rawValue.uppercased()
 57    }
 58}
 59
 60func repositoryPrimaryBranchLabel(for repository: RepositorySummary, hgTipBranch: String? = nil) -> String? {
 61    switch repository.service {
 62    case .git:
 63        return repository.defaultBranchName
 64    case .hg:
 65        return hgTipBranch ?? repository.defaultBranchName ?? "tip"
 66    default:
 67        return repository.defaultBranchName
 68    }
 69}
 70
 71struct SummaryMetadataRow: View {
 72    let icon: String
 73    let title: String
 74    var subtitle: String? = nil
 75
 76    var body: some View {
 77        HStack(alignment: .top, spacing: 10) {
 78            Image(systemName: icon)
 79                .foregroundStyle(.secondary)
 80                .frame(width: 18)
 81
 82            VStack(alignment: .leading, spacing: 2) {
 83                Text(title)
 84                if let subtitle, !subtitle.isEmpty {
 85                    Text(subtitle)
 86                        .font(.subheadline)
 87                        .foregroundStyle(.secondary)
 88                }
 89            }
 90        }
 91    }
 92}
 93
 94struct SummaryDetailRow: View {
 95    let label: String
 96    let value: String
 97    var monospace: Bool = false
 98
 99    var body: some View {
100        VStack(alignment: .leading, spacing: 4) {
101            Text(label)
102                .font(.caption)
103                .foregroundStyle(.secondary)
104            Text(value)
105                .font(monospace ? .system(.body, design: .monospaced) : .body)
106                .textSelection(.enabled)
107        }
108    }
109}
110
111struct RepositoryForgeBadge: View {
112    let service: SRHTService
113
114    var body: some View {
115        Text(repositoryForgeLabel(service))
116            .font(.caption2.weight(.medium))
117            .padding(.horizontal, 6)
118            .padding(.vertical, 2)
119            .background(color.opacity(0.15), in: Capsule())
120            .foregroundStyle(color)
121    }
122
123    private var color: Color {
124        switch service {
125        case .git:
126            .indigo
127        case .hg:
128            .cyan
129        default:
130            .secondary
131        }
132    }
133}