krz/hutch
an ios client for sourcehut
clone: git clone https://gitbay.org/krz/hutch.git
v2.4.0: Hutch/Models/Project.swift · raw
1import Foundation
2
3struct Project: Identifiable, Hashable, Sendable {
4 struct MailingList: Identifiable, Hashable, Sendable {
5 let id: String
6 let name: String
7 let description: String?
8 let visibility: Visibility
9 let owner: Entity
10
11 var ownerUsername: String {
12 owner.canonicalName.srhtUsername
13 }
14
15 var inboxReference: InboxMailingListReference {
16 InboxMailingListReference(
17 id: 0,
18 rid: id,
19 name: name,
20 owner: owner
21 )
22 }
23 }
24
25 struct SourceRepo: Identifiable, Hashable, Sendable {
26 enum RepoType: String, Decodable, Sendable {
27 case git = "GIT"
28 case hg = "HG"
29
30 var service: SRHTService {
31 switch self {
32 case .git: .git
33 case .hg: .hg
34 }
35 }
36 }
37
38 let id: String
39 let name: String
40 let description: String?
41 let visibility: Visibility
42 let owner: Entity
43 let repoType: RepoType
44
45 var ownerUsername: String {
46 owner.canonicalName.srhtUsername
47 }
48 }
49
50 struct Tracker: Identifiable, Hashable, Sendable {
51 let id: String
52 let name: String
53 let description: String?
54 let visibility: Visibility
55 let owner: Entity
56
57 var ownerUsername: String {
58 owner.canonicalName.srhtUsername
59 }
60 }
61
62 let id: String
63 let name: String
64 let description: String?
65 let website: String?
66 let visibility: Visibility
67 let tags: [String]
68 let mailingLists: [MailingList]
69 let sources: [SourceRepo]
70 let trackers: [Tracker]
71
72 var resourceSummary: String? {
73 let parts = [
74 Self.resourceCountText(count: sources.count, singular: "repo"),
75 Self.resourceCountText(count: trackers.count, singular: "tracker"),
76 Self.resourceCountText(count: mailingLists.count, singular: "list")
77 ].compactMap { $0 }
78
79 if !parts.isEmpty {
80 return parts.joined(separator: " • ")
81 }
82
83 if let website, !website.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
84 return "Website linked"
85 }
86
87 return nil
88 }
89
90 private static func resourceCountText(count: Int, singular: String) -> String? {
91 guard count > 0 else { return nil }
92 let label = count == 1 ? singular : "\(singular)s"
93 return "\(count) \(label)"
94 }
95}
96
97extension String {
98 var srhtUsername: String {
99 hasPrefix("~") ? String(dropFirst()) : self
100 }
101}