-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
Category.swift
159 lines (135 loc) · 4.33 KB
/
Category.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import Foundation
public struct ParentCategory: Swift.Codable {
public let analyticsName: String?
public let id: String
public let name: String
public var categoryType: Category {
return Category(analyticsName: self.analyticsName, id: self.id, name: self.name)
}
}
private let unrecognizedCategoryId: Int = -1
public struct Category: Swift.Codable {
public static let gamesId: Int = 12
public var analyticsName: String?
public var id: String
public var name: String
internal let _parent: ParentCategory?
public var parentId: String?
public var subcategories: SubcategoryConnection?
public var totalProjectCount: Int?
public init(
analyticsName: String?,
id: String,
name: String,
parentCategory: ParentCategory? = nil,
parentId: String? = nil,
subcategories: SubcategoryConnection? = nil,
totalProjectCount: Int? = nil
) {
self.analyticsName = analyticsName
self.id = id
self.name = name
self.parentId = parentId
self._parent = parentCategory
self.subcategories = subcategories
self.totalProjectCount = totalProjectCount
}
public var intID: Int? {
return decompose(id: self.id)
}
/*
This is a work around that fixes the incompatibility between the types of category id returned by
the server (Int) and the type we need to send when requesting category by id
through GraphQL (base64 encoded String). This will be removed once we start consuming GraphQL to fetch
Discovery projects.
*/
public static func decode(id: String) -> String {
return "Category-\(id)"
}
public var parent: Category? {
return self._parent?.categoryType
}
public struct SubcategoryConnection: Swift.Codable {
public let totalCount: Int
public let nodes: [Category]
}
public var isRoot: Bool {
return self.parentId == nil
}
/// Returns the parent category if present, or returns self if we know for a fact that self is a
/// root category.
public var root: Category? {
if let parent = self._parent {
return parent.categoryType
} else if self.parentId == nil {
return self
}
return nil
}
/// Returns the id of the root category.
public var rootId: Int? {
if let parentId = self.parentId {
return decompose(id: parentId)
}
return self.root?.intID
}
}
extension Category {
private enum CodingKeys: String, CodingKey {
case analyticsName, id, name, parentId, _parent = "parentCategory", subcategories, totalProjectCount
}
public init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
self.analyticsName = try values.decodeIfPresent(String.self, forKey: .analyticsName)
self.id = try values.decode(String.self, forKey: .id)
self.name = try values.decode(String.self, forKey: .name)
self.parentId = try? values.decode(String.self, forKey: .parentId)
self._parent = try? values.decode(ParentCategory.self, forKey: ._parent)
self.subcategories = try? values.decode(SubcategoryConnection.self, forKey: .subcategories)
self.totalProjectCount = try? values.decode(Int.self, forKey: .totalProjectCount)
}
}
extension ParentCategory: Hashable {
public func hash(into hasher: inout Hasher) {
hasher.combine(self.categoryType.intID ?? unrecognizedCategoryId)
}
}
extension ParentCategory: Equatable {
public static func == (lhs: ParentCategory, rhs: ParentCategory) -> Bool {
return lhs.id == rhs.id
}
}
extension Category: Comparable {}
public func < (lhs: Category, rhs: Category) -> Bool {
if lhs.id == rhs.id {
return false
}
if lhs.isRoot, lhs.id == rhs.parent?.id {
return true
}
if !lhs.isRoot, lhs.parent?.id == rhs.id {
return false
}
if let lhsRootName = lhs.parent?.name, let rhsRootName = rhs.parent?.name {
return lhsRootName < rhsRootName
}
return lhs.parent == nil
}
extension Category: Equatable {
public static func == (lhs: Category, rhs: Category) -> Bool {
return lhs.id == rhs.id
}
}
extension Category: Hashable {
public func hash(into hasher: inout Hasher) {
hasher.combine(self.intID ?? unrecognizedCategoryId)
}
}
extension Category: CustomStringConvertible, CustomDebugStringConvertible {
public var description: String {
return "GraphCategory(id: \(self.id), name: \(self.name))"
}
public var debugDescription: String {
return self.description
}
}