Make macOS timeline load synchronous and add an id to list that changes when the feed selection changes to reset the scroll
This commit is contained in:
parent
6b08b1e48b
commit
a48c894985
|
@ -28,7 +28,8 @@ class TimelineModel: ObservableObject, UndoableCommandRunner {
|
||||||
@Published var nameForDisplay = ""
|
@Published var nameForDisplay = ""
|
||||||
@Published var selectedTimelineItemIDs = Set<String>() // Don't use directly. Use selectedTimelineItemsPublisher
|
@Published var selectedTimelineItemIDs = Set<String>() // Don't use directly. Use selectedTimelineItemsPublisher
|
||||||
@Published var selectedTimelineItemID: String? = nil // Don't use directly. Use selectedTimelineItemsPublisher
|
@Published var selectedTimelineItemID: String? = nil // Don't use directly. Use selectedTimelineItemsPublisher
|
||||||
|
@Published var listID = ""
|
||||||
|
|
||||||
var selectedArticles: [Article] {
|
var selectedArticles: [Article] {
|
||||||
return selectedTimelineItems.map { $0.article }
|
return selectedTimelineItems.map { $0.article }
|
||||||
}
|
}
|
||||||
|
@ -252,6 +253,12 @@ private extension TimelineModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.assign(to: &$nameForDisplay)
|
.assign(to: &$nameForDisplay)
|
||||||
|
|
||||||
|
selectedFeedsPublisher
|
||||||
|
.map { _ in
|
||||||
|
return UUID().uuidString
|
||||||
|
}
|
||||||
|
.assign(to: &$listID)
|
||||||
|
|
||||||
// Clear the selected timeline items when the selected feed(s) change
|
// Clear the selected timeline items when the selected feed(s) change
|
||||||
selectedFeedsPublisher
|
selectedFeedsPublisher
|
||||||
|
@ -308,7 +315,7 @@ private extension TimelineModel {
|
||||||
// Download articles and transform them into timeline items
|
// Download articles and transform them into timeline items
|
||||||
let inputTimelineItemsPublisher = readFilterAndFeedsPublisher
|
let inputTimelineItemsPublisher = readFilterAndFeedsPublisher
|
||||||
.flatMap { (feeds, readFilter) in
|
.flatMap { (feeds, readFilter) in
|
||||||
Self.fetchArticles(feeds: feeds, isReadFiltered: readFilter)
|
Self.fetchArticlesPublisher(feeds: feeds, isReadFiltered: readFilter)
|
||||||
}
|
}
|
||||||
.combineLatest(sortDirectionPublisher, groupByPublisher)
|
.combineLatest(sortDirectionPublisher, groupByPublisher)
|
||||||
.compactMap { articles, sortDirection, groupBy -> TimelineItems in
|
.compactMap { articles, sortDirection, groupBy -> TimelineItems in
|
||||||
|
@ -331,7 +338,7 @@ private extension TimelineModel {
|
||||||
let downloadTimelineItemsPublisher = accountDidDownloadPublisher
|
let downloadTimelineItemsPublisher = accountDidDownloadPublisher
|
||||||
.withLatestFrom(readFilterAndFeedsPublisher)
|
.withLatestFrom(readFilterAndFeedsPublisher)
|
||||||
.flatMap { (feeds, readFilter) in
|
.flatMap { (feeds, readFilter) in
|
||||||
Self.fetchArticles(feeds: feeds, isReadFiltered: readFilter)
|
Self.fetchArticlesPublisher(feeds: feeds, isReadFiltered: readFilter)
|
||||||
}
|
}
|
||||||
.withLatestFrom(articlesSubject, sortDirectionPublisher, groupByPublisher, resultSelector: { (downloadArticles, latest) in
|
.withLatestFrom(articlesSubject, sortDirectionPublisher, groupByPublisher, resultSelector: { (downloadArticles, latest) in
|
||||||
return (downloadArticles, latest.0, latest.1, latest.2)
|
return (downloadArticles, latest.0, latest.1, latest.2)
|
||||||
|
@ -501,13 +508,54 @@ private extension TimelineModel {
|
||||||
|
|
||||||
// MARK: Article Fetching
|
// MARK: Article Fetching
|
||||||
|
|
||||||
static func fetchArticles(feeds: [Feed], isReadFiltered: Bool?) -> Future<Set<Article>, Never> {
|
func fetchArticles(feeds: [Feed], isReadFiltered: Bool?) -> Set<Article> {
|
||||||
|
if feeds.isEmpty {
|
||||||
|
return Set<Article>()
|
||||||
|
}
|
||||||
|
|
||||||
|
var fetchedArticles = Set<Article>()
|
||||||
|
for feed in feeds {
|
||||||
|
if isReadFiltered ?? true {
|
||||||
|
if let articles = try? feed.fetchUnreadArticles() {
|
||||||
|
fetchedArticles.formUnion(articles)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let articles = try? feed.fetchArticles() {
|
||||||
|
fetchedArticles.formUnion(articles)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fetchedArticles
|
||||||
|
}
|
||||||
|
|
||||||
|
static func fetchArticlesPublisher(feeds: [Feed], isReadFiltered: Bool?) -> Future<Set<Article>, Never> {
|
||||||
return Future<Set<Article>, Never> { promise in
|
return Future<Set<Article>, Never> { promise in
|
||||||
|
|
||||||
if feeds.isEmpty {
|
if feeds.isEmpty {
|
||||||
promise(.success(Set<Article>()))
|
promise(.success(Set<Article>()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if os(macOS)
|
||||||
|
|
||||||
|
var result = Set<Article>()
|
||||||
|
|
||||||
|
for feed in feeds {
|
||||||
|
if isReadFiltered ?? true {
|
||||||
|
if let articles = try? feed.fetchUnreadArticles() {
|
||||||
|
result.formUnion(articles)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let articles = try? feed.fetchArticles() {
|
||||||
|
result.formUnion(articles)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
promise(.success(result))
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
let group = DispatchGroup()
|
let group = DispatchGroup()
|
||||||
var result = Set<Article>()
|
var result = Set<Article>()
|
||||||
|
|
||||||
|
@ -534,6 +582,8 @@ private extension TimelineModel {
|
||||||
promise(.success(result))
|
promise(.success(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ struct TimelineView: View {
|
||||||
TimelineItemView(selected: selected, width: geometryReaderProxy.size.width, timelineItem: timelineItem)
|
TimelineItemView(selected: selected, width: geometryReaderProxy.size.width, timelineItem: timelineItem)
|
||||||
.background(TimelineItemFramePreferenceView(timelineItem: timelineItem))
|
.background(TimelineItemFramePreferenceView(timelineItem: timelineItem))
|
||||||
}
|
}
|
||||||
|
.id(timelineModel.listID)
|
||||||
.onPreferenceChange(TimelineItemFramePreferenceKey.self) { preferences in
|
.onPreferenceChange(TimelineItemFramePreferenceKey.self) { preferences in
|
||||||
for pref in preferences {
|
for pref in preferences {
|
||||||
timelineItemFrames[pref.articleID] = pref.frame
|
timelineItemFrames[pref.articleID] = pref.frame
|
||||||
|
@ -80,6 +81,7 @@ struct TimelineView: View {
|
||||||
}.buttonStyle(PlainButtonStyle())
|
}.buttonStyle(PlainButtonStyle())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.id(timelineModel.listID)
|
||||||
.onPreferenceChange(TimelineItemFramePreferenceKey.self) { preferences in
|
.onPreferenceChange(TimelineItemFramePreferenceKey.self) { preferences in
|
||||||
for pref in preferences {
|
for pref in preferences {
|
||||||
timelineItemFrames[pref.articleID] = pref.frame
|
timelineItemFrames[pref.articleID] = pref.frame
|
||||||
|
|
Loading…
Reference in New Issue