2022-06-20 15:32:58 +00:00
|
|
|
//
|
|
|
|
// WidgetHelper.swift
|
|
|
|
// Reader
|
|
|
|
//
|
|
|
|
// Created by Shadowfacts on 6/19/22.
|
|
|
|
//
|
|
|
|
|
|
|
|
import Foundation
|
|
|
|
import WidgetKit
|
|
|
|
import Persistence
|
2022-06-22 20:05:06 +00:00
|
|
|
import OSLog
|
|
|
|
|
|
|
|
private let logger = Logger(subsystem: "net.shadowfacts.Reader", category: "WidgetHelper")
|
2022-09-10 03:51:41 +00:00
|
|
|
private let signposter = OSSignposter(logger: logger)
|
2022-06-20 15:32:58 +00:00
|
|
|
|
|
|
|
struct WidgetHelper {
|
|
|
|
private init() {}
|
|
|
|
|
|
|
|
private static let maxDisplayableItems = 8
|
|
|
|
|
|
|
|
static func updateWidgetData(fervorController: FervorController) async {
|
|
|
|
// Accessing CoreData from the widget extension puts us over the memory limit, so we pre-generate all the data it needs and save it to disk
|
|
|
|
|
2022-06-22 20:05:06 +00:00
|
|
|
let context = fervorController.persistentContainer.backgroundContext
|
|
|
|
let prioritizedItems: [WidgetData.Item] = await context.perform {
|
2022-06-20 15:32:58 +00:00
|
|
|
let req = Item.fetchRequest()
|
|
|
|
req.sortDescriptors = [NSSortDescriptor(key: "published", ascending: false)]
|
|
|
|
req.fetchLimit = 32
|
|
|
|
req.predicate = NSPredicate(format: "read = NO")
|
2022-09-10 03:51:41 +00:00
|
|
|
let state = signposter.beginInterval("fetch")
|
2022-06-22 20:05:06 +00:00
|
|
|
var items = (try? context.fetch(req)) ?? []
|
2022-09-10 03:51:41 +00:00
|
|
|
signposter.endInterval("fetch", state)
|
2022-06-20 15:32:58 +00:00
|
|
|
|
|
|
|
var prioritizedItems: [Item] = []
|
|
|
|
|
|
|
|
while prioritizedItems.count < maxDisplayableItems {
|
|
|
|
let firstFromUnseenFeedIdx = items.firstIndex { item in
|
|
|
|
prioritizedItems.allSatisfy { existing in
|
|
|
|
existing.feed != item.feed
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if let firstFromUnseenFeedIdx {
|
|
|
|
prioritizedItems.append(items.remove(at: firstFromUnseenFeedIdx))
|
|
|
|
} else if let item = items.first {
|
|
|
|
prioritizedItems.append(item)
|
|
|
|
items.removeFirst()
|
|
|
|
} else {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return prioritizedItems.map {
|
|
|
|
WidgetData.Item(id: $0.id!, feedTitle: $0.feed?.title, title: $0.title, published: $0.published)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-14 17:16:33 +00:00
|
|
|
if let item = prioritizedItems.first {
|
|
|
|
logger.info("Saving widget data with first item: '\(item.title ?? "<untitled>", privacy: .public)'")
|
|
|
|
}
|
2022-09-08 02:57:48 +00:00
|
|
|
|
2022-06-20 15:32:58 +00:00
|
|
|
WidgetData(recentItems: prioritizedItems).save(account: fervorController.account!)
|
|
|
|
|
|
|
|
WidgetCenter.shared.reloadAllTimelines()
|
|
|
|
}
|
|
|
|
}
|