NetNewsWire/Shared/Timeline/ArticleSorter.swift

63 lines
1.8 KiB
Swift
Raw Normal View History

//
// ArticleSorter.swift
// NetNewsWire
//
// Created by Phil Viso on 9/8/19.
// Copyright © 2019 Ranchero Software. All rights reserved.
//
import Articles
import Foundation
protocol SortableArticle {
2024-05-03 21:05:53 +02:00
@MainActor var sortableName: String { get }
var sortableDate: Date { get }
var sortableArticleID: String { get }
var sortableFeedID: String { get }
}
struct ArticleSorter {
2024-05-03 21:05:53 +02:00
@MainActor static func sortedByDate<T: SortableArticle>(articles: [T],
sortDirection: ComparisonResult,
groupByFeed: Bool) -> [T] {
if groupByFeed {
return sortedByFeedName(articles: articles, sortByDateDirection: sortDirection)
} else {
return sortedByDate(articles: articles, sortDirection: sortDirection)
}
}
// MARK: -
2024-05-03 21:05:53 +02:00
@MainActor private static func sortedByFeedName<T: SortableArticle>(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<T: SortableArticle>(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
}
}
}