krz/hutch

an ios client for sourcehut

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

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