Add new feed naming logic
This commit is contained in:
parent
9b39165018
commit
d43bf5d57a
|
@ -38,6 +38,7 @@
|
||||||
512DD4CD2431098700C17B1F /* CloudKitAccountZoneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 512DD4CC2431098700C17B1F /* CloudKitAccountZoneDelegate.swift */; };
|
512DD4CD2431098700C17B1F /* CloudKitAccountZoneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 512DD4CC2431098700C17B1F /* CloudKitAccountZoneDelegate.swift */; };
|
||||||
5132AAC42448BAD90077840A /* FeedProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5132AAC12448BAD90077840A /* FeedProvider.swift */; };
|
5132AAC42448BAD90077840A /* FeedProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5132AAC12448BAD90077840A /* FeedProvider.swift */; };
|
||||||
5132AAC52448BAD90077840A /* TwitterFeedProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5132AAC32448BAD90077840A /* TwitterFeedProvider.swift */; };
|
5132AAC52448BAD90077840A /* TwitterFeedProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5132AAC32448BAD90077840A /* TwitterFeedProvider.swift */; };
|
||||||
|
5132DE812449159100806ADE /* TwitterUser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5132DE802449159100806ADE /* TwitterUser.swift */; };
|
||||||
513323082281070D00C30F19 /* AccountFeedbinSyncTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 513323072281070C00C30F19 /* AccountFeedbinSyncTest.swift */; };
|
513323082281070D00C30F19 /* AccountFeedbinSyncTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 513323072281070C00C30F19 /* AccountFeedbinSyncTest.swift */; };
|
||||||
5133230A2281082F00C30F19 /* subscriptions_initial.json in Resources */ = {isa = PBXBuildFile; fileRef = 513323092281082F00C30F19 /* subscriptions_initial.json */; };
|
5133230A2281082F00C30F19 /* subscriptions_initial.json in Resources */ = {isa = PBXBuildFile; fileRef = 513323092281082F00C30F19 /* subscriptions_initial.json */; };
|
||||||
5133230C2281088A00C30F19 /* subscriptions_add.json in Resources */ = {isa = PBXBuildFile; fileRef = 5133230B2281088A00C30F19 /* subscriptions_add.json */; };
|
5133230C2281088A00C30F19 /* subscriptions_add.json in Resources */ = {isa = PBXBuildFile; fileRef = 5133230B2281088A00C30F19 /* subscriptions_add.json */; };
|
||||||
|
@ -276,6 +277,7 @@
|
||||||
512DD4CC2431098700C17B1F /* CloudKitAccountZoneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloudKitAccountZoneDelegate.swift; sourceTree = "<group>"; };
|
512DD4CC2431098700C17B1F /* CloudKitAccountZoneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloudKitAccountZoneDelegate.swift; sourceTree = "<group>"; };
|
||||||
5132AAC12448BAD90077840A /* FeedProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedProvider.swift; sourceTree = "<group>"; };
|
5132AAC12448BAD90077840A /* FeedProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedProvider.swift; sourceTree = "<group>"; };
|
||||||
5132AAC32448BAD90077840A /* TwitterFeedProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TwitterFeedProvider.swift; sourceTree = "<group>"; };
|
5132AAC32448BAD90077840A /* TwitterFeedProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TwitterFeedProvider.swift; sourceTree = "<group>"; };
|
||||||
|
5132DE802449159100806ADE /* TwitterUser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TwitterUser.swift; sourceTree = "<group>"; };
|
||||||
513323072281070C00C30F19 /* AccountFeedbinSyncTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountFeedbinSyncTest.swift; sourceTree = "<group>"; };
|
513323072281070C00C30F19 /* AccountFeedbinSyncTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountFeedbinSyncTest.swift; sourceTree = "<group>"; };
|
||||||
513323092281082F00C30F19 /* subscriptions_initial.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = subscriptions_initial.json; sourceTree = "<group>"; };
|
513323092281082F00C30F19 /* subscriptions_initial.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = subscriptions_initial.json; sourceTree = "<group>"; };
|
||||||
5133230B2281088A00C30F19 /* subscriptions_add.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = subscriptions_add.json; sourceTree = "<group>"; };
|
5133230B2281088A00C30F19 /* subscriptions_add.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = subscriptions_add.json; sourceTree = "<group>"; };
|
||||||
|
@ -563,6 +565,7 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
5132AAC32448BAD90077840A /* TwitterFeedProvider.swift */,
|
5132AAC32448BAD90077840A /* TwitterFeedProvider.swift */,
|
||||||
|
5132DE802449159100806ADE /* TwitterUser.swift */,
|
||||||
);
|
);
|
||||||
path = Twitter;
|
path = Twitter;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -1217,6 +1220,7 @@
|
||||||
84245C851FDDD8CB0074AFBB /* FeedbinSubscription.swift in Sources */,
|
84245C851FDDD8CB0074AFBB /* FeedbinSubscription.swift in Sources */,
|
||||||
9EF2602C23C91FFE006D160C /* FeedlyGetUpdatedArticleIdsOperation.swift in Sources */,
|
9EF2602C23C91FFE006D160C /* FeedlyGetUpdatedArticleIdsOperation.swift in Sources */,
|
||||||
3B826DAA2385C81C00FC1ADB /* FeedWranglerSubscription.swift in Sources */,
|
3B826DAA2385C81C00FC1ADB /* FeedWranglerSubscription.swift in Sources */,
|
||||||
|
5132DE812449159100806ADE /* TwitterUser.swift in Sources */,
|
||||||
3B826DAC2385C81C00FC1ADB /* FeedWranglerAccountDelegate.swift in Sources */,
|
3B826DAC2385C81C00FC1ADB /* FeedWranglerAccountDelegate.swift in Sources */,
|
||||||
769F295938E5A30D03DFF88F /* NewsBlurAccountDelegate.swift in Sources */,
|
769F295938E5A30D03DFF88F /* NewsBlurAccountDelegate.swift in Sources */,
|
||||||
769F2BA02EF5F329CDE45F5A /* NewsBlurAPICaller.swift in Sources */,
|
769F2BA02EF5F329CDE45F5A /* NewsBlurAPICaller.swift in Sources */,
|
||||||
|
|
|
@ -24,8 +24,8 @@ public protocol FeedProvider {
|
||||||
/// Provide the iconURL of the given URL
|
/// Provide the iconURL of the given URL
|
||||||
func iconURL(_ urlComponents: URLComponents, completion: @escaping (Result<String, Error>) -> Void)
|
func iconURL(_ urlComponents: URLComponents, completion: @escaping (Result<String, Error>) -> Void)
|
||||||
|
|
||||||
/// Construct a ParsedFeed that can be used to create and store a new Feed
|
/// Construct a Name for the new feed
|
||||||
func provide(_ urlComponents: URLComponents, completion: @escaping (Result<ParsedFeed, Error>) -> Void)
|
func assignName(_ urlComponents: URLComponents, completion: @escaping (Result<String, Error>) -> Void)
|
||||||
|
|
||||||
/// Refresh all the article entries (ParsedItems)
|
/// Refresh all the article entries (ParsedItems)
|
||||||
func refresh(_ webFeed: WebFeed, completion: @escaping (Result<Set<ParsedItem>, Error>) -> Void)
|
func refresh(_ webFeed: WebFeed, completion: @escaping (Result<Set<ParsedItem>, Error>) -> Void)
|
||||||
|
|
|
@ -82,7 +82,6 @@ public struct TwitterFeedProvider: FeedProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
let bestUserName = username != nil ? username : urlComponents.user
|
let bestUserName = username != nil ? username : urlComponents.user
|
||||||
|
|
||||||
if bestUserName == userID {
|
if bestUserName == userID {
|
||||||
return .owner
|
return .owner
|
||||||
}
|
}
|
||||||
|
@ -92,14 +91,65 @@ public struct TwitterFeedProvider: FeedProvider {
|
||||||
|
|
||||||
public func iconURL(_ urlComponents: URLComponents, completion: @escaping (Result<String, Error>) -> Void) {
|
public func iconURL(_ urlComponents: URLComponents, completion: @escaping (Result<String, Error>) -> Void) {
|
||||||
if let screenName = deriveScreenName(urlComponents) {
|
if let screenName = deriveScreenName(urlComponents) {
|
||||||
fetchIconURL(screenName: screenName, completion: completion)
|
fetchUser(screenName: screenName) { result in
|
||||||
|
switch result {
|
||||||
|
case .success(let user):
|
||||||
|
if let avatarURL = user.avatarURL {
|
||||||
|
completion(.success(avatarURL))
|
||||||
|
} else {
|
||||||
|
completion(.failure(TwitterFeedProviderError.screenNameNotFound))
|
||||||
|
}
|
||||||
|
case .failure(let error):
|
||||||
|
completion(.failure(error))
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
completion(.failure(TwitterFeedProviderError.screenNameNotFound))
|
completion(.failure(TwitterFeedProviderError.screenNameNotFound))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func provide(_ urlComponents: URLComponents, completion: @escaping (Result<ParsedFeed, Error>) -> Void) {
|
public func assignName(_ urlComponents: URLComponents, completion: @escaping (Result<String, Error>) -> Void) {
|
||||||
// TODO: Finish implementation
|
switch urlComponents.path {
|
||||||
|
|
||||||
|
case "/", "/home":
|
||||||
|
let name = NSLocalizedString("Twitter Timeline", comment: "Twitter Timeline")
|
||||||
|
completion(.success(name))
|
||||||
|
|
||||||
|
case "/notifications/mentions":
|
||||||
|
let name = NSLocalizedString("Twitter Mentions", comment: "Twitter Mentions")
|
||||||
|
completion(.success(name))
|
||||||
|
|
||||||
|
case "/search":
|
||||||
|
if let query = urlComponents.queryItems?.first(where: { $0.name == "q" })?.value {
|
||||||
|
let localized = NSLocalizedString("Twitter Search: %@", comment: "Twitter Search")
|
||||||
|
let searchName = NSString.localizedStringWithFormat(localized as NSString, query) as String
|
||||||
|
completion(.success(searchName))
|
||||||
|
} else {
|
||||||
|
let name = NSLocalizedString("Twitter Search", comment: "Twitter Search")
|
||||||
|
completion(.success(name))
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
if let screenName = deriveScreenName(urlComponents) {
|
||||||
|
fetchUser(screenName: screenName) { result in
|
||||||
|
switch result {
|
||||||
|
case .success(let user):
|
||||||
|
if let userName = user.name {
|
||||||
|
let localized = NSLocalizedString("%@ on Twitter", comment: "Twitter Name")
|
||||||
|
let onName = NSString.localizedStringWithFormat(localized as NSString, userName) as String
|
||||||
|
completion(.success(onName))
|
||||||
|
} else {
|
||||||
|
completion(.failure(TwitterFeedProviderError.screenNameNotFound))
|
||||||
|
}
|
||||||
|
case .failure(let error):
|
||||||
|
completion(.failure(error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
completion(.failure(TwitterFeedProviderError.unknown))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func refresh(_ webFeed: WebFeed, completion: @escaping (Result<Set<ParsedItem>, Error>) -> Void) {
|
public func refresh(_ webFeed: WebFeed, completion: @escaping (Result<Set<ParsedItem>, Error>) -> Void) {
|
||||||
|
@ -139,17 +189,19 @@ private extension TwitterFeedProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchIconURL(screenName: String, completion: @escaping (Result<String, Error>) -> Void) {
|
func fetchUser(screenName: String, completion: @escaping (Result<TwitterUser, Error>) -> Void) {
|
||||||
let url = "\(Self.apiBase)users/show.json"
|
let url = "\(Self.apiBase)users/show.json"
|
||||||
let parameters = ["screen_name": screenName]
|
let parameters = ["screen_name": screenName]
|
||||||
|
|
||||||
client.get(url, parameters: parameters) { result in
|
client.get(url, parameters: parameters) { result in
|
||||||
switch result {
|
switch result {
|
||||||
case .success(let response):
|
case .success(let response):
|
||||||
if let json = try? response.jsonObject() as? [String: Any], let url = json["profile_image_url_https"] as? String {
|
let decoder = JSONDecoder()
|
||||||
completion(.success(url))
|
do {
|
||||||
} else {
|
let user = try decoder.decode(TwitterUser.self, from: response.data)
|
||||||
completion(.failure(TwitterFeedProviderError.unknown))
|
completion(.success(user))
|
||||||
|
} catch {
|
||||||
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
completion(.failure(error))
|
completion(.failure(error))
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
//
|
||||||
|
// TwitterUser.swift
|
||||||
|
// Account
|
||||||
|
//
|
||||||
|
// Created by Maurice Parker on 4/16/20.
|
||||||
|
// Copyright © 2020 Ranchero Software, LLC. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
struct TwitterUser: Codable {
|
||||||
|
|
||||||
|
let name: String?
|
||||||
|
let avatarURL: String?
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case name = "name"
|
||||||
|
case avatarURL = "profile_image_url_https"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -115,15 +115,30 @@ final class LocalAccountDelegate: AccountDelegate {
|
||||||
// Username should be part of the URL on new feed adds
|
// Username should be part of the URL on new feed adds
|
||||||
if let feedProvider = FeedProviderManager.shared.best(for: urlComponents, with: nil) {
|
if let feedProvider = FeedProviderManager.shared.best(for: urlComponents, with: nil) {
|
||||||
|
|
||||||
refreshProgress.addToNumberOfTasksAndRemaining(1)
|
refreshProgress.addToNumberOfTasksAndRemaining(2)
|
||||||
feedProvider.provide(urlComponents) { result in
|
|
||||||
|
feedProvider.assignName(urlComponents) { result in
|
||||||
self.refreshProgress.completeTask()
|
self.refreshProgress.completeTask()
|
||||||
switch result {
|
switch result {
|
||||||
case .success(let parsedFeed):
|
|
||||||
let feed = account.createWebFeed(with: nil, url: url.absoluteString, webFeedID: url.absoluteString, homePageURL: nil)
|
case .success(let name):
|
||||||
account.update(feed, with: parsedFeed, {_ in})
|
let feed = account.createWebFeed(with: name, url: url.absoluteString, webFeedID: url.absoluteString, homePageURL: nil)
|
||||||
case .failure:
|
feed.editedName = name
|
||||||
completion(.failure(AccountError.createErrorNotFound))
|
|
||||||
|
feedProvider.refresh(feed) { result in
|
||||||
|
self.refreshProgress.completeTask()
|
||||||
|
switch result {
|
||||||
|
case .success(let parsedItems):
|
||||||
|
account.update(urlString, with: parsedItems) { _ in
|
||||||
|
container.addWebFeed(feed)
|
||||||
|
}
|
||||||
|
case .failure:
|
||||||
|
completion(.failure(AccountError.createErrorNotFound))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case .failure(let error):
|
||||||
|
completion(.failure(error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue