a native ios client for gitbay

client ios swift

https://gitbay.org

gitbay/Discovery/FeedEvent.swift

99 lines · 3813 bytes

 1import Foundation
 2
 3/// One `feed` event. `data` varies by kind; unknown kinds and fields
 4/// must render, not sink the feed.
 5nonisolated struct FeedEvent: Decodable, Sendable, Hashable, Identifiable {
 6    let id: Int64
 7    let repo: String
 8    let actor: String?
 9    let kind: String
10    let data: Payload?
11    let createdAt: Date
12
13    enum CodingKeys: String, CodingKey {
14        case id, repo, actor, kind, data
15        case createdAt = "created_at"
16    }
17
18    nonisolated struct Payload: Decodable, Sendable, Hashable {
19        let number: Int64?
20        let sha: String?
21        let tag: String?
22        let title: String?
23        let job: String?
24    }
25
26    /// The same verb and reference phrasing as the web dashboard.
27    var phrase: String {
28        let n = data?.number.map(String.init) ?? ""
29        switch kind {
30        case "mr.created": return "opened merge request !\(n)"
31        case "mr.merged": return "merged !\(n)"
32        case "mr.commented": return "commented on !\(n)"
33        case "mr.closed": return "closed merge request !\(n)"
34        case "issue.created": return "opened issue #\(n)"
35        case "issue.closed": return "closed issue #\(n)"
36        case "issue.reopened": return "reopened issue #\(n)"
37        case "issue.commented": return "commented on #\(n)"
38        case "build.success": return "build success \(data?.job ?? "")"
39        case "build.failure": return "build failure \(data?.job ?? "")"
40        case "release.created": return "released \(data?.tag ?? "")"
41        case "push": return "pushed"
42        case let value where value.hasPrefix("issue."):
43            return "issue \(value.dropFirst("issue.".count)) #\(n)"
44        case let value where value.hasPrefix("mr."):
45            return "merge request \(value.dropFirst("mr.".count)) !\(n)"
46        case let value where value.hasPrefix("build."):
47            return "build \(value.dropFirst("build.".count)) \(data?.job ?? "")"
48        case let value where value.hasPrefix("repo."):
49            return "repository \(value.dropFirst("repo.".count))"
50        default: return kind
51        }
52    }
53
54    var displayActor: String {
55        guard let actor, !actor.isEmpty else { return "gitbay" }
56        return actor
57    }
58
59    var icon: (name: String, isPositive: Bool?) {
60        switch kind {
61        case "mr.created": ("arrow.triangle.merge", nil)
62        case "mr.merged": ("arrow.triangle.merge", true)
63        case "mr.closed": ("xmark.circle", false)
64        case "issue.created", "issue.open", "issue.reopened": ("smallcircle.filled.circle", nil)
65        case "issue.closed": ("checkmark.circle", true)
66        case "issue.commented": ("bubble.left", nil)
67        case "build.success": ("checkmark.circle.fill", true)
68        case "build.failure": ("xmark.circle.fill", false)
69        case "release.created": ("shippingbox", nil)
70        case "push": ("arrow.up.circle", nil)
71        default: ("circle", nil)
72        }
73    }
74
75    /// Where tapping the row goes, when the event names something the app
76    /// has a screen for.
77    var destination: FeedDestination? {
78        if kind == "release.created", let tag = data?.tag {
79            return .release(repo: repo, tag: tag)
80        }
81        guard let number = data?.number else {
82            return .repo(repo)
83        }
84        switch kind.split(separator: ".").first {
85        case "mr": return .mr(repo: repo, number: number)
86        case "issue": return .issue(repo: repo, number: number)
87        case "build": return .build(repo: repo, number: number)
88        default: return .repo(repo)
89        }
90    }
91}
92
93nonisolated enum FeedDestination: Hashable {
94    case repo(String)
95    case mr(repo: String, number: Int64)
96    case issue(repo: String, number: Int64)
97    case build(repo: String, number: Int64)
98    case release(repo: String, tag: String)
99}