Display groups and feeds

This commit is contained in:
Shadowfacts 2022-01-09 11:11:52 -05:00
parent 3ca42e9916
commit 8acc303a80
3 changed files with 114 additions and 15 deletions

View File

@ -17,6 +17,7 @@ class PersistentContainer: NSPersistentContainer {
private(set) lazy var backgroundContext: NSManagedObjectContext = { private(set) lazy var backgroundContext: NSManagedObjectContext = {
let context = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType) let context = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
// todo: should the background context really be parented to the view context, or should they both be direct children of the PSC?
context.parent = self.viewContext context.parent = self.viewContext
return context return context
}() }()
@ -58,6 +59,7 @@ class PersistentContainer: NSPersistentContainer {
if self.backgroundContext.hasChanges { if self.backgroundContext.hasChanges {
try self.backgroundContext.save() try self.backgroundContext.save()
try self.viewContext.save()
} }
} }
} }

View File

@ -44,12 +44,6 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
// Called when the scene has moved from an inactive state to an active state. // Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
} }
@MainActor
private func fetchFeeds() async {
let feeds = try! self.fervorController.persistentContainer.viewContext.fetch(Feed.fetchRequest())
print(feeds)
}
func sceneWillResignActive(_ scene: UIScene) { func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state. // Called when the scene will move from an active state to an inactive state.
@ -80,6 +74,12 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
await self.fetchFeeds() await self.fetchFeeds()
} }
} }
@MainActor
private func fetchFeeds() async {
let feeds = try! self.fervorController.persistentContainer.viewContext.fetch(Feed.fetchRequest())
print(feeds)
}
} }

View File

@ -6,11 +6,17 @@
// //
import UIKit import UIKit
import CoreData
class HomeViewController: UIViewController { class HomeViewController: UIViewController, UICollectionViewDelegate {
let fervorController: FervorController let fervorController: FervorController
private var collectionView: UICollectionView!
private var dataSource: UICollectionViewDiffableDataSource<Section, Item>!
private var groupResultsController: NSFetchedResultsController<Group>!
private var feedResultsController: NSFetchedResultsController<Feed>!
init(fervorController: FervorController) { init(fervorController: FervorController) {
self.fervorController = fervorController self.fervorController = fervorController
@ -26,14 +32,105 @@ class HomeViewController: UIViewController {
view.backgroundColor = .systemBackground view.backgroundColor = .systemBackground
let label = UILabel() // let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false // label.translatesAutoresizingMaskIntoConstraints = false
label.text = "Logged in to \(fervorController.instanceURL.host!)" // label.text = "Logged in to \(fervorController.instanceURL.host!)"
view.addSubview(label) // view.addSubview(label)
NSLayoutConstraint.activate([ // NSLayoutConstraint.activate([
label.centerXAnchor.constraint(equalTo: view.centerXAnchor), // label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
label.centerYAnchor.constraint(equalTo: view.centerYAnchor), // label.centerYAnchor.constraint(equalTo: view.centerYAnchor),
]) // ])
let configuration = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
let layout = UICollectionViewCompositionalLayout.list(using: configuration)
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout)
collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
collectionView.delegate = self
view.addSubview(collectionView)
dataSource = createDataSource()
// todo: maybe NSFetchedResultsController to automatically update when the database changes?
// applyInitialSnapshot()
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections([.groups, .feeds])
dataSource.apply(snapshot, animatingDifferences: false)
let groupReq = Group.fetchRequest()
groupReq.sortDescriptors = [NSSortDescriptor(key: "title", ascending: true)]
groupResultsController = NSFetchedResultsController(fetchRequest: groupReq, managedObjectContext: fervorController.persistentContainer.viewContext, sectionNameKeyPath: nil, cacheName: nil)
groupResultsController.delegate = self
try! groupResultsController.performFetch()
let feedReq = Feed.fetchRequest()
feedReq.sortDescriptors = [NSSortDescriptor(key: "title", ascending: true)]
feedResultsController = NSFetchedResultsController(fetchRequest: feedReq, managedObjectContext: fervorController.persistentContainer.viewContext, sectionNameKeyPath: nil, cacheName: nil)
feedResultsController.delegate = self
try! feedResultsController.performFetch()
} }
private func createDataSource() -> UICollectionViewDiffableDataSource<Section, Item> {
let listCell = UICollectionView.CellRegistration<UICollectionViewListCell, Item> { cell, indexPath, item in
var config = cell.defaultContentConfiguration()
config.text = item.title
cell.contentConfiguration = config
cell.accessories = [.disclosureIndicator()]
}
let dataSource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView) { collectionView, indexPath, item in
return collectionView.dequeueConfiguredReusableCell(using: listCell, for: indexPath, item: item)
}
return dataSource
}
// private func applyInitialSnapshot() {
// let groups = try! fervorController.persistentContainer.viewContext.fetch(Group.fetchRequest())
// let feeds = try! fervorController.persistentContainer.viewContext.fetch(Feed.fetchRequest())
//
// var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
// snapshot.appendSections([.groups, .feeds])
// snapshot.appendItems(groups.map { .group($0) }, toSection: .groups)
// snapshot.appendItems(feeds.map { .feed($0) }, toSection: .feeds)
// dataSource.apply(snapshot, animatingDifferences: false)
// }
}
extension HomeViewController {
enum Section: Hashable {
case groups
case feeds
}
enum Item: Hashable {
case group(Group)
case feed(Feed)
var title: String {
switch self {
case let .group(group):
// todo: manual codegen for models so this force unwrap isn't necessary
return group.title!
case let .feed(feed):
return feed.title!
}
}
}
}
extension HomeViewController: NSFetchedResultsControllerDelegate {
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChangeContentWith snapshot: NSDiffableDataSourceSnapshotReference) {
var snapshot = dataSource.snapshot()
if controller == groupResultsController {
if snapshot.sectionIdentifiers.contains(.groups) {
snapshot.deleteItems(snapshot.itemIdentifiers(inSection: .groups))
}
snapshot.appendItems(controller.fetchedObjects!.map { .group($0 as! Group) }, toSection: .groups)
} else if controller == feedResultsController {
if snapshot.sectionIdentifiers.contains(.feeds) {
snapshot.deleteItems(snapshot.itemIdentifiers(inSection: .feeds))
}
snapshot.appendItems(controller.fetchedObjects!.map { .feed($0 as! Feed) }, toSection: .feeds)
}
dataSource.apply(snapshot, animatingDifferences: false)
}
} }