gitbay/Issues/Reaction.swift
56 lines · 2266 bytes
1import Foundation
2
3/// One reaction on an issue, a merge request, or one of their comments,
4/// as `issue show` and `mr show` carry it.
5nonisolated struct ReactionCount: Decodable, Sendable, Hashable, Identifiable {
6 let reaction: String
7 let count: Int
8 /// The signed-in account gave this one.
9 let me: Bool
10
11 var id: String { reaction }
12}
13
14/// The reaction vocabulary, named as the server stores it. The order is
15/// the server's display order, so the picker reads the way the web's does.
16nonisolated struct Reaction: Sendable, Hashable, Identifiable {
17 let name: String
18 let emoji: String
19
20 var id: String { name }
21
22 /// What VoiceOver says; "+1" would be read as "plus one".
23 let spoken: String
24
25 static let all: [Reaction] = [
26 .init(name: "+1", emoji: "👍", spoken: "thumbs up"), .init(name: "-1", emoji: "👎", spoken: "thumbs down"),
27 .init(name: "laugh", emoji: "😄", spoken: "laugh"), .init(name: "hooray", emoji: "🎉", spoken: "hooray"),
28 .init(name: "confused", emoji: "😕", spoken: "confused"), .init(name: "heart", emoji: "❤️", spoken: "heart"),
29 .init(name: "rocket", emoji: "🚀", spoken: "rocket"), .init(name: "eyes", emoji: "👀", spoken: "eyes"),
30 ]
31
32 /// A name a newer server added draws as its name rather than vanishing.
33 static func emoji(for name: String) -> String {
34 all.first { $0.name == name }?.emoji ?? name
35 }
36
37 static func spoken(for name: String) -> String {
38 all.first { $0.name == name }?.spoken ?? name
39 }
40
41 /// Picking a reaction the account already gave takes it back, the way
42 /// the web's toggle does.
43 static func remove(_ name: String, given: [ReactionCount]?) -> Bool {
44 given?.contains { $0.reaction == name && $0.me } ?? false
45 }
46
47 /// `issue react` / `mr react <owner/name> <n> [--comment <id>] <reaction> [--remove]`.
48 static func argv(noun: String, repo: String, number: Int64, comment: Int64?,
49 name: String, remove: Bool) -> [String] {
50 var argv = [noun, "react", repo, String(number)]
51 if let comment { argv += ["--comment", String(comment)] }
52 argv.append(name)
53 if remove { argv.append("--remove") }
54 return argv
55 }
56}