-
-
Notifications
You must be signed in to change notification settings - Fork 723
/
TalkPageDataController.swift
139 lines (107 loc) · 4.95 KB
/
TalkPageDataController.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
import Foundation
import WMF
/// Class that coordinates network fetches for talk pages.
/// Leans on file persistence for offline mode as-needed.
class TalkPageDataController {
private let pageType: TalkPageType
private let pageTitle: String
private let siteURL: URL
private let talkPageFetcher = TalkPageFetcher()
private let articleSummaryController: ArticleSummaryController
init(pageType: TalkPageType, pageTitle: String, siteURL: URL, articleSummaryController: ArticleSummaryController) {
self.pageType = pageType
self.pageTitle = pageTitle
self.siteURL = siteURL
self.articleSummaryController = articleSummaryController
}
// MARK: Public
typealias TalkPageResult = Result<(articleSummary: WMFArticle?, items: [TalkPageItem]), Error>
func fetchTalkPage(completion: @escaping (TalkPageResult) -> Void) {
assert(Thread.isMainThread)
let group = DispatchGroup()
var finalErrors: [Error] = []
var finalItems: [TalkPageItem] = []
var finalArticleSummary: WMFArticle?
fetchTalkPageItems(dispatchGroup: group) { items, errors in
finalItems = items
finalErrors.append(contentsOf: errors)
}
fetchArticleSummaryIfNeeded(dispatchGroup: group) { articleSummary, errors in
finalArticleSummary = articleSummary
finalErrors.append(contentsOf: errors)
}
group.notify(queue: DispatchQueue.main, execute: {
if let firstError = finalErrors.first {
completion(.failure(firstError))
return
}
completion(.success((finalArticleSummary, finalItems)))
})
}
func postReply(commentId: String, comment: String, completion: @escaping(Result<Void, Error>) -> Void) {
talkPageFetcher.postReply(talkPageTitle: pageTitle, siteURL: siteURL, commentId: commentId, comment: comment, completion: completion)
}
func postTopic(topicTitle: String, topicBody: String, completion: @escaping(Result<Void, Error>) -> Void) {
talkPageFetcher.postTopic(talkPageTitle: pageTitle, siteURL: siteURL, topicTitle: topicTitle, topicBody: topicBody, completion: completion)
}
func subscribeToTopic(topicName: String, shouldSubscribe: Bool, completion: @escaping (Result<Bool, Error>) -> Void) {
talkPageFetcher.subscribeToTopic(talkPageTitle: pageTitle, siteURL: siteURL, topic: topicName, shouldSubscribe: shouldSubscribe, completion: completion)
}
func fetchSubscriptions(for topics: [String], completion: @escaping (Result<[String], Error>) -> Void) {
talkPageFetcher.getSubscribedTopics(siteURL: siteURL, topics: topics) { result in
switch result {
case let .success(result):
completion(.success(result))
case let .failure(error):
completion(.failure(error))
}
}
}
// MARK: Private
private func fetchTalkPageItems(dispatchGroup group: DispatchGroup, completion: @escaping ([TalkPageItem], [Error]) -> Void) {
group.enter()
talkPageFetcher.fetchTalkPageContent(talkPageTitle: pageTitle, siteURL: siteURL) { result in
DispatchQueue.main.async {
defer {
group.leave()
}
switch result {
case .success(let items):
completion(items, [])
case .failure(let error):
completion([], [error])
}
}
}
}
private func fetchArticleSummaryIfNeeded(dispatchGroup group: DispatchGroup, completion: @escaping (WMFArticle?, [Error]) -> Void) {
guard pageType == .article,
let languageCode = siteURL.wmf_languageCode else {
completion(nil, [])
return
}
let pageTitleMinusNamespace = pageTitle.namespaceAndTitleOfWikiResourcePath(with: languageCode).title
guard let mainNamespacePageURL = siteURL.wmf_URL(withTitle: pageTitleMinusNamespace),
let inMemoryKey = mainNamespacePageURL.wmf_inMemoryKey else {
completion(nil, [])
return
}
group.enter()
articleSummaryController.updateOrCreateArticleSummaryForArticle(withKey: inMemoryKey) { article, error in
DispatchQueue.main.async {
defer {
group.leave()
}
if let article = article {
completion(article, [])
return
}
if let error = error {
completion(nil, [error])
return
}
completion(nil, [])
}
}
}
}