IGListKit/Examples/Examples-macOS/IGListKitExamples/ViewControllers/UsersViewController.swift
Christian Tietze 8f3a89412c fix cell height in macOS sample projects (#1445)
Summary:
## Changes in this pull request

The macOS sample project used to cut off descenders of the letters "y" and "g". I adjusted the programmatic cell height to match the Nib, and recenter the components vertically.

| Before | After |
| ---- |  ---- |
| ![image](https://user-images.githubusercontent.com/59080/87017842-caeb5480-c1d0-11ea-8c58-5d396ddd6081.png) | ![Screen Shot 2020-07-09 at 10 35 15](https://user-images.githubusercontent.com/59080/87017936-ea827d00-c1d0-11ea-9705-ab26b7e63c64.png) |

### Checklist

- [x] All tests pass. Demo project builds and runs.
- [x] I added tests, an experiment, or detailed why my change isn't tested.
- [x] I added an entry to the `CHANGELOG.md` for any breaking changes, enhancements, or bug fixes.
    - This doesn't sound newsworthy :)
- [x] I have reviewed the [contributing guide](https://github.com/Instagram/IGListKit/blob/master/.github/CONTRIBUTING.md)

Pull Request resolved: https://github.com/Instagram/IGListKit/pull/1445

Reviewed By: joetam

Differential Revision: D22950519

Pulled By: bdotdub

fbshipit-source-id: 506df3ab158dae52d7d86695d602cca47bc420c3
2020-08-06 10:14:53 -07:00

160 lines
5 KiB
Swift

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import Cocoa
import IGListDiffKit
final class UsersViewController: NSViewController {
@IBOutlet weak var collectionView: NSCollectionView!
// MARK: Data
var users = [User]() {
didSet {
computeFilteredUsers()
}
}
var searchTerm = "" {
didSet {
computeFilteredUsers()
}
}
private func computeFilteredUsers() {
guard !searchTerm.isEmpty else {
filteredUsers = users
return
}
filteredUsers = users.filter({ $0.name.localizedCaseInsensitiveContains(self.searchTerm) })
}
fileprivate func delete(user: User) {
guard let index = self.users.firstIndex(where: { $0.pk == user.pk }) else { return }
self.users.remove(at: index)
}
// MARK: -
// MARK: Diffing
var isFirstRun = true
var filteredUsers = [User]() {
didSet {
// A crash occurs when you try to use performBatchUpdates the first time
guard !isFirstRun else {
collectionView.reloadData()
isFirstRun = false
return
}
// get the difference between the old array of Users and the new array of Users
let diff = ListDiffPaths(fromSection: 0, toSection: 0, oldArray: oldValue, newArray: filteredUsers, option: .equality)
let batchUpdates = diff.forBatchUpdates()
let inserts = Set(batchUpdates.inserts)
let deletes = Set(batchUpdates.deletes)
let updates = Set(batchUpdates.updates)
let moves = Set(batchUpdates.moves)
// this difference is used here to update the collection view, but it can be used
// to update collection views and other similar interface elements
// this code can also be added to an extension of NSCollectionView ;)
// Set the animation duration when updating the collection view
NSAnimationContext.current.duration = 0.25
// Perform the updates to the collection view
collectionView.animator().performBatchUpdates({
collectionView.deleteItems(at: deletes)
collectionView.insertItems(at: inserts)
collectionView.reloadItems(at: updates)
moves.forEach { move in
collectionView.moveItem(at: move.from, to: move.to)
}
}, completionHandler: nil)
}
}
// MARK: -
private func loadSampleUsers() {
guard let file = Bundle.main.url(forResource: "users", withExtension: "json") else { return }
do {
self.users = try UsersProvider(with: file).users
} catch {
NSAlert(error: error).runModal()
}
}
// MARK: Interface
override func viewDidLoad() {
super.viewDidLoad()
// The view needs to be backed by a CALayer to be able to enable the collections view animations you can
// enable this by selecting the view controller's view in the Interface Builder in the Core Animation section
// of the View Effects inspector tab, through code you can do by view.wantsLayer = true
loadSampleUsers()
}
override func viewDidAppear() {
super.viewDidAppear()
view.window?.titleVisibility = .hidden
}
@IBAction func shuffle(_ sender: Any?) {
users = users.shuffled
}
@IBAction func search(_ sender: NSSearchField) {
searchTerm = sender.stringValue
}
}
extension UsersViewController: UserCollectionViewCellDelegate {
func itemDeleted(_ user: User) {
self.delete(user: user)
}
}
extension UsersViewController: NSCollectionViewDelegate {
}
extension UsersViewController: NSCollectionViewDataSource {
private struct Storyboard {
static let cellIdentifier = "UserCollectionViewCell"
}
func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
return self.filteredUsers.count
}
@available(OSX 10.11, *)
func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
let item = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: Storyboard.cellIdentifier), for: indexPath)
guard let cell = item as? UserCollectionViewCell else { return item }
cell.delegate = self
cell.bindViewModel(filteredUsers[indexPath.item])
return cell
}
}
extension UsersViewController: NSCollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> NSSize {
let availableWidth = collectionView.bounds.width
return CGSize(width: availableWidth, height: 47)
}
}