diff options
| author | Christian Cleberg <[email protected]> | 2026-03-19 15:18:38 -0500 |
|---|---|---|
| committer | Christian Cleberg <[email protected]> | 2026-03-19 15:18:38 -0500 |
| commit | 659c76df9ff3926cb68886c16167808c23bd8f75 (patch) | |
| tree | 572bef546fcca19ad37bc1aa7cfb153eb2bf8eb7 /Hutch/Models/Project.swift | |
| parent | ed48e72520c51e4635cd3840dbc569bdd74c950f (diff) | |
| parent | 6ba4e967d5dfb5d3c7bb97a0f2662f3180595563 (diff) | |
| download | hutch-2.tar.gz hutch-2.tar.bz2 hutch-2.zip | |
v2.0: Merge branch 'dev'v2
Diffstat (limited to 'Hutch/Models/Project.swift')
| -rw-r--r-- | Hutch/Models/Project.swift | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/Hutch/Models/Project.swift b/Hutch/Models/Project.swift new file mode 100644 index 0000000..e6726c2 --- /dev/null +++ b/Hutch/Models/Project.swift @@ -0,0 +1,101 @@ +import Foundation + +struct Project: Identifiable, Hashable, Sendable { + struct MailingList: Identifiable, Hashable, Sendable { + let id: String + let name: String + let description: String? + let visibility: Visibility + let owner: Entity + + var ownerUsername: String { + owner.canonicalName.srhtUsername + } + + var inboxReference: InboxMailingListReference { + InboxMailingListReference( + id: 0, + rid: id, + name: name, + owner: owner + ) + } + } + + struct SourceRepo: Identifiable, Hashable, Sendable { + enum RepoType: String, Decodable, Sendable { + case git = "GIT" + case hg = "HG" + + var service: SRHTService { + switch self { + case .git: .git + case .hg: .hg + } + } + } + + let id: String + let name: String + let description: String? + let visibility: Visibility + let owner: Entity + let repoType: RepoType + + var ownerUsername: String { + owner.canonicalName.srhtUsername + } + } + + struct Tracker: Identifiable, Hashable, Sendable { + let id: String + let name: String + let description: String? + let visibility: Visibility + let owner: Entity + + var ownerUsername: String { + owner.canonicalName.srhtUsername + } + } + + let id: String + let name: String + let description: String? + let website: String? + let visibility: Visibility + let tags: [String] + let mailingLists: [MailingList] + let sources: [SourceRepo] + let trackers: [Tracker] + + var resourceSummary: String? { + let parts = [ + Self.resourceCountText(count: sources.count, singular: "repo"), + Self.resourceCountText(count: trackers.count, singular: "tracker"), + Self.resourceCountText(count: mailingLists.count, singular: "list") + ].compactMap { $0 } + + if !parts.isEmpty { + return parts.joined(separator: " • ") + } + + if let website, !website.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { + return "Website linked" + } + + return nil + } + + private static func resourceCountText(count: Int, singular: String) -> String? { + guard count > 0 else { return nil } + let label = count == 1 ? singular : "\(singular)s" + return "\(count) \(label)" + } +} + +extension String { + var srhtUsername: String { + hasPrefix("~") ? String(dropFirst()) : self + } +} |
