krz/hutch

an ios client for sourcehut

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

v2.13.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 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}