Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Source/Helpers/Extensions/IndexSet+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
import Foundation

internal extension IndexSet {
func aapl_indexPathsFromIndexesWithSection(_ section: Int) -> [IndexPath] {
func aapl_indexPathsFromIndexesWithSection(_ section: Int, offset: Int = 0) -> [IndexPath] {
var indexPaths: [IndexPath] = []
indexPaths.reserveCapacity(count)
(self as NSIndexSet).enumerate({idx, _ in
indexPaths.append(IndexPath(item: idx, section: section))
indexPaths.append(IndexPath(item: idx + offset, section: section))
})
return indexPaths
}
Expand Down
40 changes: 34 additions & 6 deletions Source/Pages/Gallery/YPLibrary+LibraryChange.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,29 +23,57 @@ extension YPLibraryVC: PHPhotoLibraryChangeObserver {

DispatchQueue.main.async {
let collectionView = self.v.collectionView
self.mediaManager.fetchResult = collectionChanges.fetchResultAfterChanges

// Guard against updates when the view isn't in the hierarchy
guard collectionView.window != nil else {
self.mediaManager.fetchResult = collectionChanges.fetchResultAfterChanges
collectionView.reloadData()
self.updateAssetSelection()
self.mediaManager.resetCachedAssets()
return
}

if !collectionChanges.hasIncrementalChanges || collectionChanges.hasMoves {
self.mediaManager.fetchResult = collectionChanges.fetchResultAfterChanges
collectionView.reloadData()
} else {
// Validate that the current data source count matches what PHChange expects
// before attempting incremental updates
let expectedOldCount = collectionChanges.fetchResultBeforeChanges.count
let cameraButtonOffset = YPConfig.library.showGalleryCameraButton ? 1 : 0
let actualOldCount = collectionView.numberOfItems(inSection: 0) - cameraButtonOffset

guard expectedOldCount == actualOldCount else {
ypLog("Data source count mismatch (expected: \(expectedOldCount), actual: \(actualOldCount)). Falling back to reloadData.")
self.mediaManager.fetchResult = collectionChanges.fetchResultAfterChanges
collectionView.reloadData()
self.updateAssetSelection()
self.mediaManager.resetCachedAssets()
return
}

collectionView.performBatchUpdates({
// Update fetchResult inside performBatchUpdates so that
// UICollectionView sees the old count at the start and the
// new count at the end, matching the applied deletes/inserts.
self.mediaManager.fetchResult = collectionChanges.fetchResultAfterChanges

if let removedIndexes = collectionChanges.removedIndexes,
removedIndexes.count != 0 {
collectionView.deleteItems(at: removedIndexes.aapl_indexPathsFromIndexesWithSection(0))
collectionView.deleteItems(at: removedIndexes.aapl_indexPathsFromIndexesWithSection(0, offset: cameraButtonOffset))
}

if let insertedIndexes = collectionChanges.insertedIndexes, insertedIndexes.count != 0 {
collectionView.insertItems(at: insertedIndexes.aapl_indexPathsFromIndexesWithSection(0))
collectionView.insertItems(at: insertedIndexes.aapl_indexPathsFromIndexesWithSection(0, offset: cameraButtonOffset))
}
}, completion: { finished in
guard finished else { return }
guard let changedIndexes = collectionChanges.changedIndexes,
changedIndexes.count != 0 else {
ypLog("No changes detected")
collectionView.reloadData() // If we failed to detect changes, we'll reload everything just in case
return
}

collectionView.reloadItems(at: changedIndexes.aapl_indexPathsFromIndexesWithSection(0))
collectionView.reloadItems(at: changedIndexes.aapl_indexPathsFromIndexesWithSection(0, offset: cameraButtonOffset))
})
}

Expand Down
Loading