forked from shadowfacts/Tusker
Add select more photos option to asset picker
This commit is contained in:
parent
dc1eb3d6f0
commit
6138fc7748
|
@ -90,7 +90,6 @@
|
||||||
D623A5412635FB3C0095BD04 /* PollOptionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D623A5402635FB3C0095BD04 /* PollOptionView.swift */; };
|
D623A5412635FB3C0095BD04 /* PollOptionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D623A5402635FB3C0095BD04 /* PollOptionView.swift */; };
|
||||||
D623A543263634100095BD04 /* PollOptionCheckboxView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D623A542263634100095BD04 /* PollOptionCheckboxView.swift */; };
|
D623A543263634100095BD04 /* PollOptionCheckboxView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D623A542263634100095BD04 /* PollOptionCheckboxView.swift */; };
|
||||||
D625E4822588262A0074BB2B /* DraggableTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D625E4812588262A0074BB2B /* DraggableTableViewCell.swift */; };
|
D625E4822588262A0074BB2B /* DraggableTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D625E4812588262A0074BB2B /* DraggableTableViewCell.swift */; };
|
||||||
D626493323BD751600612E6E /* ShowCameraCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D626493123BD751600612E6E /* ShowCameraCollectionViewCell.xib */; };
|
|
||||||
D626493523BD94CE00612E6E /* CompositionAttachmentData.swift in Sources */ = {isa = PBXBuildFile; fileRef = D626493423BD94CE00612E6E /* CompositionAttachmentData.swift */; };
|
D626493523BD94CE00612E6E /* CompositionAttachmentData.swift in Sources */ = {isa = PBXBuildFile; fileRef = D626493423BD94CE00612E6E /* CompositionAttachmentData.swift */; };
|
||||||
D626493823C0FD0000612E6E /* AllPhotosTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D626493623C0FD0000612E6E /* AllPhotosTableViewCell.swift */; };
|
D626493823C0FD0000612E6E /* AllPhotosTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D626493623C0FD0000612E6E /* AllPhotosTableViewCell.swift */; };
|
||||||
D626493923C0FD0000612E6E /* AllPhotosTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D626493723C0FD0000612E6E /* AllPhotosTableViewCell.xib */; };
|
D626493923C0FD0000612E6E /* AllPhotosTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D626493723C0FD0000612E6E /* AllPhotosTableViewCell.xib */; };
|
||||||
|
@ -203,6 +202,7 @@
|
||||||
D681E4D9246E346E0053414F /* AccountActivityItemSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D681E4D8246E346E0053414F /* AccountActivityItemSource.swift */; };
|
D681E4D9246E346E0053414F /* AccountActivityItemSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D681E4D8246E346E0053414F /* AccountActivityItemSource.swift */; };
|
||||||
D68232F72464F4FD00325FB8 /* ComposeDrawingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68232F62464F4FD00325FB8 /* ComposeDrawingViewController.swift */; };
|
D68232F72464F4FD00325FB8 /* ComposeDrawingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68232F62464F4FD00325FB8 /* ComposeDrawingViewController.swift */; };
|
||||||
D686BBE324FBF8110068E6AA /* WrappedProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D686BBE224FBF8110068E6AA /* WrappedProgressView.swift */; };
|
D686BBE324FBF8110068E6AA /* WrappedProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D686BBE224FBF8110068E6AA /* WrappedProgressView.swift */; };
|
||||||
|
D68ACE5D279B1ABA001CE8EB /* AssetPickerControlCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68ACE5C279B1ABA001CE8EB /* AssetPickerControlCollectionViewCell.swift */; };
|
||||||
D68C2AE325869BAB00548EFF /* AuxiliarySceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68C2AE225869BAB00548EFF /* AuxiliarySceneDelegate.swift */; };
|
D68C2AE325869BAB00548EFF /* AuxiliarySceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68C2AE225869BAB00548EFF /* AuxiliarySceneDelegate.swift */; };
|
||||||
D68E525B24A3D77E0054355A /* TuskerRootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68E525A24A3D77E0054355A /* TuskerRootViewController.swift */; };
|
D68E525B24A3D77E0054355A /* TuskerRootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68E525A24A3D77E0054355A /* TuskerRootViewController.swift */; };
|
||||||
D68E525D24A3E8F00054355A /* SearchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68E525C24A3E8F00054355A /* SearchViewController.swift */; };
|
D68E525D24A3E8F00054355A /* SearchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D68E525C24A3E8F00054355A /* SearchViewController.swift */; };
|
||||||
|
@ -495,7 +495,6 @@
|
||||||
D623A5402635FB3C0095BD04 /* PollOptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollOptionView.swift; sourceTree = "<group>"; };
|
D623A5402635FB3C0095BD04 /* PollOptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollOptionView.swift; sourceTree = "<group>"; };
|
||||||
D623A542263634100095BD04 /* PollOptionCheckboxView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollOptionCheckboxView.swift; sourceTree = "<group>"; };
|
D623A542263634100095BD04 /* PollOptionCheckboxView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollOptionCheckboxView.swift; sourceTree = "<group>"; };
|
||||||
D625E4812588262A0074BB2B /* DraggableTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraggableTableViewCell.swift; sourceTree = "<group>"; };
|
D625E4812588262A0074BB2B /* DraggableTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraggableTableViewCell.swift; sourceTree = "<group>"; };
|
||||||
D626493123BD751600612E6E /* ShowCameraCollectionViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ShowCameraCollectionViewCell.xib; sourceTree = "<group>"; };
|
|
||||||
D626493423BD94CE00612E6E /* CompositionAttachmentData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompositionAttachmentData.swift; sourceTree = "<group>"; };
|
D626493423BD94CE00612E6E /* CompositionAttachmentData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompositionAttachmentData.swift; sourceTree = "<group>"; };
|
||||||
D626493623C0FD0000612E6E /* AllPhotosTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AllPhotosTableViewCell.swift; sourceTree = "<group>"; };
|
D626493623C0FD0000612E6E /* AllPhotosTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AllPhotosTableViewCell.swift; sourceTree = "<group>"; };
|
||||||
D626493723C0FD0000612E6E /* AllPhotosTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AllPhotosTableViewCell.xib; sourceTree = "<group>"; };
|
D626493723C0FD0000612E6E /* AllPhotosTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AllPhotosTableViewCell.xib; sourceTree = "<group>"; };
|
||||||
|
@ -611,6 +610,7 @@
|
||||||
D681E4D8246E346E0053414F /* AccountActivityItemSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountActivityItemSource.swift; sourceTree = "<group>"; };
|
D681E4D8246E346E0053414F /* AccountActivityItemSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountActivityItemSource.swift; sourceTree = "<group>"; };
|
||||||
D68232F62464F4FD00325FB8 /* ComposeDrawingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeDrawingViewController.swift; sourceTree = "<group>"; };
|
D68232F62464F4FD00325FB8 /* ComposeDrawingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeDrawingViewController.swift; sourceTree = "<group>"; };
|
||||||
D686BBE224FBF8110068E6AA /* WrappedProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappedProgressView.swift; sourceTree = "<group>"; };
|
D686BBE224FBF8110068E6AA /* WrappedProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappedProgressView.swift; sourceTree = "<group>"; };
|
||||||
|
D68ACE5C279B1ABA001CE8EB /* AssetPickerControlCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AssetPickerControlCollectionViewCell.swift; sourceTree = "<group>"; };
|
||||||
D68C2AE225869BAB00548EFF /* AuxiliarySceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuxiliarySceneDelegate.swift; sourceTree = "<group>"; };
|
D68C2AE225869BAB00548EFF /* AuxiliarySceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuxiliarySceneDelegate.swift; sourceTree = "<group>"; };
|
||||||
D68E525A24A3D77E0054355A /* TuskerRootViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TuskerRootViewController.swift; sourceTree = "<group>"; };
|
D68E525A24A3D77E0054355A /* TuskerRootViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TuskerRootViewController.swift; sourceTree = "<group>"; };
|
||||||
D68E525C24A3E8F00054355A /* SearchViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchViewController.swift; sourceTree = "<group>"; };
|
D68E525C24A3E8F00054355A /* SearchViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchViewController.swift; sourceTree = "<group>"; };
|
||||||
|
@ -974,11 +974,11 @@
|
||||||
children = (
|
children = (
|
||||||
D6B053A923BD2F1400A066FA /* AssetCollectionViewCell.swift */,
|
D6B053A923BD2F1400A066FA /* AssetCollectionViewCell.swift */,
|
||||||
D6B053AA23BD2F1400A066FA /* AssetCollectionViewCell.xib */,
|
D6B053AA23BD2F1400A066FA /* AssetCollectionViewCell.xib */,
|
||||||
D626493123BD751600612E6E /* ShowCameraCollectionViewCell.xib */,
|
|
||||||
D626493623C0FD0000612E6E /* AllPhotosTableViewCell.swift */,
|
D626493623C0FD0000612E6E /* AllPhotosTableViewCell.swift */,
|
||||||
D626493723C0FD0000612E6E /* AllPhotosTableViewCell.xib */,
|
D626493723C0FD0000612E6E /* AllPhotosTableViewCell.xib */,
|
||||||
D626493A23C1000300612E6E /* AlbumTableViewCell.swift */,
|
D626493A23C1000300612E6E /* AlbumTableViewCell.swift */,
|
||||||
D626493B23C1000300612E6E /* AlbumTableViewCell.xib */,
|
D626493B23C1000300612E6E /* AlbumTableViewCell.xib */,
|
||||||
|
D68ACE5C279B1ABA001CE8EB /* AssetPickerControlCollectionViewCell.swift */,
|
||||||
);
|
);
|
||||||
path = "Asset Picker";
|
path = "Asset Picker";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -1923,7 +1923,6 @@
|
||||||
D6289E84217B795D0003D1D7 /* LargeImageViewController.xib in Resources */,
|
D6289E84217B795D0003D1D7 /* LargeImageViewController.xib in Resources */,
|
||||||
D6093FB125BE0B01004811E6 /* TrendingHashtagTableViewCell.xib in Resources */,
|
D6093FB125BE0B01004811E6 /* TrendingHashtagTableViewCell.xib in Resources */,
|
||||||
D627FF79217E950100CC0648 /* DraftsTableViewController.xib in Resources */,
|
D627FF79217E950100CC0648 /* DraftsTableViewController.xib in Resources */,
|
||||||
D626493323BD751600612E6E /* ShowCameraCollectionViewCell.xib in Resources */,
|
|
||||||
D626493D23C1000300612E6E /* AlbumTableViewCell.xib in Resources */,
|
D626493D23C1000300612E6E /* AlbumTableViewCell.xib in Resources */,
|
||||||
D627944723A6AC9300D38C68 /* BasicTableViewCell.xib in Resources */,
|
D627944723A6AC9300D38C68 /* BasicTableViewCell.xib in Resources */,
|
||||||
D64BC19023C18B9D000D0238 /* FollowRequestNotificationTableViewCell.xib in Resources */,
|
D64BC19023C18B9D000D0238 /* FollowRequestNotificationTableViewCell.xib in Resources */,
|
||||||
|
@ -2096,6 +2095,7 @@
|
||||||
D627944F23A9C99800D38C68 /* EditListAccountsViewController.swift in Sources */,
|
D627944F23A9C99800D38C68 /* EditListAccountsViewController.swift in Sources */,
|
||||||
D6945C3423AC6431005C403C /* AddSavedHashtagViewController.swift in Sources */,
|
D6945C3423AC6431005C403C /* AddSavedHashtagViewController.swift in Sources */,
|
||||||
D627943723A552C200D38C68 /* BookmarkStatusActivity.swift in Sources */,
|
D627943723A552C200D38C68 /* BookmarkStatusActivity.swift in Sources */,
|
||||||
|
D68ACE5D279B1ABA001CE8EB /* AssetPickerControlCollectionViewCell.swift in Sources */,
|
||||||
D62D2426217ABF63005076CC /* UserActivityType.swift in Sources */,
|
D62D2426217ABF63005076CC /* UserActivityType.swift in Sources */,
|
||||||
D6AC956723C4347E008C9946 /* MainSceneDelegate.swift in Sources */,
|
D6AC956723C4347E008C9946 /* MainSceneDelegate.swift in Sources */,
|
||||||
D6311C5025B3765B00B27539 /* ImageDataCache.swift in Sources */,
|
D6311C5025B3765B00B27539 /* ImageDataCache.swift in Sources */,
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
<key>NSMicrophoneUsageDescription</key>
|
<key>NSMicrophoneUsageDescription</key>
|
||||||
<string>Post videos from the camera.</string>
|
<string>Post videos from the camera.</string>
|
||||||
<key>NSPhotoLibraryAddUsageDescription</key>
|
<key>NSPhotoLibraryAddUsageDescription</key>
|
||||||
<string>Save photos directly from other people's posts.</string>
|
<string>Save photos directly from other people's posts.</string>
|
||||||
<key>NSPhotoLibraryUsageDescription</key>
|
<key>NSPhotoLibraryUsageDescription</key>
|
||||||
<string>Post photos from the photo library.</string>
|
<string>Post photos from the photo library.</string>
|
||||||
<key>NSUserActivityTypes</key>
|
<key>NSUserActivityTypes</key>
|
||||||
|
|
|
@ -18,16 +18,13 @@ protocol AssetCollectionViewControllerDelegate: AnyObject {
|
||||||
func captureFromCamera()
|
func captureFromCamera()
|
||||||
}
|
}
|
||||||
|
|
||||||
class AssetCollectionViewController: UICollectionViewController {
|
class AssetCollectionViewController: UIViewController, UICollectionViewDelegate {
|
||||||
|
|
||||||
weak var delegate: AssetCollectionViewControllerDelegate?
|
weak var delegate: AssetCollectionViewControllerDelegate?
|
||||||
|
|
||||||
|
private var collectionView: UICollectionView!
|
||||||
private var dataSource: UICollectionViewDiffableDataSource<Section, Item>!
|
private var dataSource: UICollectionViewDiffableDataSource<Section, Item>!
|
||||||
private var flowLayout: UICollectionViewFlowLayout {
|
|
||||||
return collectionViewLayout as! UICollectionViewFlowLayout
|
|
||||||
}
|
|
||||||
|
|
||||||
private var availableWidth: CGFloat!
|
|
||||||
private var thumbnailSize: CGSize!
|
private var thumbnailSize: CGSize!
|
||||||
|
|
||||||
private let imageManager = PHCachingImageManager()
|
private let imageManager = PHCachingImageManager()
|
||||||
|
@ -41,7 +38,7 @@ class AssetCollectionViewController: UICollectionViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
super.init(collectionViewLayout: UICollectionViewFlowLayout())
|
super.init(nibName: nil, bundle: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
required init?(coder: NSCoder) {
|
||||||
|
@ -51,6 +48,17 @@ class AssetCollectionViewController: UICollectionViewController {
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1/3), heightDimension: .fractionalWidth(1/3))
|
||||||
|
let item = NSCollectionLayoutItem(layoutSize: itemSize)
|
||||||
|
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .fractionalWidth(1/3))
|
||||||
|
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitem: item, count: 3)
|
||||||
|
group.interItemSpacing = .fixed(4)
|
||||||
|
let section = NSCollectionLayoutSection(group: group)
|
||||||
|
let layout = UICollectionViewCompositionalLayout(section: section)
|
||||||
|
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout)
|
||||||
|
collectionView.delegate = self
|
||||||
|
view.addSubview(collectionView)
|
||||||
|
|
||||||
// use the safe area layout guide instead of letting it automatically use the safe area insets
|
// use the safe area layout guide instead of letting it automatically use the safe area insets
|
||||||
// because otherwise, when presented in a popover with the arrow on the left or right side,
|
// because otherwise, when presented in a popover with the arrow on the left or right side,
|
||||||
// the collection view content will be cut off by the width of the arrow because the popover
|
// the collection view content will be cut off by the width of the arrow because the popover
|
||||||
|
@ -73,16 +81,24 @@ class AssetCollectionViewController: UICollectionViewController {
|
||||||
collectionView.allowsSelection = true
|
collectionView.allowsSelection = true
|
||||||
|
|
||||||
collectionView.register(UINib(nibName: "AssetCollectionViewCell", bundle: .main), forCellWithReuseIdentifier: reuseIdentifier)
|
collectionView.register(UINib(nibName: "AssetCollectionViewCell", bundle: .main), forCellWithReuseIdentifier: reuseIdentifier)
|
||||||
collectionView.register(UINib(nibName: "ShowCameraCollectionViewCell", bundle: .main), forCellWithReuseIdentifier: cameraReuseIdentifier)
|
|
||||||
|
|
||||||
let scale = UIScreen.main.scale
|
let controlCell = UICollectionView.CellRegistration<AssetPickerControlCollectionViewCell, Item> { cell, indexPath, itemIdentifier in
|
||||||
let cellSize = flowLayout.itemSize
|
switch itemIdentifier {
|
||||||
thumbnailSize = CGSize(width: cellSize.width * scale, height: cellSize.height * scale)
|
case .showCamera:
|
||||||
|
cell.imageView.image = UIImage(systemName: "camera")
|
||||||
|
cell.label.text = "Take a Photo"
|
||||||
|
case .changeLimitedSelection:
|
||||||
|
cell.imageView.image = UIImage(systemName: "photo.on.rectangle.angled")
|
||||||
|
cell.label.text = "Select More Photos"
|
||||||
|
case .asset(_):
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dataSource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView, cellProvider: { (collectionView, indexPath, item) -> UICollectionViewCell? in
|
dataSource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView, cellProvider: { (collectionView, indexPath, item) -> UICollectionViewCell? in
|
||||||
switch item {
|
switch item {
|
||||||
case .showCamera:
|
case .showCamera, .changeLimitedSelection:
|
||||||
return collectionView.dequeueReusableCell(withReuseIdentifier: cameraReuseIdentifier, for: indexPath)
|
return collectionView.dequeueConfiguredReusableCell(using: controlCell, for: indexPath, item: item)
|
||||||
case let .asset(asset):
|
case let .asset(asset):
|
||||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! AssetCollectionViewCell
|
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! AssetCollectionViewCell
|
||||||
|
|
||||||
|
@ -107,30 +123,23 @@ class AssetCollectionViewController: UICollectionViewController {
|
||||||
let interactivePopGesture = navigationController?.interactivePopGestureRecognizer {
|
let interactivePopGesture = navigationController?.interactivePopGestureRecognizer {
|
||||||
singleFingerPanGesture.require(toFail: interactivePopGesture)
|
singleFingerPanGesture.require(toFail: interactivePopGesture)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PHPhotoLibrary.shared().register(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewWillAppear(_ animated: Bool) {
|
override func viewWillAppear(_ animated: Bool) {
|
||||||
super.viewWillAppear(animated)
|
super.viewWillAppear(animated)
|
||||||
|
|
||||||
|
let scale = UIScreen.main.scale
|
||||||
|
let cellWidth = view.bounds.width / 3
|
||||||
|
thumbnailSize = CGSize(width: cellWidth * scale, height: cellWidth * scale)
|
||||||
|
|
||||||
loadAssets()
|
loadAssets()
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewWillLayoutSubviews() {
|
|
||||||
super.viewWillLayoutSubviews()
|
|
||||||
|
|
||||||
let availableWidth = view.bounds.inset(by: view.safeAreaInsets).width
|
|
||||||
|
|
||||||
if self.availableWidth != availableWidth {
|
|
||||||
self.availableWidth = availableWidth
|
|
||||||
|
|
||||||
let size = (availableWidth - 8) / 3
|
|
||||||
flowLayout.itemSize = CGSize(width: size, height: size)
|
|
||||||
flowLayout.minimumInteritemSpacing = 4
|
|
||||||
flowLayout.minimumLineSpacing = 4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func loadAssets() {
|
private func loadAssets() {
|
||||||
|
var items = [Item.showCamera]
|
||||||
|
|
||||||
switch PHPhotoLibrary.authorizationStatus(for: .readWrite) {
|
switch PHPhotoLibrary.authorizationStatus(for: .readWrite) {
|
||||||
case .notDetermined:
|
case .notDetermined:
|
||||||
PHPhotoLibrary.requestAuthorization(for: .readWrite) { (_) in
|
PHPhotoLibrary.requestAuthorization(for: .readWrite) { (_) in
|
||||||
|
@ -142,8 +151,11 @@ class AssetCollectionViewController: UICollectionViewController {
|
||||||
// todo: better UI for this
|
// todo: better UI for this
|
||||||
return
|
return
|
||||||
|
|
||||||
case .authorized, .limited:
|
case .authorized:
|
||||||
// todo: show "add more" button for limited access
|
break
|
||||||
|
|
||||||
|
case .limited:
|
||||||
|
items.append(.changeLimitedSelection)
|
||||||
break
|
break
|
||||||
|
|
||||||
@unknown default:
|
@unknown default:
|
||||||
|
@ -156,7 +168,6 @@ class AssetCollectionViewController: UICollectionViewController {
|
||||||
fetchResult = fetchAssets(with: options)
|
fetchResult = fetchAssets(with: options)
|
||||||
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
|
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
|
||||||
snapshot.appendSections([.assets])
|
snapshot.appendSections([.assets])
|
||||||
var items: [Item] = [.showCamera]
|
|
||||||
fetchResult.enumerateObjects { (asset, _, _) in
|
fetchResult.enumerateObjects { (asset, _, _) in
|
||||||
items.append(.asset(asset))
|
items.append(.asset(asset))
|
||||||
}
|
}
|
||||||
|
@ -176,11 +187,11 @@ class AssetCollectionViewController: UICollectionViewController {
|
||||||
|
|
||||||
// MARK: UICollectionViewDelegate
|
// MARK: UICollectionViewDelegate
|
||||||
|
|
||||||
override func collectionView(_ collectionView: UICollectionView, shouldBeginMultipleSelectionInteractionAt indexPath: IndexPath) -> Bool {
|
func collectionView(_ collectionView: UICollectionView, shouldBeginMultipleSelectionInteractionAt indexPath: IndexPath) -> Bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
|
func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
|
||||||
guard let item = dataSource.itemIdentifier(for: indexPath) else { return false }
|
guard let item = dataSource.itemIdentifier(for: indexPath) else { return false }
|
||||||
if let delegate = delegate,
|
if let delegate = delegate,
|
||||||
case let .asset(asset) = item {
|
case let .asset(asset) = item {
|
||||||
|
@ -189,29 +200,32 @@ class AssetCollectionViewController: UICollectionViewController {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||||
guard let item = dataSource.itemIdentifier(for: indexPath) else { return }
|
guard let item = dataSource.itemIdentifier(for: indexPath) else { return }
|
||||||
switch item {
|
switch item {
|
||||||
case .showCamera:
|
case .showCamera:
|
||||||
collectionView.deselectItem(at: indexPath, animated: false)
|
collectionView.deselectItem(at: indexPath, animated: false)
|
||||||
delegate?.captureFromCamera()
|
delegate?.captureFromCamera()
|
||||||
|
case .changeLimitedSelection:
|
||||||
|
// todo: change observer
|
||||||
|
PHPhotoLibrary.shared().presentLimitedLibraryPicker(from: self)
|
||||||
case .asset(_):
|
case .asset(_):
|
||||||
updateItemsSelectedCount()
|
updateItemsSelectedCount()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
|
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
|
||||||
updateItemsSelectedCount()
|
updateItemsSelectedCount()
|
||||||
}
|
}
|
||||||
|
|
||||||
override func collectionView(_ collectionView: UICollectionView, contextMenuConfigurationForItemAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
|
func collectionView(_ collectionView: UICollectionView, contextMenuConfigurationForItemAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
|
||||||
guard case let .asset(asset) = dataSource.itemIdentifier(for: indexPath) else { return nil }
|
guard case let .asset(asset) = dataSource.itemIdentifier(for: indexPath) else { return nil }
|
||||||
return UIContextMenuConfiguration(identifier: indexPath as NSIndexPath, previewProvider: { () -> UIViewController? in
|
return UIContextMenuConfiguration(identifier: indexPath as NSIndexPath, previewProvider: { () -> UIViewController? in
|
||||||
return AssetPreviewViewController(asset: asset)
|
return AssetPreviewViewController(asset: asset)
|
||||||
}, actionProvider: nil)
|
}, actionProvider: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func collectionView(_ collectionView: UICollectionView, previewForHighlightingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
|
func collectionView(_ collectionView: UICollectionView, previewForHighlightingContextMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
|
||||||
if let indexPath = (configuration.identifier as? NSIndexPath) as IndexPath?,
|
if let indexPath = (configuration.identifier as? NSIndexPath) as IndexPath?,
|
||||||
let cell = collectionView.cellForItem(at: indexPath) as? AssetCollectionViewCell {
|
let cell = collectionView.cellForItem(at: indexPath) as? AssetCollectionViewCell {
|
||||||
let parameters = UIPreviewParameters()
|
let parameters = UIPreviewParameters()
|
||||||
|
@ -237,6 +251,15 @@ extension AssetCollectionViewController {
|
||||||
}
|
}
|
||||||
enum Item: Hashable {
|
enum Item: Hashable {
|
||||||
case showCamera
|
case showCamera
|
||||||
|
case changeLimitedSelection
|
||||||
case asset(PHAsset)
|
case asset(PHAsset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension AssetCollectionViewController: PHPhotoLibraryChangeObserver {
|
||||||
|
func photoLibraryDidChange(_ changeInstance: PHChange) {
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.loadAssets()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
//
|
||||||
|
// AssetPickerControlCollectionViewCell.swift
|
||||||
|
// Tusker
|
||||||
|
//
|
||||||
|
// Created by Shadowfacts on 1/21/22.
|
||||||
|
// Copyright © 2022 Shadowfacts. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class AssetPickerControlCollectionViewCell: UICollectionViewCell {
|
||||||
|
|
||||||
|
let imageView = UIImageView()
|
||||||
|
let label = UILabel()
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
|
||||||
|
imageView.contentMode = .scaleAspectFit
|
||||||
|
imageView.setContentHuggingPriority(.defaultLow, for: .vertical)
|
||||||
|
|
||||||
|
label.font = .preferredFont(forTextStyle: .caption1)
|
||||||
|
label.textAlignment = .center
|
||||||
|
|
||||||
|
let stackView = UIStackView(arrangedSubviews: [
|
||||||
|
imageView,
|
||||||
|
label,
|
||||||
|
])
|
||||||
|
stackView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
stackView.axis = .vertical
|
||||||
|
stackView.alignment = .center
|
||||||
|
addSubview(stackView)
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
stackView.leadingAnchor.constraint(equalTo: leadingAnchor),
|
||||||
|
stackView.trailingAnchor.constraint(equalTo: trailingAnchor),
|
||||||
|
stackView.topAnchor.constraint(equalTo: topAnchor, constant: 8),
|
||||||
|
stackView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8),
|
||||||
|
|
||||||
|
imageView.widthAnchor.constraint(equalTo: widthAnchor, constant: -32)
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,37 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="15702" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
|
||||||
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
|
||||||
<dependencies>
|
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15704"/>
|
|
||||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
|
||||||
</dependencies>
|
|
||||||
<objects>
|
|
||||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
|
||||||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="gTV-IL-0wX">
|
|
||||||
<rect key="frame" x="0.0" y="0.0" width="80" height="80"/>
|
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
|
||||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
|
||||||
<rect key="frame" x="0.0" y="0.0" width="80" height="80"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
|
||||||
<subviews>
|
|
||||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="camera" catalog="system" translatesAutoresizingMaskIntoConstraints="NO" id="fUY-i2-EtY">
|
|
||||||
<rect key="frame" x="16" y="16.5" width="48" height="46"/>
|
|
||||||
</imageView>
|
|
||||||
</subviews>
|
|
||||||
</view>
|
|
||||||
<constraints>
|
|
||||||
<constraint firstAttribute="bottom" secondItem="fUY-i2-EtY" secondAttribute="bottom" constant="16" id="HkO-Cn-2Na"/>
|
|
||||||
<constraint firstItem="fUY-i2-EtY" firstAttribute="top" secondItem="gTV-IL-0wX" secondAttribute="top" constant="16" id="bUq-pX-5XL"/>
|
|
||||||
<constraint firstAttribute="trailing" secondItem="fUY-i2-EtY" secondAttribute="trailing" constant="16" id="fyg-fN-FJu"/>
|
|
||||||
<constraint firstItem="fUY-i2-EtY" firstAttribute="leading" secondItem="gTV-IL-0wX" secondAttribute="leading" constant="16" id="oOU-Tc-Z5T"/>
|
|
||||||
</constraints>
|
|
||||||
<viewLayoutGuide key="safeArea" id="ZTg-uK-7eu"/>
|
|
||||||
<point key="canvasLocation" x="132" y="154"/>
|
|
||||||
</collectionViewCell>
|
|
||||||
</objects>
|
|
||||||
<resources>
|
|
||||||
<image name="camera" catalog="system" width="64" height="48"/>
|
|
||||||
</resources>
|
|
||||||
</document>
|
|
Loading…
Reference in New Issue