Files
NetNewsWire/Frameworks/Account/OPMLFile.swift
2019-09-12 18:41:42 -05:00

133 lines
2.9 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// OPMLFile.swift
// Account
//
// Created by Maurice Parker on 9/12/19.
// Copyright © 2019 Ranchero Software, LLC. All rights reserved.
//
import Foundation
import os.log
import RSCore
import RSParser
final class OPMLFile: NSObject, NSFilePresenter {
private var log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "account")
private let filename: String
private let account: Account
private let operationQueue: OperationQueue
var presentedItemURL: URL? {
return URL(fileURLWithPath: filename)
}
var presentedItemOperationQueue: OperationQueue {
return operationQueue
}
init(filename: String, account: Account) {
self.filename = filename
self.account = account
operationQueue = OperationQueue()
operationQueue.maxConcurrentOperationCount = 1
super.init()
NSFileCoordinator.addFilePresenter(self)
}
func presentedItemDidChange() {
DispatchQueue.main.async {
self.reload()
}
}
func load() {
guard let opmlItems = parsedOPMLItems() else { return }
BatchUpdate.shared.perform {
account.loadOPMLItems(opmlItems, parentFolder: nil)
}
}
func save() {
let opmlDocumentString = opmlDocument()
do {
let url = URL(fileURLWithPath: filename)
try opmlDocumentString.write(to: url, atomically: true, encoding: .utf8)
} catch let error as NSError {
os_log(.error, log: log, "Save to disk failed: %@.", error.localizedDescription)
}
}
}
private extension OPMLFile {
func reload() {
guard let opmlItems = parsedOPMLItems() else { return }
BatchUpdate.shared.perform {
account.topLevelFeeds.removeAll()
account.loadOPMLItems(opmlItems, parentFolder: nil)
}
}
func parsedOPMLItems() -> [RSOPMLItem]? {
let opmlFileURL = URL(fileURLWithPath: filename)
var fileData: Data?
do {
fileData = try Data(contentsOf: opmlFileURL)
} catch {
// Commented out because its not an error on first run.
// TODO: make it so we know if its first run or not.
//NSApplication.shared.presentError(error)
return nil
}
guard let opmlData = fileData else {
return nil
}
let parserData = ParserData(url: opmlFileURL.absoluteString, data: opmlData)
var opmlDocument: RSOPMLDocument?
do {
opmlDocument = try RSOPMLParser.parseOPML(with: parserData)
} catch {
os_log(.error, log: log, "OPML Import failed: %@.", error.localizedDescription)
return nil
}
return opmlDocument?.children
}
func opmlDocument() -> String {
let escapedTitle = account.nameForDisplay.rs_stringByEscapingSpecialXMLCharacters()
let openingText =
"""
<?xml version="1.0" encoding="UTF-8"?>
<!-- OPML generated by NetNewsWire -->
<opml version="1.1">
<head>
<title>\(escapedTitle)</title>
</head>
<body>
"""
let middleText = account.OPMLString(indentLevel: 0)
let closingText =
"""
</body>
</opml>
"""
let opml = openingText + middleText + closingText
return opml
}
}