diff --git a/Frameworks/Account/Account.swift b/Frameworks/Account/Account.swift index fbed40312..e00fcaba2 100644 --- a/Frameworks/Account/Account.swift +++ b/Frameworks/Account/Account.swift @@ -1161,10 +1161,10 @@ extension Account: OPMLRepresentable { public func OPMLString(indentLevel: Int, strictConformance: Bool) -> String { var s = "" - for feed in topLevelWebFeeds { + for feed in topLevelWebFeeds.sorted(by: { $0.nameForDisplay < $1.nameForDisplay }) { s += feed.OPMLString(indentLevel: indentLevel + 1, strictConformance: strictConformance) } - for folder in folders! { + for folder in folders!.sorted(by: { $0.nameForDisplay < $1.nameForDisplay }) { s += folder.OPMLString(indentLevel: indentLevel + 1, strictConformance: strictConformance) } return s diff --git a/Frameworks/Account/Folder.swift b/Frameworks/Account/Folder.swift index 211e58b79..31bb6e4e3 100644 --- a/Frameworks/Account/Folder.swift +++ b/Frameworks/Account/Folder.swift @@ -189,7 +189,7 @@ extension Folder: OPMLRepresentable { var hasAtLeastOneChild = false - for feed in topLevelWebFeeds { + for feed in topLevelWebFeeds.sorted(by: { $0.nameForDisplay < $1.nameForDisplay }) { s += feed.OPMLString(indentLevel: indentLevel + 1, strictConformance: strictConformance) hasAtLeastOneChild = true } diff --git a/Frameworks/Account/OPMLFile.swift b/Frameworks/Account/OPMLFile.swift index 799e138d4..e6cc1917f 100644 --- a/Frameworks/Account/OPMLFile.swift +++ b/Frameworks/Account/OPMLFile.swift @@ -49,7 +49,17 @@ final class OPMLFile { private extension OPMLFile { func loadCallback() { - guard let opmlItems = parsedOPMLItems() else { return } + guard let fileData = opmlFileData() else { + return + } + + // Don't rebuild the account if the OPML hasn't changed since the last save + guard let opml = String(data: fileData, encoding: .utf8), opml != opmlDocument() else { + return + } + + guard let opmlItems = parsedOPMLItems(fileData: fileData) else { return } + BatchUpdate.shared.perform { account.topLevelWebFeeds.removeAll() account.loadOPMLItems(opmlItems, parentFolder: nil) @@ -77,8 +87,7 @@ private extension OPMLFile { } } - func parsedOPMLItems() -> [RSOPMLItem]? { - + func opmlFileData() -> Data? { var fileData: Data? = nil let errorPointer: NSErrorPointer = nil let fileCoordinator = NSFileCoordinator(filePresenter: managedFile) @@ -98,11 +107,11 @@ private extension OPMLFile { os_log(.error, log: log, "OPML read from disk coordination failed: %@.", error.localizedDescription) } - guard let opmlData = fileData else { - return nil - } - - let parserData = ParserData(url: fileURL.absoluteString, data: opmlData) + return fileData + } + + func parsedOPMLItems(fileData: Data) -> [RSOPMLItem]? { + let parserData = ParserData(url: fileURL.absoluteString, data: fileData) var opmlDocument: RSOPMLDocument? do { @@ -113,7 +122,6 @@ private extension OPMLFile { } return opmlDocument?.children - } func opmlDocument() -> String {