diff --git a/Frameworks/Account/AccountTests/Feedly/FeedlySyncStreamContentsOperationTests.swift b/Frameworks/Account/AccountTests/Feedly/FeedlySyncStreamContentsOperationTests.swift index f4358b79a..897d7492c 100644 --- a/Frameworks/Account/AccountTests/Feedly/FeedlySyncStreamContentsOperationTests.swift +++ b/Frameworks/Account/AccountTests/Feedly/FeedlySyncStreamContentsOperationTests.swift @@ -45,7 +45,7 @@ class FeedlySyncStreamContentsOperationTests: XCTestCase { XCTAssertNil(serviceUnreadOnly) } - let syncStreamContents = FeedlySyncStreamContentsOperation(account: account, resource: resource, service: service, newerThan: newerThan, log: support.log) + let syncStreamContents = FeedlySyncStreamContentsOperation(account: account, resource: resource, service: service, isPagingEnabled: true, newerThan: newerThan, log: support.log) let completionExpectation = expectation(description: "Did Finish") syncStreamContents.completionBlock = { _ in @@ -79,7 +79,7 @@ class FeedlySyncStreamContentsOperationTests: XCTestCase { XCTAssertNil(serviceUnreadOnly) } - let syncStreamContents = FeedlySyncStreamContentsOperation(account: account, resource: resource, service: service, newerThan: newerThan, log: support.log) + let syncStreamContents = FeedlySyncStreamContentsOperation(account: account, resource: resource, service: service, isPagingEnabled: true, newerThan: newerThan, log: support.log) let completionExpectation = expectation(description: "Did Finish") syncStreamContents.completionBlock = { _ in @@ -120,7 +120,7 @@ class FeedlySyncStreamContentsOperationTests: XCTestCase { getStreamPageExpectation.fulfill() } - let syncStreamContents = FeedlySyncStreamContentsOperation(account: account, resource: resource, service: service, newerThan: newerThan, log: support.log) + let syncStreamContents = FeedlySyncStreamContentsOperation(account: account, resource: resource, service: service, isPagingEnabled: true, newerThan: newerThan, log: support.log) let completionExpectation = expectation(description: "Did Finish") syncStreamContents.completionBlock = { _ in diff --git a/Frameworks/Account/Feedly/FeedlyFeedContainerValidator.swift b/Frameworks/Account/Feedly/FeedlyFeedContainerValidator.swift index 62bc0c4f4..da4e6fb81 100644 --- a/Frameworks/Account/Feedly/FeedlyFeedContainerValidator.swift +++ b/Frameworks/Account/Feedly/FeedlyFeedContainerValidator.swift @@ -10,7 +10,6 @@ import Foundation struct FeedlyFeedContainerValidator { var container: Container - var userId: String? func getValidContainer() throws -> (Folder, String) { guard let folder = container as? Folder else { @@ -21,16 +20,6 @@ struct FeedlyFeedContainerValidator { throw FeedlyAccountDelegateError.addFeedInvalidFolder(folder) } - guard let userId = userId else { - throw FeedlyAccountDelegateError.notLoggedIn - } - - let uncategorized = FeedlyCategoryResourceId.Global.uncategorized(for: userId) - - guard collectionId != uncategorized.id else { - throw FeedlyAccountDelegateError.addFeedInvalidFolder(folder) - } - return (folder, collectionId) } } diff --git a/Frameworks/Account/Feedly/Models/FeedlyCategory.swift b/Frameworks/Account/Feedly/Models/FeedlyCategory.swift index 829a85dda..534788692 100644 --- a/Frameworks/Account/Feedly/Models/FeedlyCategory.swift +++ b/Frameworks/Account/Feedly/Models/FeedlyCategory.swift @@ -9,6 +9,6 @@ import Foundation struct FeedlyCategory: Decodable { - var label: String - var id: String + let label: String + let id: String } diff --git a/Frameworks/Account/Feedly/Models/FeedlyCollection.swift b/Frameworks/Account/Feedly/Models/FeedlyCollection.swift index b989c2ba3..80322ea51 100644 --- a/Frameworks/Account/Feedly/Models/FeedlyCollection.swift +++ b/Frameworks/Account/Feedly/Models/FeedlyCollection.swift @@ -9,7 +9,7 @@ import Foundation struct FeedlyCollection: Codable { - var feeds: [FeedlyFeed] - var label: String - var id: String + let feeds: [FeedlyFeed] + let label: String + let id: String } diff --git a/Frameworks/Account/Feedly/Models/FeedlyEntry.swift b/Frameworks/Account/Feedly/Models/FeedlyEntry.swift index 33a8d8c2d..cb38fd2e6 100644 --- a/Frameworks/Account/Feedly/Models/FeedlyEntry.swift +++ b/Frameworks/Account/Feedly/Models/FeedlyEntry.swift @@ -8,84 +8,58 @@ import Foundation -enum Direction: String, Codable { - case leftToRight = "ltr" - case rightToLeft = "rtl" -} - struct FeedlyEntry: Decodable { /// the unique, immutable ID for this particular article. - var id: String + let id: String /// the article’s title. This string does not contain any HTML markup. - var title: String? + let title: String? - struct Content: Codable { - var content: String? - var direction: Direction? + struct Content: Decodable { + + enum Direction: String, Decodable { + case leftToRight = "ltr" + case rightToLeft = "rtl" + } + + let content: String? + let direction: Direction? } /// This object typically has two values: “content” for the content itself, and “direction” (“ltr” for left-to-right, “rtl” for right-to-left). The content itself contains sanitized HTML markup. - var content: Content? + let content: Content? /// content object the article summary. See the content object above. - var summary: Content? + let summary: Content? /// the author’s name - var author: String? + let author: String? /// the immutable timestamp, in ms, when this article was processed by the feedly Cloud servers. - var crawled: Date + let crawled: Date /// the timestamp, in ms, when this article was re-processed and updated by the feedly Cloud servers. - var recrawled: Date? + let recrawled: Date? - /// the timestamp, in ms, when this article was published, as reported by the RSS feed (often inaccurate). -// var published: Date - - /// the timestamp, in ms, when this article was updated, as reported by the RSS feed -// var updated: Date? - /// the feed from which this article was crawled. If present, “streamId” will contain the feed id, “title” will contain the feed title, and “htmlUrl” will contain the feed’s website. - var origin: FeedlyOrigin? + let origin: FeedlyOrigin? /// Used to help find the URL to visit an article on a web site. /// See https://groups.google.com/forum/#!searchin/feedly-cloud/feed$20url%7Csort:date/feedly-cloud/Rx3dVd4aTFQ/Hf1ZfLJoCQAJ - var canonical: [FeedlyLink]? + let canonical: [FeedlyLink]? /// a list of alternate links for this article. Each link object contains a media type and a URL. Typically, a single object is present, with a link to the original web page. - var alternate: [FeedlyLink]? -// -// // var origin: -// // Optional origin object the feed from which this article was crawled. If present, “streamId” will contain the feed id, “title” will contain the feed title, and “htmlUrl” will contain the feed’s website. -// var keywords: [String]? -// -// /// an image URL for this entry. If present, “url” will contain the image URL, “width” and “height” its dimension, and “contentType” its MIME type. -// var visual: Image? -// + let alternate: [FeedlyLink]? + /// Was this entry read by the user? If an Authorization header is not provided, this will always return false. If an Authorization header is provided, it will reflect if the user has read this entry or not. - var unread: Bool -// - /// a list of tag objects (“id” and “label”) that the user added to this entry. This value is only returned if an Authorization header is provided, and at least one tag has been added. If the entry has been explicitly marked as read (not the feed itself), the “global.read” tag will be present. - var tags: [FeedlyTag]? -// - /// a list of category objects (“id” and “label”) that the user associated with the feed of this entry. This value is only returned if an Authorization header is provided. - var categories: [FeedlyCategory]? -// -// /// an indicator of how popular this entry is. The higher the number, the more readers have read, saved or shared this particular entry. -// var engagement: Int? -// -// /// Timestamp for tagged articles, contains the timestamp when the article was tagged by the user. This will only be returned when the entry is returned through the streams API. -// var actionTimestamp: Date? -// - /// A list of media links (videos, images, sound etc) provided by the feed. Some entries do not have a summary or content, only a collection of media links. - var enclosure: [FeedlyLink]? -// -// /// The article fingerprint. This value might change if the article is updated. -// var fingerprint: String - - // originId - // string the unique id of this post in the RSS feed (not necessarily a URL!) - // sid - // Optional string an internal search id. + let unread: Bool + + /// a list of tag objects (“id” and “label”) that the user added to this entry. This value is only returned if an Authorization header is provided, and at least one tag has been added. If the entry has been explicitly marked as read (not the feed itself), the “global.read” tag will be present. + let tags: [FeedlyTag]? + + /// a list of category objects (“id” and “label”) that the user associated with the feed of this entry. This value is only returned if an Authorization header is provided. + let categories: [FeedlyCategory]? + + /// A list of media links (videos, images, sound etc) provided by the feed. Some entries do not have a summary or content, only a collection of media links. + let enclosure: [FeedlyLink]? } diff --git a/Frameworks/Account/Feedly/Models/FeedlyEntryParser.swift b/Frameworks/Account/Feedly/Models/FeedlyEntryParser.swift index 4fe7589f3..06b287806 100644 --- a/Frameworks/Account/Feedly/Models/FeedlyEntryParser.swift +++ b/Frameworks/Account/Feedly/Models/FeedlyEntryParser.swift @@ -11,7 +11,7 @@ import Articles import RSParser struct FeedlyEntryParser { - var entry: FeedlyEntry + let entry: FeedlyEntry var id: String { return entry.id diff --git a/Frameworks/Account/Feedly/Models/FeedlyFeed.swift b/Frameworks/Account/Feedly/Models/FeedlyFeed.swift index 438365110..eab1eb90a 100644 --- a/Frameworks/Account/Feedly/Models/FeedlyFeed.swift +++ b/Frameworks/Account/Feedly/Models/FeedlyFeed.swift @@ -9,8 +9,8 @@ import Foundation struct FeedlyFeed: Codable { - var id: String - var title: String? - var updated: Date? - var website: String? + let id: String + let title: String? + let updated: Date? + let website: String? } diff --git a/Frameworks/Account/Feedly/Models/FeedlyFeedsSearchResponse.swift b/Frameworks/Account/Feedly/Models/FeedlyFeedsSearchResponse.swift index 17437ac23..8ddbd563b 100644 --- a/Frameworks/Account/Feedly/Models/FeedlyFeedsSearchResponse.swift +++ b/Frameworks/Account/Feedly/Models/FeedlyFeedsSearchResponse.swift @@ -11,9 +11,9 @@ import Foundation struct FeedlyFeedsSearchResponse: Decodable { struct Feed: Decodable { - var title: String - var feedId: String + let title: String + let feedId: String } - var results: [Feed] + let results: [Feed] } diff --git a/Frameworks/Account/Feedly/Models/FeedlyLink.swift b/Frameworks/Account/Feedly/Models/FeedlyLink.swift index 3756e1034..879341a08 100644 --- a/Frameworks/Account/Feedly/Models/FeedlyLink.swift +++ b/Frameworks/Account/Feedly/Models/FeedlyLink.swift @@ -9,10 +9,10 @@ import Foundation struct FeedlyLink: Decodable { - var href: String + let href: String /// The mime type of the resource located by `href`. /// When `nil`, it's probably a web page? /// https://groups.google.com/forum/#!searchin/feedly-cloud/feed$20url%7Csort:date/feedly-cloud/Rx3dVd4aTFQ/Hf1ZfLJoCQAJ - var type: String? + let type: String? } diff --git a/Frameworks/Account/Feedly/Models/FeedlyOrigin.swift b/Frameworks/Account/Feedly/Models/FeedlyOrigin.swift index 1de7c0434..bd4a8cc86 100644 --- a/Frameworks/Account/Feedly/Models/FeedlyOrigin.swift +++ b/Frameworks/Account/Feedly/Models/FeedlyOrigin.swift @@ -9,7 +9,7 @@ import Foundation struct FeedlyOrigin: Decodable { - var title: String? - var streamId: String? - var htmlUrl: String? + let title: String? + let streamId: String? + let htmlUrl: String? } diff --git a/Frameworks/Account/Feedly/Models/FeedlyResourceId.swift b/Frameworks/Account/Feedly/Models/FeedlyResourceId.swift index b39110a8f..4db6f51aa 100644 --- a/Frameworks/Account/Feedly/Models/FeedlyResourceId.swift +++ b/Frameworks/Account/Feedly/Models/FeedlyResourceId.swift @@ -17,7 +17,7 @@ protocol FeedlyResourceId { /// The Feed Resource is documented here: https://developer.feedly.com/cloud/ struct FeedlyFeedResourceId: FeedlyResourceId { - var id: String + let id: String /// The location of the kind of resource a concrete type represents. /// If the conrete type cannot strip the resource type from the Id, it should just return the Id @@ -45,7 +45,7 @@ extension FeedlyFeedResourceId { } struct FeedlyCategoryResourceId: FeedlyResourceId { - var id: String + let id: String enum Global { @@ -72,7 +72,7 @@ struct FeedlyCategoryResourceId: FeedlyResourceId { } struct FeedlyTagResourceId: FeedlyResourceId { - var id: String + let id: String enum Global { diff --git a/Frameworks/Account/Feedly/Models/FeedlyStream.swift b/Frameworks/Account/Feedly/Models/FeedlyStream.swift index f61a43a9a..fc3e92f38 100644 --- a/Frameworks/Account/Feedly/Models/FeedlyStream.swift +++ b/Frameworks/Account/Feedly/Models/FeedlyStream.swift @@ -9,16 +9,16 @@ import Foundation struct FeedlyStream: Decodable { - var id: String + let id: String /// Of the most recent entry for this stream (regardless of continuation, newerThan, etc). - var updated: Date? + let updated: Date? - /// Optional string the continuation id to pass to the next stream call, for pagination. + /// the continuation id to pass to the next stream call, for pagination. /// This id guarantees that no entry will be duplicated in a stream (meaning, there is no need to de-duplicate entries returned by this call). /// If this value is not returned, it means the end of the stream has been reached. - var continuation: String? - var items: [FeedlyEntry] + let continuation: String? + let items: [FeedlyEntry] var isStreamEnd: Bool { return continuation == nil diff --git a/Frameworks/Account/Feedly/Models/FeedlyStreamIds.swift b/Frameworks/Account/Feedly/Models/FeedlyStreamIds.swift index b79bfa3f3..a31e1005c 100644 --- a/Frameworks/Account/Feedly/Models/FeedlyStreamIds.swift +++ b/Frameworks/Account/Feedly/Models/FeedlyStreamIds.swift @@ -9,8 +9,8 @@ import Foundation struct FeedlyStreamIds: Decodable { - var continuation: String? - var ids: [String] + let continuation: String? + let ids: [String] var isStreamEnd: Bool { return continuation == nil diff --git a/Frameworks/Account/Feedly/Models/FeedlyTag.swift b/Frameworks/Account/Feedly/Models/FeedlyTag.swift index 853068478..0111b95e2 100644 --- a/Frameworks/Account/Feedly/Models/FeedlyTag.swift +++ b/Frameworks/Account/Feedly/Models/FeedlyTag.swift @@ -9,6 +9,6 @@ import Foundation struct FeedlyTag: Decodable { - var id: String - var label: String? + let id: String + let label: String? } diff --git a/Frameworks/Account/Feedly/Operations/FeedlyAddExistingFeedOperation.swift b/Frameworks/Account/Feedly/Operations/FeedlyAddExistingFeedOperation.swift index 6dcd36e91..1b921b28d 100644 --- a/Frameworks/Account/Feedly/Operations/FeedlyAddExistingFeedOperation.swift +++ b/Frameworks/Account/Feedly/Operations/FeedlyAddExistingFeedOperation.swift @@ -18,7 +18,7 @@ class FeedlyAddExistingFeedOperation: FeedlyOperation, FeedlyOperationDelegate, init(account: Account, credentials: Credentials, resource: FeedlyFeedResourceId, service: FeedlyAddFeedToCollectionService, container: Container, progress: DownloadProgress, log: OSLog) throws { - let validator = FeedlyFeedContainerValidator(container: container, userId: credentials.username) + let validator = FeedlyFeedContainerValidator(container: container) let (folder, collectionId) = try validator.getValidContainer() self.operationQueue = MainThreadOperationQueue() diff --git a/Frameworks/Account/Feedly/Operations/FeedlyAddNewFeedOperation.swift b/Frameworks/Account/Feedly/Operations/FeedlyAddNewFeedOperation.swift index 3cdf8daa8..56fd11e0f 100644 --- a/Frameworks/Account/Feedly/Operations/FeedlyAddNewFeedOperation.swift +++ b/Frameworks/Account/Feedly/Operations/FeedlyAddNewFeedOperation.swift @@ -30,7 +30,7 @@ class FeedlyAddNewFeedOperation: FeedlyOperation, FeedlyOperationDelegate, Feedl init(account: Account, credentials: Credentials, url: String, feedName: String?, searchService: FeedlySearchService, addToCollectionService: FeedlyAddFeedToCollectionService, syncUnreadIdsService: FeedlyGetStreamIdsService, getStreamContentsService: FeedlyGetStreamContentsService, database: SyncDatabase, container: Container, progress: DownloadProgress, log: OSLog) throws { - let validator = FeedlyFeedContainerValidator(container: container, userId: credentials.username) + let validator = FeedlyFeedContainerValidator(container: container) (self.folder, self.collectionId) = try validator.getValidContainer() self.url = url @@ -83,28 +83,28 @@ class FeedlyAddNewFeedOperation: FeedlyOperation, FeedlyOperationDelegate, Feedl let addRequest = FeedlyAddFeedToCollectionOperation(account: account, folder: folder, feedResource: feedResourceId, feedName: feedName, collectionId: collectionId, service: addToCollectionService) addRequest.delegate = self addRequest.downloadProgress = downloadProgress - self.operationQueue.addOperation(addRequest) + operationQueue.addOperation(addRequest) let createFeeds = FeedlyCreateFeedsForCollectionFoldersOperation(account: account, feedsAndFoldersProvider: addRequest, log: log) operationQueue.make(createFeeds, dependOn: addRequest) createFeeds.downloadProgress = downloadProgress - self.operationQueue.addOperation(createFeeds) + operationQueue.addOperation(createFeeds) let syncUnread = FeedlyIngestUnreadArticleIdsOperation(account: account, credentials: credentials, service: syncUnreadIdsService, database: database, newerThan: nil, log: log) operationQueue.make(syncUnread, dependOn: createFeeds) syncUnread.downloadProgress = downloadProgress - self.operationQueue.addOperation(syncUnread) + operationQueue.addOperation(syncUnread) - let syncFeed = FeedlySyncStreamContentsOperation(account: account, resource: feedResourceId, service: getStreamContentsService, newerThan: nil, log: log) + let syncFeed = FeedlySyncStreamContentsOperation(account: account, resource: feedResourceId, service: getStreamContentsService, isPagingEnabled: false, newerThan: nil, log: log) operationQueue.make(syncFeed, dependOn: syncUnread) syncFeed.downloadProgress = downloadProgress - self.operationQueue.addOperation(syncFeed) + operationQueue.addOperation(syncFeed) let finishOperation = FeedlyCheckpointOperation() finishOperation.checkpointDelegate = self finishOperation.downloadProgress = downloadProgress operationQueue.make(finishOperation, dependOn: syncFeed) - self.operationQueue.addOperation(finishOperation) + operationQueue.addOperation(finishOperation) } func feedlyOperation(_ operation: FeedlyOperation, didFailWith error: Error) { diff --git a/Frameworks/Account/Feedly/Operations/FeedlySyncStreamContentsOperation.swift b/Frameworks/Account/Feedly/Operations/FeedlySyncStreamContentsOperation.swift index dd5e45030..31ba1ac4f 100644 --- a/Frameworks/Account/Feedly/Operations/FeedlySyncStreamContentsOperation.swift +++ b/Frameworks/Account/Feedly/Operations/FeedlySyncStreamContentsOperation.swift @@ -17,13 +17,15 @@ final class FeedlySyncStreamContentsOperation: FeedlyOperation, FeedlyOperationD private let operationQueue = MainThreadOperationQueue() private let service: FeedlyGetStreamContentsService private let newerThan: Date? + private let isPagingEnabled: Bool private let log: OSLog private let finishOperation: FeedlyCheckpointOperation - init(account: Account, resource: FeedlyResourceId, service: FeedlyGetStreamContentsService, newerThan: Date?, log: OSLog) { + init(account: Account, resource: FeedlyResourceId, service: FeedlyGetStreamContentsService, isPagingEnabled: Bool, newerThan: Date?, log: OSLog) { self.account = account self.resource = resource self.service = service + self.isPagingEnabled = isPagingEnabled self.operationQueue.suspend() self.newerThan = newerThan self.log = log @@ -38,7 +40,7 @@ final class FeedlySyncStreamContentsOperation: FeedlyOperation, FeedlyOperationD convenience init(account: Account, credentials: Credentials, service: FeedlyGetStreamContentsService, newerThan: Date?, log: OSLog) { let all = FeedlyCategoryResourceId.Global.all(for: credentials.username) - self.init(account: account, resource: all, service: service, newerThan: newerThan, log: log) + self.init(account: account, resource: all, service: service, isPagingEnabled: true, newerThan: newerThan, log: log) } override func cancel() { @@ -98,7 +100,7 @@ final class FeedlySyncStreamContentsOperation: FeedlyOperation, FeedlyOperationD os_log(.debug, log: log, "Ingesting %i items from %@", stream.items.count, stream.id) - guard let continuation = stream.continuation else { + guard isPagingEnabled, let continuation = stream.continuation else { os_log(.debug, log: log, "Reached end of stream for %@", stream.id) return }