Skip to content

Commit

Permalink
feat(concurrency): update HomeViewModel, make fetched result vc deleg…
Browse files Browse the repository at this point in the history
…ate call concurrency safe
  • Loading branch information
Gio2018 committed Jul 23, 2024
1 parent 889a67a commit 43e3090
Showing 1 changed file with 63 additions and 51 deletions.
114 changes: 63 additions & 51 deletions PocketKit/Sources/PocketKit/Home/HomeViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -964,62 +964,74 @@ extension HomeViewModel {
}

extension HomeViewModel: NSFetchedResultsControllerDelegate {
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChangeContentWith snapshot: NSDiffableDataSourceSnapshotReference) {
var newSnapshot = buildSnapshot()

if controller == recentSavesController {
let reloadedItemIdentifiers: [Cell] = snapshot.reloadedItemIdentifiers.compactMap({ .recentSaves($0 as! NSManagedObjectID) })
let reconfiguredItemdIdentifiers: [Cell] = snapshot.reconfiguredItemIdentifiers.compactMap({ .recentSaves($0 as! NSManagedObjectID) })
newSnapshot.reloadItems(reloadedItemIdentifiers)
newSnapshot.reconfigureItems(reconfiguredItemdIdentifiers)
updateRecentSavesWidget()
}
nonisolated func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChangeContentWith snapshot: NSDiffableDataSourceSnapshotReference) {
let isRecentSaves = controller is NSFetchedResultsController<SavedItem>
let isRecommendations = controller is RichFetchedResultsController<Recommendation>
let isSharedWithYou = controller is RichFetchedResultsController<SharedWithYouItem>

if isOffline {
// If we are offline don't try and do anything with Slates, and let the snapshot show the offline
setRecommendationsWidgetOffline()
self.snapshot = newSnapshot
return
}
let reloadedRecentSaves: [Cell] = snapshot.reloadedItemIdentifiers.compactMap({ .recentSaves($0 as! NSManagedObjectID) })
let reconfiguredRecentSaves: [Cell] = snapshot.reconfiguredItemIdentifiers.compactMap({ .recentSaves($0 as! NSManagedObjectID) })

if controller == recomendationsController {
let existingItemIdentifiers = newSnapshot.itemIdentifiers

// Gather all variations a recomendation could exist in for reloaded identifiers
var reloadedItemIdentifiers: [Cell] = snapshot.reloadedItemIdentifiers.compactMap({ .recommendationHero($0 as! NSManagedObjectID) })
reloadedItemIdentifiers.append(contentsOf: snapshot.reloadedItemIdentifiers.compactMap({ .recommendationCarousel($0 as! NSManagedObjectID) }))
// Filter to just the ones that exist in our snapshot
reloadedItemIdentifiers = reloadedItemIdentifiers.filter({ existingItemIdentifiers.contains($0) })
// Tell the new snapshot to reload just the ones that exist
newSnapshot.reloadItems(reloadedItemIdentifiers)

// Gather all variations a recomendation could exist in for reconfigured identifiers
var reconfiguredItemIdentifiers: [Cell] = snapshot.reconfiguredItemIdentifiers.compactMap({ .recommendationHero($0 as! NSManagedObjectID) })
reconfiguredItemIdentifiers.append(contentsOf: snapshot.reconfiguredItemIdentifiers.compactMap({ .recommendationCarousel($0 as! NSManagedObjectID) }))
// Filter to just the ones that exist in our snapshot
reconfiguredItemIdentifiers = reconfiguredItemIdentifiers.filter({ existingItemIdentifiers.contains($0) })
// Tell the new snapshot to reconfigure just the ones that exist
newSnapshot.reconfigureItems(reconfiguredItemIdentifiers)
updateRecommendationsWidget()
}
let reloadedHeroRecommendations: [Cell] = snapshot.reloadedItemIdentifiers.compactMap({ .recommendationHero($0 as! NSManagedObjectID) })
let reconfiguredHeroRecommendations: [Cell] = snapshot.reconfiguredItemIdentifiers.compactMap({ .recommendationHero($0 as! NSManagedObjectID) })

let reloadedCarouselRecommendations: [Cell] = snapshot.reloadedItemIdentifiers.compactMap({ .recommendationCarousel($0 as! NSManagedObjectID) })
let reconfiguredCarouselRecommendations: [Cell] = snapshot.reconfiguredItemIdentifiers.compactMap({ .recommendationCarousel($0 as! NSManagedObjectID) })

let reloadedSharedWithYou: [Cell] = snapshot.reloadedItemIdentifiers.compactMap({ .sharedWithYou($0 as! NSManagedObjectID) })
let reconfiguredSharedWithYou: [Cell] = snapshot.reconfiguredItemIdentifiers.compactMap({ .sharedWithYou($0 as! NSManagedObjectID) })

Task { @MainActor in
var newSnapshot = buildSnapshot()

if isRecentSaves {
newSnapshot.reloadItems(reloadedRecentSaves)
newSnapshot.reconfigureItems(reconfiguredRecentSaves)
updateRecentSavesWidget()
}

if controller == sharedWithYouController {
let existingItemIdentifiers = newSnapshot.itemIdentifiers
let reloadedItems: [Cell] =
snapshot
.reloadedItemIdentifiers
.compactMap { .sharedWithYou($0 as! NSManagedObjectID) }
.filter { existingItemIdentifiers.contains($0) }
let reconfiguredItems: [Cell] =
snapshot
.reconfiguredItemIdentifiers
.compactMap { .sharedWithYou($0 as! NSManagedObjectID) }
.filter { existingItemIdentifiers.contains($0) }
newSnapshot.reloadItems(reloadedItems)
newSnapshot.reconfigureItems(reconfiguredItems)
if isOffline {
// If we are offline don't try and do anything with Slates, and let the snapshot show the offline
setRecommendationsWidgetOffline()
self.updateSnapshot(newSnapshot)
return
}

if isRecommendations {
let existingItemIdentifiers = newSnapshot.itemIdentifiers

// Gather all variations a recomendation could exist in for reloaded identifiers
var reloadedItemIdentifiers = reloadedHeroRecommendations
reloadedItemIdentifiers.append(contentsOf: reloadedCarouselRecommendations)
// Filter to just the ones that exist in our snapshot
reloadedItemIdentifiers = reloadedItemIdentifiers.filter({ existingItemIdentifiers.contains($0) })
// Tell the new snapshot to reload just the ones that exist
newSnapshot.reloadItems(reloadedItemIdentifiers)

// Gather all variations a recomendation could exist in for reconfigured identifiers
var reconfiguredItemIdentifiers = reconfiguredHeroRecommendations
reconfiguredItemIdentifiers.append(contentsOf: reconfiguredCarouselRecommendations)
// Filter to just the ones that exist in our snapshot
reconfiguredItemIdentifiers = reconfiguredItemIdentifiers.filter({ existingItemIdentifiers.contains($0) })
// Tell the new snapshot to reconfigure just the ones that exist
newSnapshot.reconfigureItems(reconfiguredItemIdentifiers)
updateRecommendationsWidget()
}

if isSharedWithYou {
let existingItemIdentifiers = newSnapshot.itemIdentifiers
let reloadedItems = reloadedSharedWithYou.filter { existingItemIdentifiers.contains($0) }
let reconfiguredItems = reconfiguredSharedWithYou.filter { existingItemIdentifiers.contains($0) }
newSnapshot.reloadItems(reloadedItems)
newSnapshot.reconfigureItems(reconfiguredItems)
}

self.updateSnapshot(newSnapshot)
}
}

self.snapshot = newSnapshot
private func updateSnapshot(_ snapshot: Snapshot) {
self.snapshot = snapshot
}
}

Expand Down

0 comments on commit 43e3090

Please sign in to comment.