-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
DashboardPostsSyncManager.swift
151 lines (124 loc) · 5.33 KB
/
DashboardPostsSyncManager.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
import Foundation
protocol DashboardPostsSyncManagerListener: AnyObject {
func postsSynced(success: Bool,
blog: Blog,
postType: DashboardPostsSyncManager.PostType,
posts: [AbstractPost]?,
for statuses: [String])
}
class DashboardPostsSyncManager {
enum PostType {
case post
case page
}
// MARK: Type Aliases
typealias SyncSuccessBlock = () -> Void
typealias SyncFailureBlock = (Error?) -> Void
// MARK: Private Variables
private let postService: PostService
private let blogService: BlogService
@Atomic private var listeners: [DashboardPostsSyncManagerListener] = []
// MARK: Shared Instance
static let shared = DashboardPostsSyncManager()
// MARK: Initializer
init(postService: PostService = PostService(managedObjectContext: ContextManager.shared.mainContext),
blogService: BlogService = BlogService(coreDataStack: ContextManager.shared)) {
self.postService = postService
self.blogService = blogService
}
// MARK: Public Functions
func addListener(_ listener: DashboardPostsSyncManagerListener) {
listeners.append(listener)
}
func removeListener(_ listener: DashboardPostsSyncManagerListener) {
if let index = listeners.firstIndex(where: {$0 === listener}) {
listeners.remove(at: index)
}
}
func syncPosts(blog: Blog, postType: PostType, statuses: [String]) {
let toBeSynced = postType.statusesNotBeingSynced(statuses, for: blog)
guard toBeSynced.isEmpty == false else {
return
}
postType.markStatusesAsBeingSynced(toBeSynced, for: blog)
let options = PostServiceSyncOptions()
options.statuses = toBeSynced
options.authorID = blog.userID
options.number = Constants.numberOfPostsToSync
options.order = .descending
options.orderBy = .byModified
options.purgesLocalSync = true
// If the userID is nil we need to sync authors
// But only if the user is an admin
if blog.userID == nil && blog.isAdmin {
syncAuthors(blog: blog, success: { [weak self] in
postType.stopSyncingStatuses(toBeSynced, for: blog)
self?.syncPosts(blog: blog, postType: postType, statuses: toBeSynced)
}, failure: { [weak self] error in
postType.stopSyncingStatuses(toBeSynced, for: blog)
self?.notifyListenersOfPostsSync(success: false, blog: blog, postType: postType, posts: nil, for: toBeSynced)
})
return
}
postService.syncPosts(ofType: postType.postServiceType, with: options, for: blog) { [weak self] posts in
postType.stopSyncingStatuses(toBeSynced, for: blog)
self?.notifyListenersOfPostsSync(success: true, blog: blog, postType: postType, posts: posts, for: toBeSynced)
} failure: { [weak self] error in
postType.stopSyncingStatuses(toBeSynced, for: blog)
self?.notifyListenersOfPostsSync(success: false, blog: blog, postType: postType, posts: nil, for: toBeSynced)
}
}
func syncAuthors(blog: Blog, success: @escaping SyncSuccessBlock, failure: @escaping SyncFailureBlock) {
blogService.syncAuthors(for: blog, success: success, failure: failure)
}
// MARK: Private Helpers
private func notifyListenersOfPostsSync(success: Bool,
blog: Blog,
postType: PostType,
posts: [AbstractPost]?,
for statuses: [String]) {
for aListener in listeners {
aListener.postsSynced(success: success, blog: blog, postType: postType, posts: posts, for: statuses)
}
}
enum Constants {
static let numberOfPostsToSync: NSNumber = 3
}
}
private extension DashboardPostsSyncManager.PostType {
var postServiceType: PostServiceType {
switch self {
case .post:
return .post
case .page:
return .page
}
}
func statusesNotBeingSynced(_ statuses: [String], for blog: Blog) -> [String] {
var currentlySyncing: [String]
switch self {
case .post:
currentlySyncing = blog.dashboardState.postsSyncingStatuses
case .page:
currentlySyncing = blog.dashboardState.pagesSyncingStatuses
}
let notCurrentlySyncing = statuses.filter({ !currentlySyncing.contains($0) })
return notCurrentlySyncing
}
func markStatusesAsBeingSynced(_ toBeSynced: [String], for blog: Blog) {
switch self {
case .post:
blog.dashboardState.postsSyncingStatuses.append(contentsOf: toBeSynced)
case .page:
blog.dashboardState.pagesSyncingStatuses.append(contentsOf: toBeSynced)
}
}
func stopSyncingStatuses(_ statuses: [String], for blog: Blog) {
switch self {
case .post:
blog.dashboardState.postsSyncingStatuses = blog.dashboardState.postsSyncingStatuses.filter({ !statuses.contains($0) })
case .page:
blog.dashboardState.pagesSyncingStatuses = blog.dashboardState.pagesSyncingStatuses.filter({ !statuses.contains($0) })
}
}
}