krz/hutch
an ios client for sourcehut
clone: git clone https://gitbay.org/krz/hutch.git
remove-splash-highlighter: 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}