mirror of
https://github.com/Ranchero-Software/NetNewsWire.git
synced 2025-01-03 05:21:55 +01:00
Make BatchUpdate MainActor.
This commit is contained in:
parent
177d660cff
commit
e867487031
@ -675,22 +675,24 @@ private extension FeedbinAccountDelegate {
|
|||||||
self.refreshProgress.completeTask()
|
self.refreshProgress.completeTask()
|
||||||
self.forceExpireFolderFeedRelationship(account, tags)
|
self.forceExpireFolderFeedRelationship(account, tags)
|
||||||
self.caller.retrieveTaggings { result in
|
self.caller.retrieveTaggings { result in
|
||||||
switch result {
|
|
||||||
case .success(let taggings):
|
|
||||||
|
|
||||||
BatchUpdate.shared.perform {
|
|
||||||
self.syncFolders(account, tags)
|
|
||||||
self.syncFeeds(account, subscriptions)
|
|
||||||
self.syncFeedFolderRelationship(account, taggings)
|
|
||||||
}
|
|
||||||
|
|
||||||
self.refreshProgress.completeTask()
|
MainActor.assumeIsolated {
|
||||||
completion(.success(()))
|
switch result {
|
||||||
|
case .success(let taggings):
|
||||||
case .failure(let error):
|
|
||||||
completion(.failure(error))
|
BatchUpdate.shared.perform {
|
||||||
|
self.syncFolders(account, tags)
|
||||||
|
self.syncFeeds(account, subscriptions)
|
||||||
|
self.syncFeedFolderRelationship(account, taggings)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.refreshProgress.completeTask()
|
||||||
|
completion(.success(()))
|
||||||
|
|
||||||
|
case .failure(let error):
|
||||||
|
completion(.failure(error))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
|
@ -81,45 +81,47 @@ final class LocalAccountDelegate: AccountDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func importOPML(for account:Account, opmlFile: URL, completion: @escaping (Result<Void, Error>) -> Void) {
|
func importOPML(for account:Account, opmlFile: URL, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||||
var fileData: Data?
|
|
||||||
|
Task { @MainActor in
|
||||||
do {
|
var fileData: Data?
|
||||||
fileData = try Data(contentsOf: opmlFile)
|
|
||||||
} catch {
|
do {
|
||||||
completion(.failure(error))
|
fileData = try Data(contentsOf: opmlFile)
|
||||||
return
|
} catch {
|
||||||
}
|
completion(.failure(error))
|
||||||
|
return
|
||||||
guard let opmlData = fileData else {
|
}
|
||||||
|
|
||||||
|
guard let opmlData = fileData else {
|
||||||
|
completion(.success(()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let parserData = ParserData(url: opmlFile.absoluteString, data: opmlData)
|
||||||
|
var opmlDocument: RSOPMLDocument?
|
||||||
|
|
||||||
|
do {
|
||||||
|
opmlDocument = try RSOPMLParser.parseOPML(with: parserData)
|
||||||
|
} catch {
|
||||||
|
completion(.failure(error))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let loadDocument = opmlDocument else {
|
||||||
|
completion(.success(()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let children = loadDocument.children else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
BatchUpdate.shared.perform {
|
||||||
|
account.loadOPMLItems(children)
|
||||||
|
}
|
||||||
|
|
||||||
completion(.success(()))
|
completion(.success(()))
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let parserData = ParserData(url: opmlFile.absoluteString, data: opmlData)
|
|
||||||
var opmlDocument: RSOPMLDocument?
|
|
||||||
|
|
||||||
do {
|
|
||||||
opmlDocument = try RSOPMLParser.parseOPML(with: parserData)
|
|
||||||
} catch {
|
|
||||||
completion(.failure(error))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let loadDocument = opmlDocument else {
|
|
||||||
completion(.success(()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let children = loadDocument.children else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
BatchUpdate.shared.perform {
|
|
||||||
account.loadOPMLItems(children)
|
|
||||||
}
|
|
||||||
|
|
||||||
completion(.success(()))
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func createFeed(for account: Account, url urlString: String, name: String?, container: Container, validateFeed: Bool, completion: @escaping (Result<Feed, Error>) -> Void) {
|
func createFeed(for account: Account, url urlString: String, name: String?, container: Container, validateFeed: Bool, completion: @escaping (Result<Feed, Error>) -> Void) {
|
||||||
@ -233,57 +235,60 @@ private extension LocalAccountDelegate {
|
|||||||
|
|
||||||
func createRSSFeed(for account: Account, url: URL, editedName: String?, container: Container, completion: @escaping (Result<Feed, Error>) -> Void) {
|
func createRSSFeed(for account: Account, url: URL, editedName: String?, container: Container, completion: @escaping (Result<Feed, Error>) -> Void) {
|
||||||
|
|
||||||
// We need to use a batch update here because we need to assign add the feed to the
|
Task { @MainActor in
|
||||||
// container before the name has been downloaded. This will put it in the sidebar
|
// We need to use a batch update here because we need to assign add the feed to the
|
||||||
// with an Untitled name if we don't delay it being added to the sidebar.
|
// container before the name has been downloaded. This will put it in the sidebar
|
||||||
BatchUpdate.shared.start()
|
// with an Untitled name if we don't delay it being added to the sidebar.
|
||||||
refreshProgress.addToNumberOfTasksAndRemaining(1)
|
BatchUpdate.shared.start()
|
||||||
FeedFinder.find(url: url) { result in
|
refreshProgress.addToNumberOfTasksAndRemaining(1)
|
||||||
|
FeedFinder.find(url: url) { result in
|
||||||
switch result {
|
|
||||||
case .success(let feedSpecifiers):
|
|
||||||
guard let bestFeedSpecifier = FeedSpecifier.bestFeed(in: feedSpecifiers),
|
|
||||||
let url = URL(string: bestFeedSpecifier.urlString) else {
|
|
||||||
self.refreshProgress.completeTask()
|
|
||||||
BatchUpdate.shared.end()
|
|
||||||
completion(.failure(AccountError.createErrorNotFound))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if account.hasFeed(withURL: bestFeedSpecifier.urlString) {
|
MainActor.assumeIsolated {
|
||||||
self.refreshProgress.completeTask()
|
switch result {
|
||||||
BatchUpdate.shared.end()
|
case .success(let feedSpecifiers):
|
||||||
completion(.failure(AccountError.createErrorAlreadySubscribed))
|
guard let bestFeedSpecifier = FeedSpecifier.bestFeed(in: feedSpecifiers),
|
||||||
return
|
let url = URL(string: bestFeedSpecifier.urlString) else {
|
||||||
}
|
self.refreshProgress.completeTask()
|
||||||
|
|
||||||
InitialFeedDownloader.download(url) { parsedFeed in
|
|
||||||
self.refreshProgress.completeTask()
|
|
||||||
|
|
||||||
if let parsedFeed = parsedFeed {
|
|
||||||
let feed = account.createFeed(with: nil, url: url.absoluteString, feedID: url.absoluteString, homePageURL: nil)
|
|
||||||
feed.editedName = editedName
|
|
||||||
container.addFeed(feed)
|
|
||||||
|
|
||||||
account.update(feed, with: parsedFeed, {_ in
|
|
||||||
BatchUpdate.shared.end()
|
BatchUpdate.shared.end()
|
||||||
completion(.success(feed))
|
completion(.failure(AccountError.createErrorNotFound))
|
||||||
})
|
return
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if account.hasFeed(withURL: bestFeedSpecifier.urlString) {
|
||||||
|
self.refreshProgress.completeTask()
|
||||||
|
BatchUpdate.shared.end()
|
||||||
|
completion(.failure(AccountError.createErrorAlreadySubscribed))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
InitialFeedDownloader.download(url) { parsedFeed in
|
||||||
|
self.refreshProgress.completeTask()
|
||||||
|
|
||||||
|
if let parsedFeed = parsedFeed {
|
||||||
|
let feed = account.createFeed(with: nil, url: url.absoluteString, feedID: url.absoluteString, homePageURL: nil)
|
||||||
|
feed.editedName = editedName
|
||||||
|
container.addFeed(feed)
|
||||||
|
|
||||||
|
account.update(feed, with: parsedFeed, {_ in
|
||||||
|
MainActor.assumeIsolated {
|
||||||
|
BatchUpdate.shared.end()
|
||||||
|
completion(.success(feed))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
BatchUpdate.shared.end()
|
||||||
|
completion(.failure(AccountError.createErrorNotFound))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
case .failure:
|
||||||
BatchUpdate.shared.end()
|
BatchUpdate.shared.end()
|
||||||
|
self.refreshProgress.completeTask()
|
||||||
completion(.failure(AccountError.createErrorNotFound))
|
completion(.failure(AccountError.createErrorNotFound))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case .failure:
|
|
||||||
BatchUpdate.shared.end()
|
|
||||||
self.refreshProgress.completeTask()
|
|
||||||
completion(.failure(AccountError.createErrorNotFound))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,16 +21,19 @@ extension NewsBlurAccountDelegate {
|
|||||||
os_log(.debug, log: log, "Refreshing feeds...")
|
os_log(.debug, log: log, "Refreshing feeds...")
|
||||||
|
|
||||||
caller.retrieveFeeds { result in
|
caller.retrieveFeeds { result in
|
||||||
switch result {
|
|
||||||
case .success((let feeds, let folders)):
|
MainActor.assumeIsolated {
|
||||||
BatchUpdate.shared.perform {
|
switch result {
|
||||||
self.syncFolders(account, folders)
|
case .success((let feeds, let folders)):
|
||||||
self.syncFeeds(account, feeds)
|
BatchUpdate.shared.perform {
|
||||||
self.syncFeedFolderRelationship(account, folders)
|
self.syncFolders(account, folders)
|
||||||
|
self.syncFeeds(account, feeds)
|
||||||
|
self.syncFeedFolderRelationship(account, folders)
|
||||||
|
}
|
||||||
|
completion(.success(()))
|
||||||
|
case .failure(let error):
|
||||||
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
completion(.success(()))
|
|
||||||
case .failure(let error):
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -689,10 +689,12 @@ private extension ReaderAPIAccountDelegate {
|
|||||||
self.refreshProgress.completeTask()
|
self.refreshProgress.completeTask()
|
||||||
switch result {
|
switch result {
|
||||||
case .success(let subscriptions):
|
case .success(let subscriptions):
|
||||||
BatchUpdate.shared.perform {
|
MainActor.assumeIsolated {
|
||||||
self.syncFolders(account, tags)
|
BatchUpdate.shared.perform {
|
||||||
self.syncFeeds(account, subscriptions)
|
self.syncFolders(account, tags)
|
||||||
self.syncFeedFolderRelationship(account, subscriptions)
|
self.syncFeeds(account, subscriptions)
|
||||||
|
self.syncFeedFolderRelationship(account, subscriptions)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
completion(.success(()))
|
completion(.success(()))
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
|
@ -19,10 +19,10 @@ public extension Notification.Name {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A class for batch updating.
|
/// A class for batch updating.
|
||||||
public final class BatchUpdate {
|
@MainActor public final class BatchUpdate {
|
||||||
|
|
||||||
/// The shared batch update object.
|
/// The shared batch update object.
|
||||||
public static let shared = BatchUpdate()
|
@MainActor public static let shared = BatchUpdate()
|
||||||
|
|
||||||
private var count = 0
|
private var count = 0
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ class ScriptableAccount: NSObject, UniqueIdScriptingObject, ScriptingObjectConta
|
|||||||
return self.classDescription as! NSScriptClassDescription
|
return self.classDescription as! NSScriptClassDescription
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteElement(_ element:ScriptingObject) {
|
@MainActor func deleteElement(_ element:ScriptingObject) {
|
||||||
if let scriptableFolder = element as? ScriptableFolder {
|
if let scriptableFolder = element as? ScriptableFolder {
|
||||||
BatchUpdate.shared.perform {
|
BatchUpdate.shared.perform {
|
||||||
account.removeFolder(scriptableFolder.folder) { result in
|
account.removeFolder(scriptableFolder.folder) { result in
|
||||||
|
@ -50,7 +50,7 @@ class ScriptableFolder: NSObject, UniqueIdScriptingObject, ScriptingObjectContai
|
|||||||
return self.classDescription as! NSScriptClassDescription
|
return self.classDescription as! NSScriptClassDescription
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteElement(_ element:ScriptingObject) {
|
@MainActor func deleteElement(_ element:ScriptingObject) {
|
||||||
if let scriptableFeed = element as? ScriptableFeed {
|
if let scriptableFeed = element as? ScriptableFeed {
|
||||||
BatchUpdate.shared.perform {
|
BatchUpdate.shared.perform {
|
||||||
folder.account?.removeFeed(scriptableFeed.feed, from: folder) { result in }
|
folder.account?.removeFeed(scriptableFeed.feed, from: folder) { result in }
|
||||||
|
@ -15,7 +15,7 @@ extension UIView: MarkAsReadAlertControllerSourceType {}
|
|||||||
extension UIBarButtonItem: MarkAsReadAlertControllerSourceType {}
|
extension UIBarButtonItem: MarkAsReadAlertControllerSourceType {}
|
||||||
|
|
||||||
|
|
||||||
struct MarkAsReadAlertController {
|
@MainActor struct MarkAsReadAlertController {
|
||||||
|
|
||||||
static func confirm<T>(_ controller: UIViewController?,
|
static func confirm<T>(_ controller: UIViewController?,
|
||||||
coordinator: SceneCoordinator?,
|
coordinator: SceneCoordinator?,
|
||||||
|
Loading…
Reference in New Issue
Block a user