// // ArticleSorter.swift // NetNewsWire // // Created by Phil Viso on 9/8/19. // Copyright © 2019 Ranchero Software. All rights reserved. // import Articles import Foundation protocol SortableArticle { @MainActor var sortableName: String { get } var sortableDate: Date { get } var sortableArticleID: String { get } var sortableFeedID: String { get } } struct ArticleSorter { @MainActor static func sortedByDate(articles: [T], sortDirection: ComparisonResult, groupByFeed: Bool) -> [T] { if groupByFeed { return sortedByFeedName(articles: articles, sortByDateDirection: sortDirection) } else { return sortedByDate(articles: articles, sortDirection: sortDirection) } } // MARK: - @MainActor private static func sortedByFeedName(articles: [T], sortByDateDirection: ComparisonResult) -> [T] { // Group articles by "feed-feedID" - feed ID is used to differentiate between // two feeds that have the same name let groupedArticles = Dictionary(grouping: articles) { "\($0.sortableName.lowercased())-\($0.sortableFeedID)" } return groupedArticles .sorted { $0.key < $1.key } .flatMap { (tuple) -> [T] in let (_, articles) = tuple return sortedByDate(articles: articles, sortDirection: sortByDateDirection) } } private static func sortedByDate(articles: [T], sortDirection: ComparisonResult) -> [T] { return articles.sorted { (article1, article2) -> Bool in if article1.sortableDate == article2.sortableDate { return article1.sortableArticleID < article2.sortableArticleID } if sortDirection == .orderedDescending { return article1.sortableDate > article2.sortableDate } return article1.sortableDate < article2.sortableDate } } }