krz/hutch
an ios client for sourcehut
clone: git clone https://gitbay.org/krz/hutch.git
v2.12.1: 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 updated: Date
69 let mailingLists: [MailingList]
70 let sources: [SourceRepo]
71 let trackers: [Tracker]
72
73 var resourceSummary: String? {
74 let parts = [
75 Self.resourceCountText(count: sources.count, singular: "repo"),
76 Self.resourceCountText(count: trackers.count, singular: "tracker"),
77 Self.resourceCountText(count: mailingLists.count, singular: "list")
78 ].compactMap { $0 }
79
80 if !parts.isEmpty {
81 return parts.joined(separator: " • ")
82 }
83
84 if let website, !website.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
85 return "Website linked"
86 }
87
88 return nil
89 }
90
91 private static func resourceCountText(count: Int, singular: String) -> String? {
92 guard count > 0 else { return nil }
93 let label = count == 1 ? singular : "\(singular)s"
94 return "\(count) \(label)"
95 }
96}
97
98extension String {
99 var srhtUsername: String {
100 hasPrefix("~") ? String(dropFirst()) : self
101 }
102}