Add CloudKit syncing add account UI.
This commit is contained in:
parent
770206df60
commit
e3d46960fd
|
@ -36,6 +36,7 @@ public extension Notification.Name {
|
|||
public enum AccountType: Int, Codable {
|
||||
// Raw values should not change since they’re stored on disk.
|
||||
case onMyMac = 1
|
||||
case cloudKit = 2
|
||||
case feedly = 16
|
||||
case feedbin = 17
|
||||
case feedWrangler = 18
|
||||
|
@ -232,6 +233,8 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
|||
switch type {
|
||||
case .onMyMac:
|
||||
self.delegate = LocalAccountDelegate()
|
||||
case .cloudKit:
|
||||
self.delegate = CloudKitAccountDelegate()
|
||||
case .feedbin:
|
||||
self.delegate = FeedbinAccountDelegate(dataFolder: dataFolder, transport: transport)
|
||||
case .freshRSS:
|
||||
|
@ -256,6 +259,8 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
|||
switch type {
|
||||
case .onMyMac:
|
||||
defaultName = Account.defaultLocalAccountName
|
||||
case .cloudKit:
|
||||
defaultName = "iCloud"
|
||||
case .feedly:
|
||||
defaultName = "Feedly"
|
||||
case .feedbin:
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
3B826DAE2385C81C00FC1ADB /* FeedWranglerSubscriptionsRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B826DA52385C81C00FC1ADB /* FeedWranglerSubscriptionsRequest.swift */; };
|
||||
3B826DAF2385C81C00FC1ADB /* FeedWranglerGenericResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3B826DA62385C81C00FC1ADB /* FeedWranglerGenericResult.swift */; };
|
||||
3BC23AB92385ECB100371CBA /* FeedWranglerSubscriptionResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BC23AB82385ECB100371CBA /* FeedWranglerSubscriptionResult.swift */; };
|
||||
5103A9D92422546800410853 /* CloudKitAppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5103A9D82422546800410853 /* CloudKitAppDelegate.swift */; };
|
||||
5107A09B227DE49500C7C3C5 /* TestAccountManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5107A09A227DE49500C7C3C5 /* TestAccountManager.swift */; };
|
||||
5107A09D227DE77700C7C3C5 /* TestTransport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5107A09C227DE77700C7C3C5 /* TestTransport.swift */; };
|
||||
510BD111232C3801002692E4 /* AccountMetadataFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 510BD110232C3801002692E4 /* AccountMetadataFile.swift */; };
|
||||
|
@ -230,6 +231,7 @@
|
|||
3B826DA52385C81C00FC1ADB /* FeedWranglerSubscriptionsRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedWranglerSubscriptionsRequest.swift; sourceTree = "<group>"; };
|
||||
3B826DA62385C81C00FC1ADB /* FeedWranglerGenericResult.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedWranglerGenericResult.swift; sourceTree = "<group>"; };
|
||||
3BC23AB82385ECB100371CBA /* FeedWranglerSubscriptionResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedWranglerSubscriptionResult.swift; sourceTree = "<group>"; };
|
||||
5103A9D82422546800410853 /* CloudKitAppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloudKitAppDelegate.swift; sourceTree = "<group>"; };
|
||||
5107A098227DE42E00C7C3C5 /* AccountCredentialsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountCredentialsTest.swift; sourceTree = "<group>"; };
|
||||
5107A09A227DE49500C7C3C5 /* TestAccountManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestAccountManager.swift; sourceTree = "<group>"; };
|
||||
5107A09C227DE77700C7C3C5 /* TestTransport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestTransport.swift; sourceTree = "<group>"; };
|
||||
|
@ -450,6 +452,14 @@
|
|||
path = FeedWrangler;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
5103A9D7242253DC00410853 /* CloudKit */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5103A9D82422546800410853 /* CloudKitAppDelegate.swift */,
|
||||
);
|
||||
path = CloudKit;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
5111D71C2357534700737D45 /* Feedbin */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -606,6 +616,7 @@
|
|||
3B826D9D2385C81C00FC1ADB /* FeedWrangler */,
|
||||
552032EA229D5D5A009559E0 /* ReaderAPI */,
|
||||
9EA31339231E368100268BA0 /* Feedly */,
|
||||
5103A9D7242253DC00410853 /* CloudKit */,
|
||||
848935031F62484F00CEBD24 /* AccountTests */,
|
||||
848934F71F62484F00CEBD24 /* Products */,
|
||||
8469F80F1F6DC3C10084783E /* Frameworks */,
|
||||
|
@ -844,11 +855,11 @@
|
|||
848934F51F62484F00CEBD24 = {
|
||||
CreatedOnToolsVersion = 9.0;
|
||||
LastSwiftMigration = 0900;
|
||||
ProvisioningStyle = Manual;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
848934FE1F62484F00CEBD24 = {
|
||||
CreatedOnToolsVersion = 9.0;
|
||||
ProvisioningStyle = Manual;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -1008,6 +1019,7 @@
|
|||
84F73CF1202788D90000BCEF /* ArticleFetcher.swift in Sources */,
|
||||
841974251F6DDCE4006346C4 /* AccountDelegate.swift in Sources */,
|
||||
510BD113232C3E9D002692E4 /* WebFeedMetadataFile.swift in Sources */,
|
||||
5103A9D92422546800410853 /* CloudKitAppDelegate.swift in Sources */,
|
||||
5165D73122837F3400D9D53D /* InitialFeedDownloader.swift in Sources */,
|
||||
9E784EBE237E890600099B1B /* FeedlyLogoutOperation.swift in Sources */,
|
||||
9EEEF71F23545CB4009E9D80 /* FeedlySendArticleStatusesOperation.swift in Sources */,
|
||||
|
|
|
@ -120,7 +120,7 @@ public final class AccountManager: UnreadCountProvider {
|
|||
// MARK: - API
|
||||
|
||||
public func createAccount(type: AccountType) -> Account {
|
||||
let accountID = UUID().uuidString
|
||||
let accountID = type == .cloudKit ? "iCloud" : UUID().uuidString
|
||||
let accountFolder = (accountsFolder as NSString).appendingPathComponent("\(type.rawValue)_\(accountID)")
|
||||
|
||||
do {
|
||||
|
|
|
@ -0,0 +1,216 @@
|
|||
//
|
||||
// CloudKitAppDelegate.swift
|
||||
// Account
|
||||
//
|
||||
// Created by Maurice Parker on 3/18/20.
|
||||
// Copyright © 2020 Ranchero Software, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RSCore
|
||||
import RSParser
|
||||
import Articles
|
||||
import RSWeb
|
||||
|
||||
public enum CloudKitAccountDelegateError: String, Error {
|
||||
case invalidParameter = "An invalid parameter was used."
|
||||
}
|
||||
|
||||
final class CloudKitAccountDelegate: AccountDelegate {
|
||||
|
||||
let behaviors: AccountBehaviors = []
|
||||
let isOPMLImportInProgress = false
|
||||
|
||||
let server: String? = nil
|
||||
var credentials: Credentials?
|
||||
var accountMetadata: AccountMetadata?
|
||||
|
||||
private let refresher = LocalAccountRefresher()
|
||||
|
||||
var refreshProgress: DownloadProgress {
|
||||
return refresher.progress
|
||||
}
|
||||
|
||||
func refreshAll(for account: Account, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
refresher.refreshFeeds(account.flattenedWebFeeds()) {
|
||||
account.metadata.lastArticleFetchEndTime = Date()
|
||||
completion(.success(()))
|
||||
}
|
||||
}
|
||||
|
||||
func sendArticleStatus(for account: Account, completion: @escaping ((Result<Void, Error>) -> Void)) {
|
||||
completion(.success(()))
|
||||
}
|
||||
|
||||
func refreshArticleStatus(for account: Account, completion: @escaping ((Result<Void, Error>) -> Void)) {
|
||||
completion(.success(()))
|
||||
}
|
||||
|
||||
func importOPML(for account:Account, opmlFile: URL, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
var fileData: Data?
|
||||
|
||||
do {
|
||||
fileData = try Data(contentsOf: opmlFile)
|
||||
} catch {
|
||||
completion(.failure(error))
|
||||
return
|
||||
}
|
||||
|
||||
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, parentFolder: nil)
|
||||
}
|
||||
|
||||
completion(.success(()))
|
||||
|
||||
}
|
||||
|
||||
func createWebFeed(for account: Account, url urlString: String, name: String?, container: Container, completion: @escaping (Result<WebFeed, Error>) -> Void) {
|
||||
guard let url = URL(string: urlString) else {
|
||||
completion(.failure(LocalAccountDelegateError.invalidParameter))
|
||||
return
|
||||
}
|
||||
|
||||
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()
|
||||
completion(.failure(AccountError.createErrorNotFound))
|
||||
return
|
||||
}
|
||||
|
||||
if account.hasWebFeed(withURL: bestFeedSpecifier.urlString) {
|
||||
self.refreshProgress.completeTask()
|
||||
completion(.failure(AccountError.createErrorAlreadySubscribed))
|
||||
return
|
||||
}
|
||||
|
||||
let feed = account.createWebFeed(with: nil, url: url.absoluteString, webFeedID: url.absoluteString, homePageURL: nil)
|
||||
|
||||
InitialFeedDownloader.download(url) { parsedFeed in
|
||||
self.refreshProgress.completeTask()
|
||||
|
||||
if let parsedFeed = parsedFeed {
|
||||
account.update(feed, with: parsedFeed, {_ in})
|
||||
}
|
||||
|
||||
feed.editedName = name
|
||||
|
||||
container.addWebFeed(feed)
|
||||
completion(.success(feed))
|
||||
|
||||
}
|
||||
|
||||
case .failure:
|
||||
self.refreshProgress.completeTask()
|
||||
completion(.failure(AccountError.createErrorNotFound))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func renameWebFeed(for account: Account, with feed: WebFeed, to name: String, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
feed.editedName = name
|
||||
completion(.success(()))
|
||||
}
|
||||
|
||||
func removeWebFeed(for account: Account, with feed: WebFeed, from container: Container, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
container.removeWebFeed(feed)
|
||||
completion(.success(()))
|
||||
}
|
||||
|
||||
func moveWebFeed(for account: Account, with feed: WebFeed, from: Container, to: Container, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
from.removeWebFeed(feed)
|
||||
to.addWebFeed(feed)
|
||||
completion(.success(()))
|
||||
}
|
||||
|
||||
func addWebFeed(for account: Account, with feed: WebFeed, to container: Container, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
container.addWebFeed(feed)
|
||||
completion(.success(()))
|
||||
}
|
||||
|
||||
func restoreWebFeed(for account: Account, feed: WebFeed, container: Container, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
container.addWebFeed(feed)
|
||||
completion(.success(()))
|
||||
}
|
||||
|
||||
func addFolder(for account: Account, name: String, completion: @escaping (Result<Folder, Error>) -> Void) {
|
||||
if let folder = account.ensureFolder(with: name) {
|
||||
completion(.success(folder))
|
||||
} else {
|
||||
completion(.failure(FeedbinAccountDelegateError.invalidParameter))
|
||||
}
|
||||
}
|
||||
|
||||
func renameFolder(for account: Account, with folder: Folder, to name: String, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
folder.name = name
|
||||
completion(.success(()))
|
||||
}
|
||||
|
||||
func removeFolder(for account: Account, with folder: Folder, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
account.removeFolder(folder)
|
||||
completion(.success(()))
|
||||
}
|
||||
|
||||
func restoreFolder(for account: Account, folder: Folder, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
account.addFolder(folder)
|
||||
completion(.success(()))
|
||||
}
|
||||
|
||||
func markArticles(for account: Account, articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) -> Set<Article>? {
|
||||
return try? account.update(articles, statusKey: statusKey, flag: flag)
|
||||
}
|
||||
|
||||
func accountDidInitialize(_ account: Account) {
|
||||
}
|
||||
|
||||
func accountWillBeDeleted(_ account: Account) {
|
||||
}
|
||||
|
||||
static func validateCredentials(transport: Transport, credentials: Credentials, endpoint: URL? = nil, completion: (Result<Credentials?, Error>) -> Void) {
|
||||
return completion(.success(nil))
|
||||
}
|
||||
|
||||
// MARK: Suspend and Resume (for iOS)
|
||||
|
||||
func suspendNetwork() {
|
||||
refresher.suspend()
|
||||
}
|
||||
|
||||
func suspendDatabase() {
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
func resume() {
|
||||
refresher.resume()
|
||||
}
|
||||
}
|
|
@ -21,6 +21,10 @@ struct AppAssets {
|
|||
return RSImage(named: .timelineStar)
|
||||
}()
|
||||
|
||||
static var accountCloudKit: RSImage! = {
|
||||
return RSImage(named: "accountCloudKit")
|
||||
}()
|
||||
|
||||
static var accountLocal: RSImage! = {
|
||||
return RSImage(named: "accountLocal")
|
||||
}()
|
||||
|
@ -129,6 +133,8 @@ struct AppAssets {
|
|||
switch accountType {
|
||||
case .onMyMac:
|
||||
return AppAssets.accountLocal
|
||||
case .cloudKit:
|
||||
return AppAssets.accountCloudKit
|
||||
case .feedbin:
|
||||
return AppAssets.accountFeedbin
|
||||
case .feedly:
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// AccountsAddCloudKitWindowController.swift
|
||||
// NetNewsWire
|
||||
//
|
||||
// Created by Maurice Parker on 3/18/20.
|
||||
// Copyright © 2020 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Account
|
||||
|
||||
class AccountsAddCloudKitWindowController: NSWindowController {
|
||||
|
||||
private weak var hostWindow: NSWindow?
|
||||
|
||||
convenience init() {
|
||||
self.init(windowNibName: NSNib.Name("AccountsAddCloudKit"))
|
||||
}
|
||||
|
||||
override func windowDidLoad() {
|
||||
super.windowDidLoad()
|
||||
}
|
||||
|
||||
// MARK: API
|
||||
|
||||
func runSheetOnWindow(_ hostWindow: NSWindow, completion: ((NSApplication.ModalResponse) -> Void)? = nil) {
|
||||
self.hostWindow = hostWindow
|
||||
hostWindow.beginSheet(window!, completionHandler: completion)
|
||||
}
|
||||
|
||||
// MARK: Actions
|
||||
|
||||
@IBAction func cancel(_ sender: Any) {
|
||||
hostWindow!.endSheet(window!, returnCode: NSApplication.ModalResponse.cancel)
|
||||
}
|
||||
|
||||
@IBAction func create(_ sender: Any) {
|
||||
_ = AccountManager.shared.createAccount(type: .cloudKit)
|
||||
hostWindow!.endSheet(window!, returnCode: NSApplication.ModalResponse.OK)
|
||||
}
|
||||
|
||||
}
|
|
@ -16,7 +16,11 @@ class AccountsAddViewController: NSViewController {
|
|||
|
||||
private var accountsAddWindowController: NSWindowController?
|
||||
|
||||
private let addableAccountTypes: [AccountType] = [.onMyMac, .feedbin, .feedly, .feedWrangler, .freshRSS]
|
||||
#if DEBUG
|
||||
private var addableAccountTypes: [AccountType] = [.onMyMac, .cloudKit, .feedbin, .feedly, .feedWrangler, .freshRSS]
|
||||
#else
|
||||
private var addableAccountTypes: [AccountType] = [.onMyMac, .feedbin, .feedly]
|
||||
#endif
|
||||
|
||||
init() {
|
||||
super.init(nibName: "AccountsAdd", bundle: nil)
|
||||
|
@ -27,12 +31,10 @@ class AccountsAddViewController: NSViewController {
|
|||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
|
||||
super.viewDidLoad()
|
||||
|
||||
tableView.dataSource = self
|
||||
tableView.delegate = self
|
||||
|
||||
removeCloudKitIfNecessary()
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -63,6 +65,9 @@ extension AccountsAddViewController: NSTableViewDelegate {
|
|||
case .onMyMac:
|
||||
cell.accountNameLabel?.stringValue = Account.defaultLocalAccountName
|
||||
cell.accountImageView?.image = AppAssets.accountLocal
|
||||
case .cloudKit:
|
||||
cell.accountNameLabel?.stringValue = NSLocalizedString("iCloud", comment: "iCloud")
|
||||
cell.accountImageView?.image = AppAssets.accountCloudKit
|
||||
case .feedbin:
|
||||
cell.accountNameLabel?.stringValue = NSLocalizedString("Feedbin", comment: "Feedbin")
|
||||
cell.accountImageView?.image = AppAssets.accountFeedbin
|
||||
|
@ -95,6 +100,15 @@ extension AccountsAddViewController: NSTableViewDelegate {
|
|||
let accountsAddLocalWindowController = AccountsAddLocalWindowController()
|
||||
accountsAddLocalWindowController.runSheetOnWindow(self.view.window!)
|
||||
accountsAddWindowController = accountsAddLocalWindowController
|
||||
case .cloudKit:
|
||||
let accountsAddCloudKitWindowController = AccountsAddCloudKitWindowController()
|
||||
accountsAddCloudKitWindowController.runSheetOnWindow(self.view.window!) { response in
|
||||
if response == NSApplication.ModalResponse.OK {
|
||||
self.removeCloudKitIfNecessary()
|
||||
self.tableView.reloadData()
|
||||
}
|
||||
}
|
||||
accountsAddWindowController = accountsAddCloudKitWindowController
|
||||
case .feedbin:
|
||||
let accountsFeedbinWindowController = AccountsFeedbinWindowController()
|
||||
accountsFeedbinWindowController.runSheetOnWindow(self.view.window!)
|
||||
|
@ -142,3 +156,13 @@ extension AccountsAddViewController: OAuthAccountAuthorizationOperationDelegate
|
|||
view.window?.presentError(error)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private extension AccountsAddViewController {
|
||||
func removeCloudKitIfNecessary() {
|
||||
if let index = AccountManager.shared.activeAccounts.firstIndex(where: { $0.type == .cloudKit }) {
|
||||
addableAccountTypes.remove(at: index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "icloud.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
Binary file not shown.
|
@ -159,6 +159,8 @@ class ScriptableAccount: NSObject, UniqueIdScriptingObject, ScriptingObjectConta
|
|||
switch self.account.type {
|
||||
case .onMyMac:
|
||||
osType = "Locl"
|
||||
case .cloudKit:
|
||||
osType = "Clkt"
|
||||
case .feedly:
|
||||
osType = "Fdly"
|
||||
case .feedbin:
|
||||
|
|
|
@ -17,6 +17,10 @@
|
|||
5103A9982421643300410853 /* blank.html in Resources */ = {isa = PBXBuildFile; fileRef = 5103A9972421643300410853 /* blank.html */; };
|
||||
5103A9992421643300410853 /* blank.html in Resources */ = {isa = PBXBuildFile; fileRef = 5103A9972421643300410853 /* blank.html */; };
|
||||
5103A9B424216A4200410853 /* blank.html in Resources */ = {isa = PBXBuildFile; fileRef = 5103A9B324216A4200410853 /* blank.html */; };
|
||||
5103A9F4242258C600410853 /* AccountsAddCloudKit.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5103A9DA242258C600410853 /* AccountsAddCloudKit.xib */; };
|
||||
5103A9F5242258C600410853 /* AccountsAddCloudKit.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5103A9DA242258C600410853 /* AccountsAddCloudKit.xib */; };
|
||||
5103A9F724225E4C00410853 /* AccountsAddCloudKitWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5103A9F624225E4C00410853 /* AccountsAddCloudKitWindowController.swift */; };
|
||||
5103A9F824225E4C00410853 /* AccountsAddCloudKitWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5103A9F624225E4C00410853 /* AccountsAddCloudKitWindowController.swift */; };
|
||||
5108F6B62375E612001ABC45 /* CacheCleaner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5108F6B52375E612001ABC45 /* CacheCleaner.swift */; };
|
||||
5108F6B72375E612001ABC45 /* CacheCleaner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5108F6B52375E612001ABC45 /* CacheCleaner.swift */; };
|
||||
5108F6D22375EED2001ABC45 /* TimelineCustomizerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5108F6D12375EED2001ABC45 /* TimelineCustomizerViewController.swift */; };
|
||||
|
@ -1255,6 +1259,8 @@
|
|||
49F40DEF2335B71000552BF4 /* newsfoot.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = newsfoot.js; sourceTree = "<group>"; };
|
||||
5103A9972421643300410853 /* blank.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = blank.html; sourceTree = "<group>"; };
|
||||
5103A9B324216A4200410853 /* blank.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = blank.html; sourceTree = "<group>"; };
|
||||
5103A9DA242258C600410853 /* AccountsAddCloudKit.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AccountsAddCloudKit.xib; sourceTree = "<group>"; };
|
||||
5103A9F624225E4C00410853 /* AccountsAddCloudKitWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountsAddCloudKitWindowController.swift; sourceTree = "<group>"; };
|
||||
5108F6B52375E612001ABC45 /* CacheCleaner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CacheCleaner.swift; sourceTree = "<group>"; };
|
||||
5108F6D12375EED2001ABC45 /* TimelineCustomizerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineCustomizerViewController.swift; sourceTree = "<group>"; };
|
||||
5108F6D32375EEEF001ABC45 /* TimelinePreviewTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelinePreviewTableViewController.swift; sourceTree = "<group>"; };
|
||||
|
@ -2616,6 +2622,8 @@
|
|||
55E15BCA229D65A900D6602A /* AccountsReaderAPIWindowController.swift */,
|
||||
5144EA352279FC3D00D19003 /* AccountsAddLocal.xib */,
|
||||
5144EA372279FC6200D19003 /* AccountsAddLocalWindowController.swift */,
|
||||
5103A9DA242258C600410853 /* AccountsAddCloudKit.xib */,
|
||||
5103A9F624225E4C00410853 /* AccountsAddCloudKitWindowController.swift */,
|
||||
);
|
||||
path = Accounts;
|
||||
sourceTree = "<group>";
|
||||
|
@ -3468,6 +3476,7 @@
|
|||
65ED405B235DEF6C0081F399 /* KeyboardShortcuts.html in Resources */,
|
||||
65ED405C235DEF6C0081F399 /* ImportOPMLSheet.xib in Resources */,
|
||||
65ED405D235DEF6C0081F399 /* SidebarKeyboardShortcuts.plist in Resources */,
|
||||
5103A9F5242258C600410853 /* AccountsAddCloudKit.xib in Resources */,
|
||||
65ED405E235DEF6C0081F399 /* DefaultFeeds.opml in Resources */,
|
||||
65ED405F235DEF6C0081F399 /* Preferences.storyboard in Resources */,
|
||||
65ED4060235DEF6C0081F399 /* (null) in Resources */,
|
||||
|
@ -3556,6 +3565,7 @@
|
|||
84C9FC8C22629E8F00D921D6 /* KeyboardShortcuts.html in Resources */,
|
||||
5144EA3B227A379E00D19003 /* ImportOPMLSheet.xib in Resources */,
|
||||
844B5B691FEA20DF00C7C76A /* SidebarKeyboardShortcuts.plist in Resources */,
|
||||
5103A9F4242258C600410853 /* AccountsAddCloudKit.xib in Resources */,
|
||||
84A3EE5F223B667F00557320 /* DefaultFeeds.opml in Resources */,
|
||||
849C78902362AAFC009A71E4 /* ExportOPMLSheet.xib in Resources */,
|
||||
84C9FC8222629E4800D921D6 /* Preferences.storyboard in Resources */,
|
||||
|
@ -3778,6 +3788,7 @@
|
|||
65ED3FD6235DEF6C0081F399 /* MarkStatusCommand.swift in Sources */,
|
||||
65ED3FD7235DEF6C0081F399 /* NSApplication+Scriptability.swift in Sources */,
|
||||
65ED3FD8235DEF6C0081F399 /* NSView-Extensions.swift in Sources */,
|
||||
5103A9F824225E4C00410853 /* AccountsAddCloudKitWindowController.swift in Sources */,
|
||||
65ED3FD9235DEF6C0081F399 /* SidebarCell.swift in Sources */,
|
||||
65ED3FDA235DEF6C0081F399 /* ArticleStatusSyncTimer.swift in Sources */,
|
||||
65ED3FDB235DEF6C0081F399 /* WebFeedTreeControllerDelegate.swift in Sources */,
|
||||
|
@ -4129,6 +4140,7 @@
|
|||
55E15BCC229D65A900D6602A /* AccountsReaderAPIWindowController.swift in Sources */,
|
||||
5144EA382279FC6200D19003 /* AccountsAddLocalWindowController.swift in Sources */,
|
||||
84AD1EAA2031617300BC20B7 /* PasteboardFolder.swift in Sources */,
|
||||
5103A9F724225E4C00410853 /* AccountsAddCloudKitWindowController.swift in Sources */,
|
||||
5144EA51227B8E4500D19003 /* AccountsFeedbinWindowController.swift in Sources */,
|
||||
84AD1EBC2032AF5C00BC20B7 /* SidebarOutlineDataSource.swift in Sources */,
|
||||
845A29241FC9255E007B49E3 /* SidebarCellAppearance.swift in Sources */,
|
||||
|
|
Loading…
Reference in New Issue