diff --git a/Demo/DemoListViewController.swift b/Demo/DemoListViewController.swift index 277b42f..4f7cc78 100644 --- a/Demo/DemoListViewController.swift +++ b/Demo/DemoListViewController.swift @@ -16,6 +16,7 @@ import UIKit import NohanaImagePicker import Photos +import PhotosUI struct Cell { let title: String @@ -72,7 +73,13 @@ class DemoListViewController: UITableViewController, NohanaImagePickerController // MARK: - Photos func checkIfAuthorizedToAccessPhotos(_ handler: @escaping (_ isAuthorized: Bool) -> Void) { - switch PHPhotoLibrary.authorizationStatus() { + let status: PHAuthorizationStatus + if #available(iOS 14, *) { + status = PHPhotoLibrary.authorizationStatus(for: .readWrite) + } else { + status = PHPhotoLibrary.authorizationStatus() + } + switch status { case .notDetermined: PHPhotoLibrary.requestAuthorization { status in DispatchQueue.main.async { @@ -238,4 +245,21 @@ class DemoListViewController: UITableViewController, NohanaImagePickerController func nohanaImagePicker(_ picker: NohanaImagePickerController, assetDetailListViewController: UICollectionViewController, didChangeAssetDetailPage indexPath: IndexPath, photoKitAsset: PHAsset) { print("🐷\(#function)\n\tindexPath = \(indexPath)") } + + func nohanaImagePickerDidTapAddPhotoButton(_ picker: NohanaImagePickerController) { + print("🐷\(#function)") + if #available(iOS 14, *) { + PHPhotoLibrary.shared().presentLimitedLibraryPicker(from: picker) + } + } + + func nohanaImagePickerDidTapAuthorizeAllPhotoButton(_ picker: NohanaImagePickerController) { + print("🐷\(#function)") + guard let url = URL(string: UIApplication.openSettingsURLString), + UIApplication.shared.canOpenURL(url) else { + assertionFailure("Not able to open App privacy settings") + return + } + UIApplication.shared.open(url, options: [:], completionHandler: nil) + } } diff --git a/Demo/Info.plist b/Demo/Info.plist index 36e869d..3de749b 100644 --- a/Demo/Info.plist +++ b/Demo/Info.plist @@ -45,5 +45,7 @@ NSPhotoLibraryUsageDescription To pick some photos. + PHPhotoLibraryPreventAutomaticLimitedAccessAlert + diff --git a/NohanaImagePicker.xcodeproj/project.pbxproj b/NohanaImagePicker.xcodeproj/project.pbxproj index 93471c5..4fdbb7d 100644 --- a/NohanaImagePicker.xcodeproj/project.pbxproj +++ b/NohanaImagePicker.xcodeproj/project.pbxproj @@ -17,6 +17,8 @@ 6AD1607C27700F0C00A8B066 /* RootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD1607B27700F0C00A8B066 /* RootViewController.swift */; }; 6AD1607F2770B23D00A8B066 /* UIApplication+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD1607E2770B23D00A8B066 /* UIApplication+Ex.swift */; }; F117F732273B6A2600E11BC7 /* AssetDateSectionCreater.swift in Sources */ = {isa = PBXBuildFile; fileRef = F117F731273B6A2600E11BC7 /* AssetDateSectionCreater.swift */; }; + F145C5E22890F8DC0070A4E2 /* PhotoAuthorizationLimitedCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F145C5E02890F8DC0070A4E2 /* PhotoAuthorizationLimitedCell.swift */; }; + F145C5E32890F8DC0070A4E2 /* PhotoAuthorizationLimitedCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F145C5E12890F8DC0070A4E2 /* PhotoAuthorizationLimitedCell.xib */; }; F181095026A5361A001C2BDE /* MomentDetailListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F181094F26A5361A001C2BDE /* MomentDetailListViewController.swift */; }; F1A26CCD2738DE6A00433E9F /* AssetListSelectableDateSection.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F1A26CCC2738DE6A00433E9F /* AssetListSelectableDateSection.storyboard */; }; F1A26CCF2738E7E400433E9F /* AssetListSelectableDateSectionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1A26CCE2738E7E400433E9F /* AssetListSelectableDateSectionController.swift */; }; @@ -99,6 +101,8 @@ 6AD1607B27700F0C00A8B066 /* RootViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootViewController.swift; sourceTree = ""; }; 6AD1607E2770B23D00A8B066 /* UIApplication+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIApplication+Ex.swift"; sourceTree = ""; }; F117F731273B6A2600E11BC7 /* AssetDateSectionCreater.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AssetDateSectionCreater.swift; sourceTree = ""; }; + F145C5E02890F8DC0070A4E2 /* PhotoAuthorizationLimitedCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoAuthorizationLimitedCell.swift; sourceTree = ""; }; + F145C5E12890F8DC0070A4E2 /* PhotoAuthorizationLimitedCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PhotoAuthorizationLimitedCell.xib; sourceTree = ""; }; F181094F26A5361A001C2BDE /* MomentDetailListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MomentDetailListViewController.swift; sourceTree = ""; }; F1A26CCC2738DE6A00433E9F /* AssetListSelectableDateSection.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = AssetListSelectableDateSection.storyboard; sourceTree = ""; }; F1A26CCE2738E7E400433E9F /* AssetListSelectableDateSectionController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AssetListSelectableDateSectionController.swift; sourceTree = ""; }; @@ -233,6 +237,8 @@ F1A26CCC2738DE6A00433E9F /* AssetListSelectableDateSection.storyboard */, F27029CD1C71C43A001647AB /* NohanaImagePicker.strings */, F237249A1C6DCF96005D1E8A /* NohanaImagePicker.xcassets */, + F145C5E02890F8DC0070A4E2 /* PhotoAuthorizationLimitedCell.swift */, + F145C5E12890F8DC0070A4E2 /* PhotoAuthorizationLimitedCell.xib */, ); name = Resources; sourceTree = ""; @@ -439,6 +445,7 @@ F237249B1C6DCF96005D1E8A /* NohanaImagePicker.xcassets in Resources */, 6A8047FF276C3D77000F3B28 /* AlbumList.storyboard in Resources */, F1A26CCD2738DE6A00433E9F /* AssetListSelectableDateSection.storyboard in Resources */, + F145C5E32890F8DC0070A4E2 /* PhotoAuthorizationLimitedCell.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -479,6 +486,7 @@ F2131F431C79615700797887 /* SwipeInteractionController.swift in Sources */, F2DF3B2D1C6D780100C1C0E4 /* AssetDetailCell.swift in Sources */, F25C69901CA27311005935D6 /* EmptyIndicatable.swift in Sources */, + F145C5E22890F8DC0070A4E2 /* PhotoAuthorizationLimitedCell.swift in Sources */, F117F732273B6A2600E11BC7 /* AssetDateSectionCreater.swift in Sources */, F2DA29771C7749D600B0A8E3 /* NotificationInfo.swift in Sources */, F1A26CCF2738E7E400433E9F /* AssetListSelectableDateSectionController.swift in Sources */, diff --git a/NohanaImagePicker/AssetListSelectableDateSection.storyboard b/NohanaImagePicker/AssetListSelectableDateSection.storyboard index d3a2094..2db981a 100644 --- a/NohanaImagePicker/AssetListSelectableDateSection.storyboard +++ b/NohanaImagePicker/AssetListSelectableDateSection.storyboard @@ -1,9 +1,9 @@ - + - + @@ -73,8 +73,8 @@ - - + + @@ -135,7 +136,7 @@ - + diff --git a/NohanaImagePicker/AssetListSelectableDateSectionController.swift b/NohanaImagePicker/AssetListSelectableDateSectionController.swift index bb619ec..07fb4ad 100644 --- a/NohanaImagePicker/AssetListSelectableDateSectionController.swift +++ b/NohanaImagePicker/AssetListSelectableDateSectionController.swift @@ -16,11 +16,16 @@ import Foundation import Photos +import UIKit class AssetListSelectableDateSectionController: UICollectionViewController, UICollectionViewDelegateFlowLayout, ActivityIndicatable { - + + private enum Section: Int { + case photoAuthorizationLimited = 0 + } + private let nohanaImagePickerController: NohanaImagePickerController - let photoKitAssetList: PhotoKitAssetList + private var photoKitAssetList: PhotoKitAssetList var dateSectionList: [AssetDateSection] = [] var cellSize: CGSize { @@ -32,6 +37,25 @@ class AssetListSelectableDateSectionController: UICollectionViewController, UICo let cellWidth = (view.frame.width - cellMargin * (CGFloat(numberOfColumns) - 1)) / CGFloat(numberOfColumns) return CGSize(width: cellWidth, height: cellWidth) } + + private lazy var isHiddenPhotoAuthorizationLimitedCell: Bool = { + guard !nohanaImagePickerController.isHiddenPhotoAuthorizationLimitedView else { + return true + } + + let status: PHAuthorizationStatus + if #available(iOS 14, *) { + status = PHPhotoLibrary.authorizationStatus(for: .readWrite) + } else { + status = PHPhotoLibrary.authorizationStatus() + } + switch status { + case .limited: + return false + default: + return true + } + }() init?(coder: NSCoder, nohanaImagePickerController: NohanaImagePickerController, photoKitAssetList: PhotoKitAssetList) { self.nohanaImagePickerController = nohanaImagePickerController @@ -49,6 +73,8 @@ class AssetListSelectableDateSectionController: UICollectionViewController, UICo setUpToolbarItems() addPickPhotoKitAssetNotificationObservers() setUpActivityIndicator() + collectionView.register(UINib(nibName: "PhotoAuthorizationLimitedCell", bundle: self.nohanaImagePickerController.assetBundle), forCellWithReuseIdentifier: PhotoAuthorizationLimitedCell.defaultReusableId) + PHPhotoLibrary.shared().register(self) DispatchQueue.main.async { [weak self] in guard let self = self else { return } self.dateSectionList = AssetDateSectionCreater().createSections(assetList: self.photoKitAssetList.assetList, options: PhotoKitAssetList.fetchOptions(self.photoKitAssetList.mediaType, ascending: false)) @@ -87,21 +113,34 @@ class AssetListSelectableDateSectionController: UICollectionViewController, UICo if let activityIndicator = activityIndicator { updateVisibilityOfActivityIndicator(activityIndicator) } - - return dateSectionList.count + return dateSectionList.count + 1 } override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - return dateSectionList[section].assetResult.count + if Section(rawValue: section) == .photoAuthorizationLimited { + return 1 + } else { + return dateSectionList[section - 1].assetResult.count + } } // MARK: - UICollectionViewDelegate override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + if Section(rawValue: indexPath.section) == .photoAuthorizationLimited { + guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PhotoAuthorizationLimitedCell.defaultReusableId, for: indexPath) as? PhotoAuthorizationLimitedCell else { + fatalError("failed to dequeueReusableCellWithIdentifier(\"PhotoAuthorizationLimitedCell\")") + } + cell.delegate = self + let isHidden = isHiddenPhotoAuthorizationLimitedCell + cell.update(isHidden, nohanaImagePickerController: nohanaImagePickerController) + return cell + } + guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "AssetCell", for: indexPath) as? AssetCell else { fatalError("failed to dequeueReusableCellWithIdentifier(\"AssetCell\")") } - + let indexPath: IndexPath = .init(row: indexPath.row, section: indexPath.section - 1) let asset = PhotoKitAsset(asset: dateSectionList[indexPath.section].assetResult[indexPath.row]) cell.tag = indexPath.item cell.delegate = self @@ -126,15 +165,20 @@ class AssetListSelectableDateSectionController: UICollectionViewController, UICo override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { switch kind { case UICollectionView.elementKindSectionHeader: - let album = dateSectionList[indexPath.section] guard let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "AssetDateSectionHeader", for: indexPath) as? AssetDateSectionHeaderView else { fatalError("failed to create AssetDateSectionHeader") } + if Section(rawValue: indexPath.section) == .photoAuthorizationLimited { + return header + } + let sectionListIndex = indexPath.section - 1 + let album = dateSectionList[sectionListIndex] header.date = album.creationDate header.delegate = self - let assets = dateSectionList[indexPath.section].assetResult.map { PhotoKitAsset(asset: $0) } + let assets = dateSectionList[sectionListIndex].assetResult.map { PhotoKitAsset(asset: $0) } header.update(assets: assets, indexPath: indexPath, nohanaImagePickerController: nohanaImagePickerController) return header + default: fatalError("failed to create AssetDateSectionHeader") } @@ -143,9 +187,25 @@ class AssetListSelectableDateSectionController: UICollectionViewController, UICo // MARK: - UICollectionViewDelegateFlowLayout func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { - return cellSize + if Section(rawValue: indexPath.section) == .photoAuthorizationLimited { + if isHiddenPhotoAuthorizationLimitedCell { + return CGSize(width: collectionView.frame.width, height: 1) + } else { + return PhotoAuthorizationLimitedCell.cellSize(nohanaImagePickerController) + } + } else { + return cellSize + } } + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { + if Section(rawValue: section) == .photoAuthorizationLimited { + return .zero + } + return .init(width: .infinity, height: 44.0) + } + + // MARK: - ActivityIndicatable var activityIndicator: UIActivityIndicatorView? @@ -166,12 +226,18 @@ class AssetListSelectableDateSectionController: UICollectionViewController, UICo // MARK: - UICollectionViewDelegate override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { - nohanaImagePickerController.delegate?.nohanaImagePicker?(nohanaImagePickerController, didSelectPhotoKitAsset: dateSectionList[indexPath.section].assetResult[indexPath.row]) + + guard Section(rawValue: indexPath.section) != .photoAuthorizationLimited else { + return + } + + let sectionListIndex = indexPath.section - 1 + nohanaImagePickerController.delegate?.nohanaImagePicker?(nohanaImagePickerController, didSelectPhotoKitAsset: dateSectionList[sectionListIndex].assetResult[indexPath.row]) } @available(iOS 13.0, *) override func collectionView(_ collectionView: UICollectionView, contextMenuConfigurationForItemAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? { - let asset = PhotoKitAsset(asset: dateSectionList[indexPath.section].assetResult[indexPath.row]) + let asset = PhotoKitAsset(asset: dateSectionList[indexPath.section - 1].assetResult[indexPath.row]) if let cell = collectionView.cellForItem(at: indexPath) as? AssetCell { return UIContextMenuConfiguration(identifier: indexPath as NSCopying, previewProvider: { [weak self] in // Create a preview view controller and return it @@ -221,21 +287,23 @@ class AssetListSelectableDateSectionController: UICollectionViewController, UICo override func prepare(for segue: UIStoryboardSegue, sender: Any?) { guard let selectedIndexPath = collectionView?.indexPathsForSelectedItems?.first, - selectedIndexPath.section < dateSectionList.count else { + selectedIndexPath.section != 0, + selectedIndexPath.section - 1 < dateSectionList.count else { return } var assetListDetailCurrentRow = 0 - for section in 0..<(selectedIndexPath.section + 1) { - if selectedIndexPath.section == section { + for section in 0..<(selectedIndexPath.section) { + if selectedIndexPath.section == (section + 1) { assetListDetailCurrentRow += selectedIndexPath.row } else { assetListDetailCurrentRow += dateSectionList[section].assetResult.count } } + if assetListDetailCurrentRow >= photoKitAssetList.count { assetListDetailCurrentRow = photoKitAssetList.count - 1 } - + let assetListDetailViewController = segue.destination as! AssetDetailListViewController assetListDetailViewController.currentIndexPath = IndexPath(item: assetListDetailCurrentRow, section: 0) } @@ -261,7 +329,7 @@ extension AssetListSelectableDateSectionController: AssetCellDelegate { if #available(iOS 9.0, *) { let rowResetIndexPath = IndexPath(row: 0, section: indexPath.section) let header = collectionView.supplementaryView(forElementKind: UICollectionView.elementKindSectionHeader, at: rowResetIndexPath) as? AssetDateSectionHeaderView - let assets = dateSectionList[indexPath.section].assetResult.map { PhotoKitAsset(asset: $0) } + let assets = dateSectionList[indexPath.section - 1].assetResult.map { PhotoKitAsset(asset: $0) } header?.update(assets: assets, indexPath: indexPath, nohanaImagePickerController: nohanaImagePickerController) } else { UIView.animate(withDuration: 0) { [weak self] in @@ -275,3 +343,45 @@ extension AssetListSelectableDateSectionController: AssetCellDelegate { updateDoneBarButtonColor() } } + +// MARK: - PhotoAuthorizationLimitedCellDeletate + +extension AssetListSelectableDateSectionController: PhotoAuthorizationLimitedCellDeletate { + func didSelectAddPhotoButton(_ cell: PhotoAuthorizationLimitedCell) { + nohanaImagePickerController.delegate?.nohanaImagePickerDidTapAddPhotoButton?(nohanaImagePickerController) + } + + func didSelectAuthorizeAllPhotoButton(_ cell: PhotoAuthorizationLimitedCell) { + nohanaImagePickerController.delegate?.nohanaImagePickerDidTapAuthorizeAllPhotoButton?(nohanaImagePickerController) + } +} + +extension String { + func height(withConstrainedWidth width: CGFloat, font: UIFont = .systemFont(ofSize: 13.5)) -> CGFloat { + let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude) + let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil) + + return ceil(boundingBox.height) + } + + func width(withConstrainedHeight height: CGFloat, font: UIFont) -> CGFloat { + let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height) + let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil) + + return ceil(boundingBox.width) + } +} + +// MARK: - PHPhotoLibraryChangeObserver + +extension AssetListSelectableDateSectionController: PHPhotoLibraryChangeObserver { + func photoLibraryDidChange(_ changeInstance: PHChange) { + DispatchQueue.main.async { [weak self] in + guard let self = self else { return } + self.photoKitAssetList = PhotoKitAssetList(album: self.photoKitAssetList.assetList, mediaType: self.photoKitAssetList.mediaType, ascending: false) + self.dateSectionList = AssetDateSectionCreater().createSections(assetList: self.photoKitAssetList.assetList, options: PhotoKitAssetList.fetchOptions(self.photoKitAssetList.mediaType, ascending: false)) + self.isLoading = false + self.collectionView?.reloadData() + } + } +} diff --git a/NohanaImagePicker/NohanaImagePickerController.swift b/NohanaImagePicker/NohanaImagePickerController.swift index 4c98908..c8b5443 100644 --- a/NohanaImagePicker/NohanaImagePickerController.swift +++ b/NohanaImagePicker/NohanaImagePickerController.swift @@ -35,6 +35,8 @@ public enum MediaType: Int { @objc optional func nohanaImagePicker(_ picker: NohanaImagePickerController, assetListViewController: UICollectionViewController, cell: UICollectionViewCell, indexPath: IndexPath, photoKitAsset: PHAsset) -> UICollectionViewCell @objc optional func nohanaImagePicker(_ picker: NohanaImagePickerController, assetDetailListViewController: UICollectionViewController, cell: UICollectionViewCell, indexPath: IndexPath, photoKitAsset: PHAsset) -> UICollectionViewCell @objc optional func nohanaImagePicker(_ picker: NohanaImagePickerController, assetDetailListViewController: UICollectionViewController, didChangeAssetDetailPage indexPath: IndexPath, photoKitAsset: PHAsset) + @objc optional func nohanaImagePickerDidTapAddPhotoButton(_ picker: NohanaImagePickerController) + @objc optional func nohanaImagePickerDidTapAuthorizeAllPhotoButton(_ picker: NohanaImagePickerController) } open class NohanaImagePickerController: UIViewController { @@ -57,6 +59,7 @@ open class NohanaImagePickerController: UIViewController { .font: UIFont.systemFont(ofSize: 17, weight: .semibold) ] }() + open var isHiddenPhotoAuthorizationLimitedView: Bool = false lazy var assetBundle: Bundle = { let bundle = Bundle(for: type(of: self)) if let path = bundle.path(forResource: "NohanaImagePicker", ofType: "bundle") { diff --git a/NohanaImagePicker/PhotoAuthorizationLimitedCell.swift b/NohanaImagePicker/PhotoAuthorizationLimitedCell.swift new file mode 100644 index 0000000..288f2c7 --- /dev/null +++ b/NohanaImagePicker/PhotoAuthorizationLimitedCell.swift @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2022 nohana, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import UIKit + +protocol PhotoAuthorizationLimitedCellDeletate { + func didSelectAddPhotoButton(_ cell: PhotoAuthorizationLimitedCell) + func didSelectAuthorizeAllPhotoButton(_ cell: PhotoAuthorizationLimitedCell) +} + +class PhotoAuthorizationLimitedCell: UICollectionViewCell { + + static var defaultReusableId: String { + String(describing: self) + } + + var delegate: PhotoAuthorizationLimitedCellDeletate? + + @IBOutlet weak private var containerView: UIStackView! + @IBOutlet weak private var attentionLabel: UILabel! + @IBOutlet weak private var addPhotoButton: UIButton! { + didSet { + self.addPhotoButton.layer.cornerRadius = 6 + self.addPhotoButton.layer.borderColor = UIColor(red: 187/255, green: 187/255, blue: 187/255, alpha: 1).cgColor + self.addPhotoButton.layer.borderWidth = 1 + } + } + @IBOutlet weak private var authorizeAllPhotoButton: UIButton! { + didSet { + self.authorizeAllPhotoButton.layer.cornerRadius = 6 + self.authorizeAllPhotoButton.layer.borderColor = UIColor(red: 187/255, green: 187/255, blue: 187/255, alpha: 1).cgColor + self.authorizeAllPhotoButton.layer.borderWidth = 1 + } + } + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + @IBAction func tappedAddPhotoButton(_ sender: UIButton) { + delegate?.didSelectAddPhotoButton(self) + } + + @IBAction func tappedAuthorizeAllPhotoButton(_ sender: UIButton) { + delegate?.didSelectAuthorizeAllPhotoButton(self) + } + + func update(_ isHidden: Bool, nohanaImagePickerController: NohanaImagePickerController) { + + containerView.isHidden = isHidden + attentionLabel.text = NSLocalizedString( + "albumlist.menu.description", + tableName: "NohanaImagePicker", + bundle: nohanaImagePickerController.assetBundle, + comment: "" + ) + + addPhotoButton.setTitle( + NSLocalizedString( + "albumlist.menu.addPhoto.title", + tableName: "NohanaImagePicker", + bundle: nohanaImagePickerController.assetBundle, + comment: "" + ), + for: .normal + ) + + authorizeAllPhotoButton.setTitle( + NSLocalizedString( + "albumlist.menu.authorizeAllPhoto.title", + tableName: "NohanaImagePicker", + bundle: nohanaImagePickerController.assetBundle, + comment: "" + ), + for: .normal + ) + } + + func isHiddenCell(_ isHidden: Bool) { + containerView.isHidden = isHidden + } + + static func cellSize(_ nohanaImagePickerController: NohanaImagePickerController) -> CGSize { + let descriptionLabel = UILabel() + descriptionLabel.numberOfLines = 0 + descriptionLabel.font = .systemFont(ofSize: 13.5) + descriptionLabel.text = NSLocalizedString("albumlist.menu.description", tableName: "NohanaImagePicker", bundle: nohanaImagePickerController.assetBundle, comment: "") + let maxSize: CGSize = .init(width: UIScreen.main.bounds.width - 28, height: .infinity) + let height: CGFloat = descriptionLabel.sizeThatFits(maxSize).height + 44 * 2 + 10 + 16 * 3 + return .init(width: UIScreen.main.bounds.width, height: height) + } +} diff --git a/NohanaImagePicker/PhotoAuthorizationLimitedCell.xib b/NohanaImagePicker/PhotoAuthorizationLimitedCell.xib new file mode 100644 index 0000000..0068e33 --- /dev/null +++ b/NohanaImagePicker/PhotoAuthorizationLimitedCell.xib @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/NohanaImagePicker/RootViewController.swift b/NohanaImagePicker/RootViewController.swift index 790c6a0..9f17ae4 100644 --- a/NohanaImagePicker/RootViewController.swift +++ b/NohanaImagePicker/RootViewController.swift @@ -215,6 +215,14 @@ class RootViewController: UIViewController { } }) } + + @objc func didTapAddPhoto(_ notification: Notification) { + nohanaImagePickerController.delegate?.nohanaImagePickerDidTapAddPhotoButton?(nohanaImagePickerController) + } + + @objc func didTapAuthorizeAllPhoto(_ notification: Notification) { + nohanaImagePickerController.delegate?.nohanaImagePickerDidTapAuthorizeAllPhotoButton?(nohanaImagePickerController) + } // MARK: - IBAction @IBAction func didTapDone(_ sender: AnyObject) { diff --git a/NohanaImagePicker/de.lproj/NohanaImagePicker.strings b/NohanaImagePicker/de.lproj/NohanaImagePicker.strings index 8b8b529..b51aede 100644 --- a/NohanaImagePicker/de.lproj/NohanaImagePicker.strings +++ b/NohanaImagePicker/de.lproj/NohanaImagePicker.strings @@ -19,6 +19,10 @@ "albumlist.empty.description" = "Nimm Fotos mit der Kamera App auf."; "albumlist.empty.alert.button.ok" = "OK"; "albumlist.moment.title" = "Moment"; +"albumlist.menu.description" = "Derzeit sind nur \"ausgewählte Fotos\" erlaubt. \n +Wenn Sie auf dem Einstellungsbildschirm unter „Fotos“ unter „Alle Fotos“ ✓ eingeben, können Sie aus allen Fotos im Terminal auswählen."; +"albumlist.menu.addPhoto.title" = "Genehmigungsfoto hinzufügen"; +"albumlist.menu.authorizeAllPhoto.title" = "alle Fotos zulassen"; "toolbar.title.nolimit" = "Ausgewählte Fotos: %ld"; "toolbar.title.haslimit" = "Ausgewählte Fotos: %ld / %ld"; "action.title.select" = "Auswählen"; diff --git a/NohanaImagePicker/en.lproj/NohanaImagePicker.strings b/NohanaImagePicker/en.lproj/NohanaImagePicker.strings index 8b4dbe4..073ffb5 100644 --- a/NohanaImagePicker/en.lproj/NohanaImagePicker.strings +++ b/NohanaImagePicker/en.lproj/NohanaImagePicker.strings @@ -19,7 +19,12 @@ "albumlist.empty.description" = "Take some photos with Camera app."; "albumlist.empty.alert.button.ok" = "OK"; "albumlist.moment.title" = "Moment"; +"albumlist.menu.description" = "Currently only \"selected photos\" are allowed.\n +If you put ✓ in \"All photos\" in \"Photos\" on the setting screen, you will be able to select from all the photos in the terminal."; +"albumlist.menu.addPhoto.title" = "Add permission photo"; +"albumlist.menu.authorizeAllPhoto.title" = "Allow all photos"; "toolbar.title.nolimit" = "Selected Items: %ld"; "toolbar.title.haslimit" = "Selected Items: %ld / %ld"; "action.title.select" = "Select"; "action.title.deselect" = "Deselect"; + diff --git a/NohanaImagePicker/ja.lproj/NohanaImagePicker.strings b/NohanaImagePicker/ja.lproj/NohanaImagePicker.strings index 0595dde..88650d8 100644 --- a/NohanaImagePicker/ja.lproj/NohanaImagePicker.strings +++ b/NohanaImagePicker/ja.lproj/NohanaImagePicker.strings @@ -19,6 +19,10 @@ "albumlist.empty.description" = "カメラで写真を撮影しましょう"; "albumlist.empty.alert.button.ok" = "OK"; "albumlist.moment.title" = "日付から選択"; +"albumlist.menu.description" = "現在「選択した写真」のみ許可されています。\n +設定画面の「写真」で「すべての写真」に✓を入れると、端末内のすべての写真から選べるようになります。"; +"albumlist.menu.addPhoto.title" = "許可写真を追加する"; +"albumlist.menu.authorizeAllPhoto.title" = "すべての写真を許可する"; "toolbar.title.nolimit" = "%ld枚選択中"; "toolbar.title.haslimit" = "%ld枚選択中(最大%ld枚)"; "action.title.select" = "選択する"; diff --git a/NohanaImagePicker/ru.lproj/NohanaImagePicker.strings b/NohanaImagePicker/ru.lproj/NohanaImagePicker.strings index 1b6036d..fc03438 100644 --- a/NohanaImagePicker/ru.lproj/NohanaImagePicker.strings +++ b/NohanaImagePicker/ru.lproj/NohanaImagePicker.strings @@ -19,6 +19,10 @@ "albumlist.empty.description" = "Получить фото с камеры"; "albumlist.empty.alert.button.ok" = "ла́дно"; "albumlist.moment.title" = "Моменты"; +"albumlist.menu.description" = "В настоящее время разрешены только «избранные фотографии». \n +Если вы поместите ✓ в «Все фотографии» в «Фотографии» на экране настроек, вы сможете выбрать из всех фотографий в терминале."; +"albumlist.menu.addPhoto.title" = "добавить фото разрешения"; +"albumlist.menu.authorizeAllPhoto.title" = "разрешить все фото"; "toolbar.title.nolimit" = "Выбрано: %ld"; "toolbar.title.haslimit" = "Выбрано: %ld / %ld"; "action.title.select" = "Выбирать";