Allow refreshing of Feed Wrangler subscriptions
This commit is contained in:
parent
86caa869fc
commit
d80aeefdb3
|
@ -10,6 +10,8 @@
|
|||
3BF610C723571CD4000EF978 /* FeedWranglerAPICaller.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BF610C423571CD4000EF978 /* FeedWranglerAPICaller.swift */; };
|
||||
3BF610C823571CD4000EF978 /* FeedWranglerConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BF610C523571CD4000EF978 /* FeedWranglerConfig.swift */; };
|
||||
3BF610C923571CD4000EF978 /* FeedWranglerAccountDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BF610C623571CD4000EF978 /* FeedWranglerAccountDelegate.swift */; };
|
||||
3BF6112423572A62000EF978 /* FeedWranglerSubscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BF6112323572A62000EF978 /* FeedWranglerSubscription.swift */; };
|
||||
3BF6112623572E43000EF978 /* FeedWranglerSubscriptionsRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3BF6112523572E43000EF978 /* FeedWranglerSubscriptionsRequest.swift */; };
|
||||
5107A099227DE42E00C7C3C5 /* AccountCredentialsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5107A098227DE42E00C7C3C5 /* AccountCredentialsTest.swift */; };
|
||||
5107A09B227DE49500C7C3C5 /* TestAccountManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5107A09A227DE49500C7C3C5 /* TestAccountManager.swift */; };
|
||||
5107A09D227DE77700C7C3C5 /* TestTransport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5107A09C227DE77700C7C3C5 /* TestTransport.swift */; };
|
||||
|
@ -191,6 +193,8 @@
|
|||
3BF610C423571CD4000EF978 /* FeedWranglerAPICaller.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedWranglerAPICaller.swift; sourceTree = "<group>"; };
|
||||
3BF610C523571CD4000EF978 /* FeedWranglerConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedWranglerConfig.swift; sourceTree = "<group>"; };
|
||||
3BF610C623571CD4000EF978 /* FeedWranglerAccountDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedWranglerAccountDelegate.swift; sourceTree = "<group>"; };
|
||||
3BF6112323572A62000EF978 /* FeedWranglerSubscription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedWranglerSubscription.swift; sourceTree = "<group>"; };
|
||||
3BF6112523572E43000EF978 /* FeedWranglerSubscriptionsRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedWranglerSubscriptionsRequest.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>"; };
|
||||
|
@ -349,6 +353,8 @@
|
|||
3BF610C423571CD4000EF978 /* FeedWranglerAPICaller.swift */,
|
||||
3BF610C523571CD4000EF978 /* FeedWranglerConfig.swift */,
|
||||
3BF610C623571CD4000EF978 /* FeedWranglerAccountDelegate.swift */,
|
||||
3BF6112323572A62000EF978 /* FeedWranglerSubscription.swift */,
|
||||
3BF6112523572E43000EF978 /* FeedWranglerSubscriptionsRequest.swift */,
|
||||
);
|
||||
path = FeedWrangler;
|
||||
sourceTree = "<group>";
|
||||
|
@ -892,6 +898,7 @@
|
|||
9ECC9A85234DC16E009B5144 /* FeedlyAccountDelegateError.swift in Sources */,
|
||||
9EA3133B231E368100268BA0 /* FeedlyAccountDelegate.swift in Sources */,
|
||||
51E5959B228C781500FCC42B /* FeedbinStarredEntry.swift in Sources */,
|
||||
3BF6112423572A62000EF978 /* FeedWranglerSubscription.swift in Sources */,
|
||||
846E77451F6EF9B900A165E2 /* Container.swift in Sources */,
|
||||
9E1D15532334304B00F4944C /* FeedlyGetStreamOperation.swift in Sources */,
|
||||
9E12B0202334696A00ADE5A0 /* FeedlyCreateFeedsForCollectionFoldersOperation.swift in Sources */,
|
||||
|
@ -950,6 +957,7 @@
|
|||
84D09623217418DC00D77525 /* FeedbinTagging.swift in Sources */,
|
||||
84CAD7161FDF2E22000F0755 /* FeedbinEntry.swift in Sources */,
|
||||
5165D72A22835F7D00D9D53D /* HTMLFeedFinder.swift in Sources */,
|
||||
3BF6112623572E43000EF978 /* FeedWranglerSubscriptionsRequest.swift in Sources */,
|
||||
841974011F6DD1EC006346C4 /* Folder.swift in Sources */,
|
||||
510BD111232C3801002692E4 /* AccountMetadataFile.swift in Sources */,
|
||||
846E774F1F6EF9C000A165E2 /* LocalAccountDelegate.swift in Sources */,
|
||||
|
|
|
@ -37,7 +37,13 @@ public extension URLRequest {
|
|||
]
|
||||
self.url = components.url
|
||||
case .feedWranglerToken:
|
||||
fatalError() // TODO: implement
|
||||
guard var components = URLComponents(url: url, resolvingAgainstBaseURL: false) else {
|
||||
return
|
||||
}
|
||||
components.queryItems = [
|
||||
URLQueryItem(name: "access_token", value: credentials.secret),
|
||||
]
|
||||
self.url = components.url
|
||||
case .readerBasic:
|
||||
setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
|
||||
httpMethod = "POST"
|
||||
|
|
|
@ -56,4 +56,19 @@ final class FeedWranglerAPICaller: NSObject {
|
|||
}
|
||||
}
|
||||
|
||||
func retrieveSubscriptions(completion: @escaping (Result<[FeedWranglerSubscription], Error>) -> Void) {
|
||||
let url = FeedWranglerConfig.clientURL.appendingPathComponent("subscriptions/list")
|
||||
let request = URLRequest(url: url, credentials: credentials)
|
||||
|
||||
transport.send(request: request, resultType: FeedWranglerSubscriptionsRequest.self) { result in
|
||||
switch result {
|
||||
case .success(let (_, results)):
|
||||
completion(.success(results?.feeds ?? []))
|
||||
|
||||
case .failure(let error):
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,7 +19,12 @@ final class FeedWranglerAccountDelegate: AccountDelegate {
|
|||
|
||||
var isOPMLImportInProgress = false
|
||||
var server: String? = FeedWranglerConfig.clientPath
|
||||
var credentials: Credentials?
|
||||
var credentials: Credentials? {
|
||||
didSet {
|
||||
caller.credentials = credentials
|
||||
}
|
||||
}
|
||||
|
||||
var accountMetadata: AccountMetadata?
|
||||
var refreshProgress = DownloadProgress(numberOfTasks: 0)
|
||||
|
||||
|
@ -54,13 +59,17 @@ final class FeedWranglerAccountDelegate: AccountDelegate {
|
|||
func refreshAll(for account: Account, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
refreshProgress.addToNumberOfTasksAndRemaining(6)
|
||||
|
||||
self.sendArticleStatus(for: account) {
|
||||
self.refreshArticleStatus(for: account) {
|
||||
self.refreshArticles(for: account) {
|
||||
self.refreshMissingArticles(for: account) {
|
||||
self.refreshProgress.clear()
|
||||
DispatchQueue.main.async {
|
||||
completion(.success(()))
|
||||
self.refreshCredentials(for: account) {
|
||||
self.refreshSubscriptions(for: account) { _ in
|
||||
self.sendArticleStatus(for: account) {
|
||||
self.refreshArticleStatus(for: account) {
|
||||
self.refreshArticles(for: account) {
|
||||
self.refreshMissingArticles(for: account) {
|
||||
self.refreshProgress.clear()
|
||||
DispatchQueue.main.async {
|
||||
completion(.success(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -68,8 +77,31 @@ final class FeedWranglerAccountDelegate: AccountDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
func refreshCredentials(for account: Account, completion: @escaping (() -> Void)) {
|
||||
os_log(.debug, log: log, "Refreshing credentials...")
|
||||
// MARK: TODO
|
||||
credentials = try? account.retrieveCredentials(type: .feedWranglerToken)
|
||||
completion()
|
||||
}
|
||||
|
||||
func refreshSubscriptions(for account: Account, completion: @escaping ((Result<Void, Error>) -> Void)) {
|
||||
os_log(.debug, log: log, "Refreshing subscriptions...")
|
||||
caller.retrieveSubscriptions { result in
|
||||
switch result {
|
||||
case .success(let subscriptions):
|
||||
self.syncFeeds(account, subscriptions)
|
||||
completion(.success(()))
|
||||
|
||||
case .failure(let error):
|
||||
completion(.failure(error))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func refreshArticles(for account: Account, completion: @escaping (() -> Void)) {
|
||||
os_log(.debug, log: log, "Refreshing articles...")
|
||||
completion()
|
||||
}
|
||||
|
||||
func refreshMissingArticles(for account: Account, completion: @escaping (() -> Void)) {
|
||||
|
@ -153,4 +185,31 @@ final class FeedWranglerAccountDelegate: AccountDelegate {
|
|||
// MARK: Private
|
||||
private extension FeedWranglerAccountDelegate {
|
||||
|
||||
func syncFeeds(_ account: Account, _ subscriptions: [FeedWranglerSubscription]) {
|
||||
assert(Thread.isMainThread)
|
||||
let feedIds = subscriptions.map { String($0.feed_id) }
|
||||
|
||||
let feedsToRemove = account.topLevelFeeds.filter { !feedIds.contains($0.feedID) }
|
||||
account.removeFeeds(feedsToRemove)
|
||||
|
||||
var subscriptionsToAdd = Set<FeedWranglerSubscription>()
|
||||
subscriptions.forEach { subscription in
|
||||
let subscriptionId = String(subscription.feed_id)
|
||||
|
||||
if let feed = account.existingFeed(withFeedID: subscriptionId) {
|
||||
feed.name = subscription.title
|
||||
feed.homePageURL = subscription.site_url
|
||||
feed.subscriptionID = nil // MARK: TODO What should this be?
|
||||
} else {
|
||||
subscriptionsToAdd.insert(subscription)
|
||||
}
|
||||
}
|
||||
|
||||
subscriptionsToAdd.forEach { subscription in
|
||||
let feedId = String(subscription.feed_id)
|
||||
let feed = account.createFeed(with: subscription.title, url: subscription.feed_url, feedID: feedId, homePageURL: subscription.site_url)
|
||||
feed.subscriptionID = nil
|
||||
account.addFeed(feed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
//
|
||||
// FeedWranglerSubscription.swift
|
||||
// Account
|
||||
//
|
||||
// Created by Jonathan Bennett on 2019-10-16.
|
||||
// Copyright © 2019 Ranchero Software, LLC. All rights reserved.
|
||||
//
|
||||
import Foundation
|
||||
import RSCore
|
||||
import RSParser
|
||||
|
||||
struct FeedWranglerSubscription: Hashable, Codable {
|
||||
let title: String
|
||||
let feed_id: Int
|
||||
let feed_url: String
|
||||
let site_url: String?
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
//
|
||||
// FeedWranglerSubscriptionsRequest.swift
|
||||
// Account
|
||||
//
|
||||
// Created by Jonathan Bennett on 2019-10-16.
|
||||
// Copyright © 2019 Ranchero Software, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct FeedWranglerSubscriptionsRequest: Hashable, Codable {
|
||||
|
||||
let feeds: [FeedWranglerSubscription]
|
||||
let error: String?
|
||||
let result: String
|
||||
|
||||
}
|
Loading…
Reference in New Issue