Prevent more than one OPML import from being run at the same time.
This commit is contained in:
parent
b89f088917
commit
0a9bf2aef0
|
@ -36,9 +36,25 @@ public enum AccountType: Int {
|
||||||
// TODO: more
|
// TODO: more
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum AccountError: Error {
|
public enum AccountError: LocalizedError {
|
||||||
|
|
||||||
case createErrorNotFound
|
case createErrorNotFound
|
||||||
case createErrorAlreadySubscribed
|
case createErrorAlreadySubscribed
|
||||||
|
case opmlImportInProgress
|
||||||
|
|
||||||
|
public var errorDescription: String? {
|
||||||
|
switch self {
|
||||||
|
case .opmlImportInProgress:
|
||||||
|
return NSLocalizedString("An OPML import for this account is already running.", comment: "Import running")
|
||||||
|
default:
|
||||||
|
return NSLocalizedString("An unknown error occurred.", comment: "Unknown error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public var recoverySuggestion: String? {
|
||||||
|
return NSLocalizedString("Please try again later.", comment: "Try later")
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class Account: DisplayNameProvider, UnreadCountProvider, Container, Hashable {
|
public final class Account: DisplayNameProvider, UnreadCountProvider, Container, Hashable {
|
||||||
|
@ -299,6 +315,12 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
||||||
}
|
}
|
||||||
|
|
||||||
public func importOPML(_ opmlFile: URL, completion: @escaping (Result<Void, Error>) -> Void) {
|
public func importOPML(_ opmlFile: URL, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||||
|
|
||||||
|
guard !delegate.opmlImportInProgress else {
|
||||||
|
completion(.failure(AccountError.opmlImportInProgress))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
delegate.importOPML(for: self, opmlFile: opmlFile) { [weak self] result in
|
delegate.importOPML(for: self, opmlFile: opmlFile) { [weak self] result in
|
||||||
switch result {
|
switch result {
|
||||||
case .success:
|
case .success:
|
||||||
|
@ -312,6 +334,7 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func markArticles(_ articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) -> Set<Article>? {
|
public func markArticles(_ articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) -> Set<Article>? {
|
||||||
|
|
|
@ -14,6 +14,8 @@ protocol AccountDelegate {
|
||||||
|
|
||||||
// Local account does not; some synced accounts might.
|
// Local account does not; some synced accounts might.
|
||||||
var supportsSubFolders: Bool { get }
|
var supportsSubFolders: Bool { get }
|
||||||
|
var opmlImportInProgress: Bool { get }
|
||||||
|
|
||||||
var server: String? { get }
|
var server: String? { get }
|
||||||
var credentials: Credentials? { get set }
|
var credentials: Credentials? { get set }
|
||||||
var accountMetadata: AccountMetadata? { get set }
|
var accountMetadata: AccountMetadata? { get set }
|
||||||
|
|
|
@ -32,6 +32,7 @@ final class FeedbinAccountDelegate: AccountDelegate {
|
||||||
|
|
||||||
let supportsSubFolders = false
|
let supportsSubFolders = false
|
||||||
let server: String? = "api.feedbin.com"
|
let server: String? = "api.feedbin.com"
|
||||||
|
var opmlImportInProgress = false
|
||||||
|
|
||||||
var credentials: Credentials? {
|
var credentials: Credentials? {
|
||||||
didSet {
|
didSet {
|
||||||
|
@ -201,6 +202,7 @@ final class FeedbinAccountDelegate: AccountDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
os_log(.debug, log: log, "Begin importing OPML...")
|
os_log(.debug, log: log, "Begin importing OPML...")
|
||||||
|
opmlImportInProgress = true
|
||||||
|
|
||||||
caller.importOPML(opmlData: opmlData) { [weak self] result in
|
caller.importOPML(opmlData: opmlData) { [weak self] result in
|
||||||
switch result {
|
switch result {
|
||||||
|
@ -208,6 +210,7 @@ final class FeedbinAccountDelegate: AccountDelegate {
|
||||||
if importResult.complete {
|
if importResult.complete {
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
os_log(.debug, log: self.log, "Import OPML done.")
|
os_log(.debug, log: self.log, "Import OPML done.")
|
||||||
|
self.opmlImportInProgress = false
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
completion(.success(()))
|
completion(.success(()))
|
||||||
}
|
}
|
||||||
|
@ -217,6 +220,7 @@ final class FeedbinAccountDelegate: AccountDelegate {
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
os_log(.debug, log: self.log, "Import OPML failed.")
|
os_log(.debug, log: self.log, "Import OPML failed.")
|
||||||
|
self.opmlImportInProgress = false
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
|
@ -225,41 +229,6 @@ final class FeedbinAccountDelegate: AccountDelegate {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func checkImportResult(opmlImportResultID: Int, completion: @escaping (Result<Void, Error>) -> Void) {
|
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
|
|
||||||
Timer.scheduledTimer(withTimeInterval: 15, repeats: true) { [weak self] timer in
|
|
||||||
|
|
||||||
guard let self = self else { return }
|
|
||||||
|
|
||||||
os_log(.debug, log: self.log, "Checking status of OPML import...")
|
|
||||||
|
|
||||||
self.caller.retrieveOPMLImportResult(importID: opmlImportResultID) { result in
|
|
||||||
switch result {
|
|
||||||
case .success(let importResult):
|
|
||||||
if let result = importResult, result.complete {
|
|
||||||
os_log(.debug, log: self.log, "Checking status of OPML import successfully completed.")
|
|
||||||
timer.invalidate()
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
completion(.success(()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case .failure(let error):
|
|
||||||
os_log(.debug, log: self.log, "Import OPML check failed.")
|
|
||||||
timer.invalidate()
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func renameFolder(for account: Account, with folder: Folder, to name: String, completion: @escaping (Result<Void, Error>) -> Void) {
|
func renameFolder(for account: Account, with folder: Folder, to name: String, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||||
|
|
||||||
caller.renameTag(oldName: folder.name ?? "", newName: name) { result in
|
caller.renameTag(oldName: folder.name ?? "", newName: name) { result in
|
||||||
|
@ -546,6 +515,43 @@ private extension FeedbinAccountDelegate {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkImportResult(opmlImportResultID: Int, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||||
|
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
|
||||||
|
Timer.scheduledTimer(withTimeInterval: 15, repeats: true) { [weak self] timer in
|
||||||
|
|
||||||
|
guard let self = self else { return }
|
||||||
|
|
||||||
|
os_log(.debug, log: self.log, "Checking status of OPML import...")
|
||||||
|
|
||||||
|
self.caller.retrieveOPMLImportResult(importID: opmlImportResultID) { result in
|
||||||
|
switch result {
|
||||||
|
case .success(let importResult):
|
||||||
|
if let result = importResult, result.complete {
|
||||||
|
os_log(.debug, log: self.log, "Checking status of OPML import successfully completed.")
|
||||||
|
timer.invalidate()
|
||||||
|
self.opmlImportInProgress = false
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
completion(.success(()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case .failure(let error):
|
||||||
|
os_log(.debug, log: self.log, "Import OPML check failed.")
|
||||||
|
timer.invalidate()
|
||||||
|
self.opmlImportInProgress = false
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
completion(.failure(error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func syncFolders(_ account: Account, _ tags: [FeedbinTag]?) {
|
func syncFolders(_ account: Account, _ tags: [FeedbinTag]?) {
|
||||||
|
|
||||||
guard let tags = tags else { return }
|
guard let tags = tags else { return }
|
||||||
|
|
|
@ -18,6 +18,8 @@ public enum LocalAccountDelegateError: String, Error {
|
||||||
final class LocalAccountDelegate: AccountDelegate {
|
final class LocalAccountDelegate: AccountDelegate {
|
||||||
|
|
||||||
let supportsSubFolders = false
|
let supportsSubFolders = false
|
||||||
|
let opmlImportInProgress = false
|
||||||
|
|
||||||
let server: String? = nil
|
let server: String? = nil
|
||||||
var credentials: Credentials?
|
var credentials: Credentials?
|
||||||
var accountMetadata: AccountMetadata?
|
var accountMetadata: AccountMetadata?
|
||||||
|
|
Loading…
Reference in New Issue