Skip to content

Commit b6764eb

Browse files
committed
Merge branch 'feature/comments' into dev
2 parents 27dce82 + 76b088f commit b6764eb

File tree

19 files changed

+479
-106
lines changed

19 files changed

+479
-106
lines changed

HNReader.xcodeproj/project.pbxproj

+66-19
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
archiveVersion = 1;
44
classes = {
55
};
6-
objectVersion = 50;
6+
objectVersion = 52;
77
objects = {
88

99
/* Begin PBXBuildFile section */
@@ -15,12 +15,19 @@
1515
330718D415D21296AA14E7CA /* HackerNewsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33071291447141A6D31E671B /* HackerNewsTests.swift */; };
1616
330719203034BDB177F28C41 /* +DateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33071B0E5439D8D207CB68F4 /* +DateTests.swift */; };
1717
33071F1C64D4742E1F947FAA /* ItemDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33071D0E5913DB91DDDBDADB /* ItemDownloader.swift */; };
18-
C93F99B6267554F00046F870 /* ItemCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C93F99B5267554F00046F870 /* ItemCell.swift */; };
19-
C93F99B8267557FC0046F870 /* ItemList.swift in Sources */ = {isa = PBXBuildFile; fileRef = C93F99B7267557FC0046F870 /* ItemList.swift */; };
20-
C93F99BA267580CE0046F870 /* HTMLText.swift in Sources */ = {isa = PBXBuildFile; fileRef = C93F99B9267580CE0046F870 /* HTMLText.swift */; };
18+
C93F99B6267554F00046F870 /* StoryCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C93F99B5267554F00046F870 /* StoryCell.swift */; };
19+
C93F99B8267557FC0046F870 /* StoryList.swift in Sources */ = {isa = PBXBuildFile; fileRef = C93F99B7267557FC0046F870 /* StoryList.swift */; };
20+
C9B58794267C153C005E0A50 /* DetailStoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B58793267C153C005E0A50 /* DetailStoryView.swift */; };
21+
C9B83DD426A8631300036AC6 /* Comment.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B83DD326A8631300036AC6 /* Comment.swift */; };
22+
C9B83DD726A8637D00036AC6 /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = C9B83DD626A8637D00036AC6 /* Alamofire */; };
23+
C9B83DD926A863C000036AC6 /* Job.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B83DD826A863C000036AC6 /* Job.swift */; };
24+
C9B83DDB26A863D000036AC6 /* Story.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B83DDA26A863D000036AC6 /* Story.swift */; };
25+
C9B83DDF26A8808900036AC6 /* CommentCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B83DDE26A8808900036AC6 /* CommentCell.swift */; };
26+
C9B83DE126A8820F00036AC6 /* HTMLText.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B83DE026A8820F00036AC6 /* HTMLText.swift */; };
27+
C9B83DE926A8A23C00036AC6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C9B83DE826A8A23C00036AC6 /* Assets.xcassets */; };
28+
C9B83DEB26A8A76800036AC6 /* +NSTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9B83DEA26A8A76800036AC6 /* +NSTextField.swift */; };
2129
C9D0937726741BBE002CC786 /* HNReaderApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9D0937626741BBE002CC786 /* HNReaderApp.swift */; };
2230
C9D0937926741BBE002CC786 /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9D0937826741BBE002CC786 /* HomeView.swift */; };
23-
C9D0937B26741BBF002CC786 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C9D0937A26741BBF002CC786 /* Assets.xcassets */; };
2431
C9D0937E26741BBF002CC786 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C9D0937D26741BBF002CC786 /* Preview Assets.xcassets */; };
2532
C9D0938026741BBF002CC786 /* Persistence.swift in Sources */ = {isa = PBXBuildFile; fileRef = C9D0937F26741BBF002CC786 /* Persistence.swift */; };
2633
C9D0938326741BBF002CC786 /* HNReader.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = C9D0938126741BBF002CC786 /* HNReader.xcdatamodeld */; };
@@ -58,13 +65,19 @@
5865
33071D0E5913DB91DDDBDADB /* ItemDownloader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ItemDownloader.swift; sourceTree = "<group>"; };
5966
33071E538EC434DF1A245518 /* HackerNewsClientTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HackerNewsClientTests.swift; sourceTree = "<group>"; };
6067
33071EEBE46634E658582AE3 /* ItemTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ItemTests.swift; sourceTree = "<group>"; };
61-
C93F99B5267554F00046F870 /* ItemCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemCell.swift; sourceTree = "<group>"; };
62-
C93F99B7267557FC0046F870 /* ItemList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItemList.swift; sourceTree = "<group>"; };
63-
C93F99B9267580CE0046F870 /* HTMLText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTMLText.swift; sourceTree = "<group>"; };
68+
C93F99B5267554F00046F870 /* StoryCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoryCell.swift; sourceTree = "<group>"; };
69+
C93F99B7267557FC0046F870 /* StoryList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoryList.swift; sourceTree = "<group>"; };
70+
C9B58793267C153C005E0A50 /* DetailStoryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailStoryView.swift; sourceTree = "<group>"; };
71+
C9B83DD326A8631300036AC6 /* Comment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Comment.swift; sourceTree = "<group>"; };
72+
C9B83DD826A863C000036AC6 /* Job.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Job.swift; sourceTree = "<group>"; };
73+
C9B83DDA26A863D000036AC6 /* Story.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Story.swift; sourceTree = "<group>"; };
74+
C9B83DDE26A8808900036AC6 /* CommentCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentCell.swift; sourceTree = "<group>"; };
75+
C9B83DE026A8820F00036AC6 /* HTMLText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTMLText.swift; sourceTree = "<group>"; };
76+
C9B83DE826A8A23C00036AC6 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
77+
C9B83DEA26A8A76800036AC6 /* +NSTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "+NSTextField.swift"; sourceTree = "<group>"; };
6478
C9D0937326741BBE002CC786 /* HNReader.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HNReader.app; sourceTree = BUILT_PRODUCTS_DIR; };
6579
C9D0937626741BBE002CC786 /* HNReaderApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HNReaderApp.swift; sourceTree = "<group>"; };
6680
C9D0937826741BBE002CC786 /* HomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeView.swift; sourceTree = "<group>"; };
67-
C9D0937A26741BBF002CC786 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
6881
C9D0937D26741BBF002CC786 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
6982
C9D0937F26741BBF002CC786 /* Persistence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Persistence.swift; sourceTree = "<group>"; };
7083
C9D0938226741BBF002CC786 /* HNReader.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = HNReader.xcdatamodel; sourceTree = "<group>"; };
@@ -87,6 +100,7 @@
87100
isa = PBXFrameworksBuildPhase;
88101
buildActionMask = 2147483647;
89102
files = (
103+
C9B83DD726A8637D00036AC6 /* Alamofire in Frameworks */,
90104
);
91105
runOnlyForDeploymentPostprocessing = 0;
92106
};
@@ -111,6 +125,7 @@
111125
isa = PBXGroup;
112126
children = (
113127
3307159309D438EFAA1259C7 /* +Date.swift */,
128+
C9B83DEA26A8A76800036AC6 /* +NSTextField.swift */,
114129
);
115130
path = Utils;
116131
sourceTree = "<group>";
@@ -143,7 +158,9 @@
143158
C9926691267588B80035A88F /* Components */ = {
144159
isa = PBXGroup;
145160
children = (
146-
C93F99B9267580CE0046F870 /* HTMLText.swift */,
161+
C93F99B5267554F00046F870 /* StoryCell.swift */,
162+
C9B83DDE26A8808900036AC6 /* CommentCell.swift */,
163+
C9B83DE026A8820F00036AC6 /* HTMLText.swift */,
147164
);
148165
path = Components;
149166
sourceTree = "<group>";
@@ -171,12 +188,12 @@
171188
C9D0937526741BBE002CC786 /* HNReader */ = {
172189
isa = PBXGroup;
173190
children = (
191+
C9B83DE826A8A23C00036AC6 /* Assets.xcassets */,
174192
C9D093AA26741BFD002CC786 /* HNClient */,
175193
C9D093A926741BF6002CC786 /* ViewModel */,
176194
C9D093A826741BF0002CC786 /* Model */,
177195
C9D093A726741BE1002CC786 /* View */,
178196
C9D0937626741BBE002CC786 /* HNReaderApp.swift */,
179-
C9D0937A26741BBF002CC786 /* Assets.xcassets */,
180197
C9D0937F26741BBF002CC786 /* Persistence.swift */,
181198
C9D0938426741BBF002CC786 /* Info.plist */,
182199
C9D0938526741BBF002CC786 /* HNReader.entitlements */,
@@ -219,9 +236,9 @@
219236
isa = PBXGroup;
220237
children = (
221238
C9D0937826741BBE002CC786 /* HomeView.swift */,
222-
C93F99B5267554F00046F870 /* ItemCell.swift */,
223-
C93F99B7267557FC0046F870 /* ItemList.swift */,
239+
C93F99B7267557FC0046F870 /* StoryList.swift */,
224240
C9926691267588B80035A88F /* Components */,
241+
C9B58793267C153C005E0A50 /* DetailStoryView.swift */,
225242
);
226243
path = View;
227244
sourceTree = "<group>";
@@ -231,6 +248,9 @@
231248
children = (
232249
C9D093AB26741C25002CC786 /* Item.swift */,
233250
C9E9BD022674D095001B4E19 /* User.swift */,
251+
C9B83DD326A8631300036AC6 /* Comment.swift */,
252+
C9B83DD826A863C000036AC6 /* Job.swift */,
253+
C9B83DDA26A863D000036AC6 /* Story.swift */,
234254
);
235255
path = Model;
236256
sourceTree = "<group>";
@@ -272,6 +292,7 @@
272292
);
273293
name = HNReader;
274294
packageProductDependencies = (
295+
C9B83DD626A8637D00036AC6 /* Alamofire */,
275296
);
276297
productName = HNReader;
277298
productReference = C9D0937326741BBE002CC786 /* HNReader.app */;
@@ -345,6 +366,7 @@
345366
);
346367
mainGroup = C9D0936A26741BBE002CC786;
347368
packageReferences = (
369+
C9B83DD526A8637D00036AC6 /* XCRemoteSwiftPackageReference "Alamofire" */,
348370
);
349371
productRefGroup = C9D0937426741BBE002CC786 /* Products */;
350372
projectDirPath = "";
@@ -362,8 +384,8 @@
362384
isa = PBXResourcesBuildPhase;
363385
buildActionMask = 2147483647;
364386
files = (
387+
C9B83DE926A8A23C00036AC6 /* Assets.xcassets in Resources */,
365388
C9D0937E26741BBF002CC786 /* Preview Assets.xcassets in Resources */,
366-
C9D0937B26741BBF002CC786 /* Assets.xcassets in Resources */,
367389
);
368390
runOnlyForDeploymentPostprocessing = 0;
369391
};
@@ -388,22 +410,28 @@
388410
isa = PBXSourcesBuildPhase;
389411
buildActionMask = 2147483647;
390412
files = (
413+
C9B83DEB26A8A76800036AC6 /* +NSTextField.swift in Sources */,
391414
C9D093AC26741C25002CC786 /* Item.swift in Sources */,
392415
C9D0938026741BBF002CC786 /* Persistence.swift in Sources */,
393416
C9D0937926741BBE002CC786 /* HomeView.swift in Sources */,
394-
C93F99B6267554F00046F870 /* ItemCell.swift in Sources */,
395-
C93F99B8267557FC0046F870 /* ItemList.swift in Sources */,
417+
C93F99B6267554F00046F870 /* StoryCell.swift in Sources */,
418+
C93F99B8267557FC0046F870 /* StoryList.swift in Sources */,
396419
C9E9BCFD2674C80E001B4E19 /* AppState.swift in Sources */,
397420
C9D0938326741BBF002CC786 /* HNReader.xcdatamodeld in Sources */,
398421
C9E9BD032674D095001B4E19 /* User.swift in Sources */,
399-
C93F99BA267580CE0046F870 /* HTMLText.swift in Sources */,
400422
C9E9BCFF2674CB6C001B4E19 /* HackerNewsClient.swift in Sources */,
401423
C9E9BD012674D007001B4E19 /* HackerNews.swift in Sources */,
402424
C9D0937726741BBE002CC786 /* HNReaderApp.swift in Sources */,
403425
330713D3016ED410AFD53FDF /* ItemListViewModel.swift in Sources */,
426+
C9B83DDB26A863D000036AC6 /* Story.swift in Sources */,
404427
330711A9216E762026AF98A0 /* +Date.swift in Sources */,
428+
C9B58794267C153C005E0A50 /* DetailStoryView.swift in Sources */,
429+
C9B83DD426A8631300036AC6 /* Comment.swift in Sources */,
430+
C9B83DE126A8820F00036AC6 /* HTMLText.swift in Sources */,
405431
33071F1C64D4742E1F947FAA /* ItemDownloader.swift in Sources */,
406432
3307147AB95F03650FC40B97 /* ItemCache.swift in Sources */,
433+
C9B83DD926A863C000036AC6 /* Job.swift in Sources */,
434+
C9B83DDF26A8808900036AC6 /* CommentCell.swift in Sources */,
407435
);
408436
runOnlyForDeploymentPostprocessing = 0;
409437
};
@@ -563,7 +591,7 @@
563591
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
564592
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
565593
CODE_SIGN_ENTITLEMENTS = HNReader/HNReader.entitlements;
566-
CODE_SIGN_IDENTITY = "-";
594+
CODE_SIGN_IDENTITY = "Apple Development";
567595
CODE_SIGN_STYLE = Automatic;
568596
COMBINE_HIDPI_IMAGES = YES;
569597
CURRENT_PROJECT_VERSION = 2;
@@ -589,7 +617,7 @@
589617
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
590618
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
591619
CODE_SIGN_ENTITLEMENTS = HNReader/HNReader.entitlements;
592-
CODE_SIGN_IDENTITY = "-";
620+
CODE_SIGN_IDENTITY = "Apple Development";
593621
CODE_SIGN_STYLE = Automatic;
594622
COMBINE_HIDPI_IMAGES = YES;
595623
CURRENT_PROJECT_VERSION = 2;
@@ -734,6 +762,25 @@
734762
};
735763
/* End XCConfigurationList section */
736764

765+
/* Begin XCRemoteSwiftPackageReference section */
766+
C9B83DD526A8637D00036AC6 /* XCRemoteSwiftPackageReference "Alamofire" */ = {
767+
isa = XCRemoteSwiftPackageReference;
768+
repositoryURL = "https://github.com/Alamofire/Alamofire.git";
769+
requirement = {
770+
kind = upToNextMajorVersion;
771+
minimumVersion = 5.4.3;
772+
};
773+
};
774+
/* End XCRemoteSwiftPackageReference section */
775+
776+
/* Begin XCSwiftPackageProductDependency section */
777+
C9B83DD626A8637D00036AC6 /* Alamofire */ = {
778+
isa = XCSwiftPackageProductDependency;
779+
package = C9B83DD526A8637D00036AC6 /* XCRemoteSwiftPackageReference "Alamofire" */;
780+
productName = Alamofire;
781+
};
782+
/* End XCSwiftPackageProductDependency section */
783+
737784
/* Begin XCVersionGroup section */
738785
C9D0938126741BBF002CC786 /* HNReader.xcdatamodeld */ = {
739786
isa = XCVersionGroup;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"object": {
3+
"pins": [
4+
{
5+
"package": "Alamofire",
6+
"repositoryURL": "https://github.com/Alamofire/Alamofire.git",
7+
"state": {
8+
"branch": null,
9+
"revision": "f96b619bcb2383b43d898402283924b80e2c4bae",
10+
"version": "5.4.3"
11+
}
12+
}
13+
]
14+
},
15+
"version": 1
16+
}

HNReader/Assets.xcassets/AccentColor.colorset/Contents.json

-20
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"images" : [
3+
{
4+
"filename" : "NoComments.png",
5+
"idiom" : "universal",
6+
"scale" : "1x"
7+
},
8+
{
9+
"idiom" : "universal",
10+
"scale" : "2x"
11+
},
12+
{
13+
"idiom" : "universal",
14+
"scale" : "3x"
15+
}
16+
],
17+
"info" : {
18+
"author" : "xcode",
19+
"version" : 1
20+
}
21+
}
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"images" : [
3+
{
4+
"filename" : "Select.png",
5+
"idiom" : "universal",
6+
"scale" : "1x"
7+
},
8+
{
9+
"idiom" : "universal",
10+
"scale" : "2x"
11+
},
12+
{
13+
"idiom" : "universal",
14+
"scale" : "3x"
15+
}
16+
],
17+
"info" : {
18+
"author" : "xcode",
19+
"version" : 1
20+
}
21+
}
Loading

HNReader/HNClient/HackerNewsClient.swift

+31
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import Foundation
99
import Combine
10+
import Alamofire
1011

1112
/// HackerNews Client that exposes methods to get users, items and stories from https://news.ycombinator.com
1213
class HackerNewsClient {
@@ -65,4 +66,34 @@ class HackerNewsClient {
6566
.flatMap(getStories)
6667
.eraseToAnyPublisher()
6768
}
69+
70+
/// Recursively fetches comments and all its childrens
71+
public func getComments(commentsIds: [Int], completionHandler: @escaping (Bool, [Comment]) -> Void) {
72+
var returnComments : [Comment] = []
73+
74+
let commentsGroup = DispatchGroup()
75+
for commentId in commentsIds {
76+
commentsGroup.enter()
77+
let itemUrl = HackerNews.API.Item.id(commentId).urlString
78+
AF.request(itemUrl).responseJSON { response in
79+
if let commentJSON = try! response.result.get() as? NSDictionary {
80+
let commentObject = Comment.init(json: commentJSON)
81+
commentObject.getComments(completionHandler: { (success) in
82+
returnComments.append(commentObject)
83+
commentsGroup.leave()
84+
})
85+
} else {
86+
commentsGroup.leave()
87+
}
88+
}
89+
}
90+
91+
commentsGroup.notify(queue: .main) {
92+
returnComments.sort {a, b in
93+
commentsIds.firstIndex(of: a.id!)! < commentsIds.firstIndex(of: b.id!)!
94+
}
95+
96+
completionHandler(true, returnComments)
97+
}
98+
}
6899
}

HNReader/HNClient/ItemDownloader.swift

+2-12
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,11 @@
55
import Foundation
66

77
protocol ItemDownloader {
8-
var cacheKey: Int { get }
9-
func downloadItem(completion: @escaping (Item?) -> Void)
8+
func downloadItem(itemId: Int, completion: @escaping (Item?) -> Void)
109
}
1110

1211
class DefaultItemDownloader: ItemDownloader {
13-
let itemId: Int
14-
var cacheKey: Int {
15-
itemId
16-
}
17-
18-
init(itemId: Int) {
19-
self.itemId = itemId
20-
}
21-
22-
func downloadItem(completion: @escaping (Item?) -> ()) {
12+
func downloadItem(itemId: Int, completion: @escaping (Item?) -> ()) {
2313
guard let url = URL(string: HackerNews.API.Item.id(itemId).urlString) else { return }
2414
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
2515
if let data = data {

HNReader/HNReaderApp.swift

+6-7
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ struct HNReaderApp: App {
1414

1515
private var displayModeBind: Binding<ColorScheme> {
1616
Binding<ColorScheme>(
17-
get: { appState.getColorScheme() },
18-
set: {
19-
appState.setColorScheme($0)
20-
displayMode = $0
21-
}
17+
get: { appState.getColorScheme() },
18+
set: {
19+
appState.setColorScheme($0)
20+
displayMode = $0
21+
}
2222
)
2323
}
2424
@State var displayMode: ColorScheme?
@@ -44,8 +44,7 @@ struct HNReaderApp: App {
4444
.frame(maxWidth: 100)
4545
}
4646
}
47-
.frame(minHeight: 100)
48-
.frame(minWidth: 300)
47+
.frame(minWidth: 300, minHeight: 100)
4948
.preferredColorScheme(displayMode)
5049
}
5150
}

0 commit comments

Comments
 (0)