forked from shadowfacts/Tusker
parent
2e64500c35
commit
5e2b551045
|
@ -8,6 +8,7 @@
|
|||
|
||||
import UIKit
|
||||
import Pachyderm
|
||||
import CoreData
|
||||
|
||||
class BookmarksViewController: UIViewController, CollectionViewController {
|
||||
|
||||
|
@ -83,7 +84,7 @@ class BookmarksViewController: UIViewController, CollectionViewController {
|
|||
}
|
||||
return UICollectionViewDiffableDataSource(collectionView: collectionView) { collectionView, indexPath, itemIdentifier in
|
||||
switch itemIdentifier {
|
||||
case .status(id: let id, state: let state):
|
||||
case .status(id: let id, state: let state, addedLocally: _):
|
||||
return collectionView.dequeueConfiguredReusableCell(using: statusCell, for: indexPath, item: (id, state))
|
||||
case .loadingIndicator:
|
||||
return collectionView.dequeueConfiguredReusableCell(using: loadingCell, for: indexPath, item: ())
|
||||
|
@ -93,6 +94,9 @@ class BookmarksViewController: UIViewController, CollectionViewController {
|
|||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(handleStatusDeleted), name: .statusDeleted, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(managedObjectsDidChange), name: .NSManagedObjectContextObjectsDidChange, object: mastodonController.persistentContainer.viewContext)
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
|
@ -132,7 +136,7 @@ class BookmarksViewController: UIViewController, CollectionViewController {
|
|||
|
||||
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
|
||||
snapshot.appendSections([.bookmarks])
|
||||
snapshot.appendItems(statuses.map { .status(id: $0.id, state: .unknown) })
|
||||
snapshot.appendItems(statuses.map { .status(id: $0.id, state: .unknown, addedLocally: false) })
|
||||
await apply(snapshot: snapshot, animatingDifferences: true)
|
||||
|
||||
state = .loaded
|
||||
|
@ -170,7 +174,7 @@ class BookmarksViewController: UIViewController, CollectionViewController {
|
|||
await mastodonController.persistentContainer.addAll(statuses: statuses)
|
||||
|
||||
snapshot.deleteItems([.loadingIndicator])
|
||||
snapshot.appendItems(statuses.map { .status(id: $0.id, state: .unknown) })
|
||||
snapshot.appendItems(statuses.map { .status(id: $0.id, state: .unknown, addedLocally: false) })
|
||||
await apply(snapshot: snapshot, animatingDifferences: true)
|
||||
|
||||
state = .loaded
|
||||
|
@ -188,6 +192,63 @@ class BookmarksViewController: UIViewController, CollectionViewController {
|
|||
}
|
||||
}
|
||||
|
||||
@objc private func handleStatusDeleted(_ notification: Foundation.Notification) {
|
||||
guard let userInfo = notification.userInfo,
|
||||
let accountID = mastodonController.accountInfo?.id,
|
||||
userInfo["accountID"] as? String == accountID,
|
||||
let statusIDs = userInfo["statusIDs"] as? [String] else {
|
||||
return
|
||||
}
|
||||
var snapshot = dataSource.snapshot()
|
||||
let toDelete = statusIDs.map { id in
|
||||
Item.status(id: id, state: .unknown, addedLocally: false)
|
||||
}.filter { item in
|
||||
snapshot.itemIdentifiers.contains(item)
|
||||
}
|
||||
if !toDelete.isEmpty {
|
||||
snapshot.deleteItems(toDelete)
|
||||
Task {
|
||||
await apply(snapshot: snapshot, animatingDifferences: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func managedObjectsDidChange(_ notification: Foundation.Notification) {
|
||||
var snapshot = dataSource.snapshot()
|
||||
func prepend(item: Item) {
|
||||
if let first = snapshot.itemIdentifiers.first {
|
||||
snapshot.insertItems([item], beforeItem: first)
|
||||
} else {
|
||||
snapshot.appendItems([item])
|
||||
}
|
||||
}
|
||||
var hasChanges = false
|
||||
if let inserted = notification.userInfo?[NSInsertedObjectsKey] as? Set<NSManagedObject> {
|
||||
for case let status as StatusMO in inserted where status.bookmarked == true {
|
||||
prepend(item: .status(id: status.id, state: .unknown, addedLocally: true))
|
||||
hasChanges = true
|
||||
}
|
||||
}
|
||||
if let updated = notification.userInfo?[NSUpdatedObjectsKey] as? Set<NSManagedObject> {
|
||||
for case let status as StatusMO in updated {
|
||||
let item = Item.status(id: status.id, state: .unknown, addedLocally: true)
|
||||
var exists = snapshot.itemIdentifiers.contains(item)
|
||||
if status.bookmarked == true && !exists {
|
||||
prepend(item: item)
|
||||
hasChanges = true
|
||||
} else if status.bookmarked == false && exists {
|
||||
snapshot.deleteItems([item])
|
||||
hasChanges = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if hasChanges {
|
||||
Task {
|
||||
await apply(snapshot: snapshot, animatingDifferences: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension BookmarksViewController {
|
||||
|
@ -195,7 +256,7 @@ extension BookmarksViewController {
|
|||
case bookmarks
|
||||
}
|
||||
enum Item: Equatable, Hashable {
|
||||
case status(id: String, state: CollapseState)
|
||||
case status(id: String, state: CollapseState, addedLocally: Bool)
|
||||
case loadingIndicator
|
||||
|
||||
var hideIndicators: Bool {
|
||||
|
@ -209,7 +270,7 @@ extension BookmarksViewController {
|
|||
|
||||
static func ==(lhs: Item, rhs: Item) -> Bool {
|
||||
switch (lhs, rhs) {
|
||||
case (.status(id: let a, state: _), .status(id: let b, state: _)):
|
||||
case (.status(id: let a, _, _), .status(id: let b, _, _)):
|
||||
return a == b
|
||||
case (.loadingIndicator, .loadingIndicator):
|
||||
return true
|
||||
|
@ -220,7 +281,7 @@ extension BookmarksViewController {
|
|||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
switch self {
|
||||
case .status(id: let id, state: _):
|
||||
case .status(id: let id, _, _):
|
||||
hasher.combine(0)
|
||||
hasher.combine(id)
|
||||
case .loadingIndicator:
|
||||
|
@ -250,7 +311,7 @@ extension BookmarksViewController: UICollectionViewDelegate {
|
|||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
|
||||
if case .status(id: _, state: _) = dataSource.itemIdentifier(for: indexPath) {
|
||||
if case .status(_, _, _) = dataSource.itemIdentifier(for: indexPath) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
|
@ -258,7 +319,7 @@ extension BookmarksViewController: UICollectionViewDelegate {
|
|||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||
if case .status(id: let id, state: let state) = dataSource.itemIdentifier(for: indexPath) {
|
||||
if case .status(id: let id, state: let state, _) = dataSource.itemIdentifier(for: indexPath) {
|
||||
selected(status: id, state: state.copy())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue