Introduces limited iOS 13 support – wip
This commit is contained in:
parent
19a7cf0b27
commit
0ad99191d9
|
@ -29,7 +29,6 @@ import ObjectiveC
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
public struct Backport<Wrapped> {
|
public struct Backport<Wrapped> {
|
||||||
|
|
||||||
/// The underlying content this backport represents.
|
/// The underlying content this backport represents.
|
||||||
public let content: Wrapped
|
public let content: Wrapped
|
||||||
|
|
||||||
|
@ -38,7 +37,12 @@ public struct Backport<Wrapped> {
|
||||||
public init(_ content: Wrapped) {
|
public init(_ content: Wrapped) {
|
||||||
self.content = content
|
self.content = content
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public extension Backport where Wrapped == Any {
|
||||||
|
init(_ content: Wrapped) {
|
||||||
|
self.content = content
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension View {
|
public extension View {
|
||||||
|
|
|
@ -165,7 +165,6 @@ struct PasteButtonStyle: PrimitiveButtonStyle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// .opacity(configuration.isPressed ? 0.5 : 1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -14,6 +14,9 @@ internal extension View {
|
||||||
library: PHPhotoLibrary
|
library: PHPhotoLibrary
|
||||||
) -> some View {
|
) -> some View {
|
||||||
if #available(iOS 14, *) {
|
if #available(iOS 14, *) {
|
||||||
|
sheet(isPresented: isPresented) {
|
||||||
|
|
||||||
|
}
|
||||||
// var config = PHPickerConfiguration(photoLibrary: library)
|
// var config = PHPickerConfiguration(photoLibrary: library)
|
||||||
// config.preferredAssetRepresentationMode = preferredItemEncoding.mode
|
// config.preferredAssetRepresentationMode = preferredItemEncoding.mode
|
||||||
// config.selectionLimit = maxSelectionCount ?? 0
|
// config.selectionLimit = maxSelectionCount ?? 0
|
||||||
|
@ -29,13 +32,15 @@ internal extension View {
|
||||||
// configuration: config
|
// configuration: config
|
||||||
// )
|
// )
|
||||||
} else {
|
} else {
|
||||||
EmptyView()
|
backport.background {
|
||||||
|
LegacyPhotosViewController(isPresented: isPresented, selection: selection, filter: filter)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@available(iOS 14, *)
|
@available(iOS 14, *)
|
||||||
private struct PickerViewController: UIViewControllerRepresentable {
|
private struct PhotosViewController: UIViewControllerRepresentable {
|
||||||
@Binding var isPresented: Bool
|
@Binding var isPresented: Bool
|
||||||
@Binding var selection: [Backport<Any>.PhotosPickerItem]
|
@Binding var selection: [Backport<Any>.PhotosPickerItem]
|
||||||
|
|
||||||
|
@ -57,7 +62,7 @@ private struct PickerViewController: UIViewControllerRepresentable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@available(iOS 14, *)
|
@available(iOS 14, *)
|
||||||
private extension PickerViewController {
|
private extension PhotosViewController {
|
||||||
final class Representable: UIViewController, PHPickerViewControllerDelegate, UIAdaptivePresentationControllerDelegate {
|
final class Representable: UIViewController, PHPickerViewControllerDelegate, UIAdaptivePresentationControllerDelegate {
|
||||||
private weak var controller: PHPickerViewController?
|
private weak var controller: PHPickerViewController?
|
||||||
|
|
||||||
|
@ -105,17 +110,121 @@ private extension PickerViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func dismissController() {
|
private func dismissController() {
|
||||||
|
isPresented.wrappedValue = false
|
||||||
guard let controller else { return }
|
guard let controller else { return }
|
||||||
controller.presentedViewController?.dismiss(animated: true)
|
controller.presentedViewController?.dismiss(animated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
|
||||||
|
print(results)
|
||||||
|
dismissController()
|
||||||
|
}
|
||||||
|
|
||||||
func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
|
func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
|
||||||
dismissController()
|
dismissController()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
|
@available(iOS 13, *)
|
||||||
print(results)
|
private struct LegacyPhotosViewController: UIViewControllerRepresentable {
|
||||||
#warning("TBD")
|
@Binding var isPresented: Bool
|
||||||
|
@Binding var selection: [Backport<Any>.PhotosPickerItem]
|
||||||
|
|
||||||
|
let filter: Backport<Any>.PHPickerFilter?
|
||||||
|
|
||||||
|
func makeUIViewController(context: Context) -> Representable {
|
||||||
|
Representable(
|
||||||
|
isPresented: $isPresented,
|
||||||
|
selection: $selection,
|
||||||
|
filter: filter
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func updateUIViewController(_ controller: Representable, context: Context) {
|
||||||
|
controller.selection = $selection
|
||||||
|
controller.filter = filter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(iOS 13, *)
|
||||||
|
private extension LegacyPhotosViewController {
|
||||||
|
final class Representable: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UIAdaptivePresentationControllerDelegate {
|
||||||
|
private weak var controller: UIImagePickerController?
|
||||||
|
|
||||||
|
var isPresented: Binding<Bool> {
|
||||||
|
didSet {
|
||||||
|
updateControllerLifecycle(
|
||||||
|
from: oldValue.wrappedValue,
|
||||||
|
to: isPresented.wrappedValue
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var selection: Binding<[Backport<Any>.PhotosPickerItem]>
|
||||||
|
var filter: Backport<Any>.PHPickerFilter?
|
||||||
|
|
||||||
|
init(isPresented: Binding<Bool>, selection: Binding<[Backport<Any>.PhotosPickerItem]>, filter: Backport<Any>.PHPickerFilter?) {
|
||||||
|
self.isPresented = isPresented
|
||||||
|
self.selection = selection
|
||||||
|
self.filter = filter
|
||||||
|
|
||||||
|
super.init(nibName: nil, bundle: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
private func updateControllerLifecycle(from oldValue: Bool, to newValue: Bool) {
|
||||||
|
switch (oldValue, newValue) {
|
||||||
|
case (false, true):
|
||||||
|
presentController()
|
||||||
|
case (true, false):
|
||||||
|
dismissController()
|
||||||
|
case (true, true), (false, false):
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func presentController() {
|
||||||
|
let controller = UIImagePickerController()
|
||||||
|
|
||||||
|
if let filter {
|
||||||
|
controller.mediaTypes = filter.mediaTypes
|
||||||
|
} else if let types = UIImagePickerController.availableMediaTypes(for: .photoLibrary) {
|
||||||
|
controller.mediaTypes = types
|
||||||
|
}
|
||||||
|
|
||||||
|
controller.allowsEditing = false
|
||||||
|
controller.sourceType = .photoLibrary
|
||||||
|
controller.videoQuality = .typeHigh
|
||||||
|
controller.presentationController?.delegate = self
|
||||||
|
controller.delegate = self
|
||||||
|
|
||||||
|
present(controller, animated: true)
|
||||||
|
self.controller = controller
|
||||||
|
}
|
||||||
|
|
||||||
|
private func dismissController() {
|
||||||
|
isPresented.wrappedValue = false
|
||||||
|
guard let controller else { return }
|
||||||
|
controller.presentedViewController?.dismiss(animated: true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
|
||||||
|
print("TBD")
|
||||||
|
print(info)
|
||||||
|
dismissController()
|
||||||
|
}
|
||||||
|
|
||||||
|
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
|
||||||
|
dismissController()
|
||||||
|
}
|
||||||
|
|
||||||
|
func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
|
||||||
|
dismissController()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,22 +2,22 @@
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import PhotosUI
|
import PhotosUI
|
||||||
|
|
||||||
@available(iOS, introduced: 14, deprecated: 16)
|
@available(iOS, introduced: 13, deprecated: 16)
|
||||||
public extension Backport where Wrapped == Any {
|
public extension Backport<Any> {
|
||||||
// Available when SwiftUI is imported with PhotosUI
|
/// Available when SwiftUI is imported with PhotosUI
|
||||||
/// A control that allows a user to choose photos and/or videos from the photo library.
|
/// A control that allows a user to choose photos and/or videos from the photo library.
|
||||||
///
|
///
|
||||||
/// The user explicitly grants access only to items they choose, so photo library access authorization is not needed.
|
/// The user explicitly grants access only to items they choose, so photo library access authorization is not needed.
|
||||||
struct PhotosPicker<Label>: View where Label: View {
|
struct PhotosPicker<Label>: View where Label: View {
|
||||||
@State private var isPresented: Bool = false
|
@State private var isPresented: Bool = false
|
||||||
@Binding var selection: [Backport<Any>.PhotosPickerItem]
|
@Binding var selection: [Backport.PhotosPickerItem]
|
||||||
|
|
||||||
private let filter: Backport<Any>.PHPickerFilter?
|
let filter: Backport.PHPickerFilter?
|
||||||
private let maxSelection: Int?
|
let maxSelection: Int?
|
||||||
private let selectionBehavior: Backport<Any>.PhotosPickerSelectionBehavior
|
let selectionBehavior: Backport.PhotosPickerSelectionBehavior
|
||||||
private let encoding: Backport<Any>.PhotosPickerItem.EncodingDisambiguationPolicy
|
let encoding: Backport.PhotosPickerItem.EncodingDisambiguationPolicy
|
||||||
private let library: PHPh otoLibrary
|
let library: PHPhotoLibrary
|
||||||
private let label: Label
|
let label: Label
|
||||||
|
|
||||||
public var body: some View {
|
public var body: some View {
|
||||||
Button {
|
Button {
|
||||||
|
@ -38,24 +38,11 @@ public extension Backport where Wrapped == Any {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@available(iOS 14, *)
|
@available(iOS, introduced: 13, deprecated: 14)
|
||||||
public extension Backport.PhotosPicker where Wrapped == Any {
|
public extension Backport<Any>.PhotosPicker {
|
||||||
/// Creates a Photos picker that selects a `PhotosPickerItem` from a given photo library.
|
|
||||||
///
|
|
||||||
/// The user explicitly grants access only to items they choose, so photo library access authorization is not needed.
|
|
||||||
///
|
|
||||||
/// - Parameters:
|
|
||||||
/// - selection: The item being shown and selected in the Photos picker.
|
|
||||||
/// - filter: Types of items that can be shown. Default is `nil`. Setting it to `nil` means all supported types can be shown.
|
|
||||||
/// - preferredItemEncoding: The encoding disambiguation policy of the selected item. Default is `.automatic`. Setting it to `.automatic` means the best encoding determined by the system will be used.
|
|
||||||
/// - photoLibrary: The photo library to choose from.
|
|
||||||
/// - label: The view that describes the action of choosing an item from the photo library.
|
|
||||||
init(
|
init(
|
||||||
selection: Binding<Backport<Any>.PhotosPickerItem?>,
|
selection: Binding<Backport.PhotosPickerItem?>,
|
||||||
maxSelectionCount: Int? = nil,
|
matching filter: Backport.PHPickerFilter? = nil,
|
||||||
matching filter: Backport<Any>.PHPickerFilter? = nil,
|
|
||||||
preferredItemEncoding: Backport<Any>.PhotosPickerItem.EncodingDisambiguationPolicy = .automatic,
|
|
||||||
photoLibrary: PHPhotoLibrary = .shared(),
|
|
||||||
@ViewBuilder label: () -> Label
|
@ViewBuilder label: () -> Label
|
||||||
) {
|
) {
|
||||||
_selection = .init(
|
_selection = .init(
|
||||||
|
@ -67,32 +54,20 @@ public extension Backport.PhotosPicker where Wrapped == Any {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
self.filter = filter
|
self.filter = filter
|
||||||
self.maxSelection = maxSelectionCount
|
self.maxSelection = 1
|
||||||
self.selectionBehavior = .default
|
self.selectionBehavior = .default
|
||||||
self.encoding = preferredItemEncoding
|
self.encoding = .automatic
|
||||||
self.library = photoLibrary
|
self.library = .shared()
|
||||||
self.label = label()
|
self.label = label()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@available(iOS 14, *)
|
@available(iOS, introduced: 13, deprecated: 14)
|
||||||
public extension Backport.PhotosPicker where Wrapped == Any, Label == Text {
|
public extension Backport<Any>.PhotosPicker<Text> {
|
||||||
/// Creates a Photos picker with its label generated from a localized string key that selects a `PhotosPickerItem`.
|
|
||||||
///
|
|
||||||
/// The user explicitly grants access only to items they choose, so photo library access authorization is not needed.
|
|
||||||
///
|
|
||||||
/// - Parameters:
|
|
||||||
/// - titleKey: A localized string key that describes the purpose of showing the picker.
|
|
||||||
/// - selection: The item being shown and selected in the Photos picker.
|
|
||||||
/// - filter: Types of items that can be shown. Default is `nil`. Setting it to `nil` means all supported types can be shown.
|
|
||||||
/// - preferredItemEncoding: The encoding disambiguation policy of the selected item. Default is `.automatic`. Setting it to `.automatic` means the best encoding determined by the system will be used.
|
|
||||||
init(
|
init(
|
||||||
_ title: String,
|
_ titleKey: LocalizedStringKey,
|
||||||
selection: Binding<Backport<Any>.PhotosPickerItem?>,
|
selection: Binding<Backport.PhotosPickerItem?>,
|
||||||
maxSelectionCount: Int? = nil,
|
matching filter: Backport.PHPickerFilter? = nil
|
||||||
matching filter: Backport<Any>.PHPickerFilter? = nil,
|
|
||||||
preferredItemEncoding: Backport<Any>.PhotosPickerItem.EncodingDisambiguationPolicy = .automatic,
|
|
||||||
photoLibrary: PHPhotoLibrary = .shared()
|
|
||||||
) {
|
) {
|
||||||
_selection = .init(
|
_selection = .init(
|
||||||
get: {
|
get: {
|
||||||
|
@ -103,16 +78,267 @@ public extension Backport.PhotosPicker where Wrapped == Any, Label == Text {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
self.filter = filter
|
self.filter = filter
|
||||||
self.maxSelection = maxSelectionCount
|
self.maxSelection = 1
|
||||||
self.selectionBehavior = .default
|
self.selectionBehavior = .default
|
||||||
self.encoding = preferredItemEncoding
|
self.encoding = .automatic
|
||||||
self.library = photoLibrary
|
self.library = .shared()
|
||||||
label = Text(title)
|
self.label = Text(titleKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
init<S>(
|
||||||
|
_ title: S,
|
||||||
|
selection: Binding<Backport.PhotosPickerItem?>,
|
||||||
|
matching filter: Backport.PHPickerFilter? = nil
|
||||||
|
) where S: StringProtocol {
|
||||||
|
_selection = .init(
|
||||||
|
get: {
|
||||||
|
[selection.wrappedValue].compactMap { $0 }
|
||||||
|
},
|
||||||
|
set: { newValue in
|
||||||
|
selection.wrappedValue = newValue.first
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.filter = filter
|
||||||
|
self.maxSelection = 1
|
||||||
|
self.selectionBehavior = .default
|
||||||
|
self.encoding = .automatic
|
||||||
|
self.library = .shared()
|
||||||
|
self.label = Text(title)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@available(iOS 14, *)
|
||||||
|
public extension Backport<Any>.PhotosPicker {
|
||||||
|
/// Creates a Photos picker that selects a `PhotosPickerItem`.
|
||||||
|
///
|
||||||
|
/// The user explicitly grants access only to items they choose, so photo library access authorization is not needed.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - selection: The item being shown and selected in the Photos picker.
|
||||||
|
/// - filter: Types of items that can be shown. Default is `nil`. Setting it to `nil` means all supported types can be shown.
|
||||||
|
/// - preferredItemEncoding: The encoding disambiguation policy of the selected item. Default is `.automatic`. Setting it to `.automatic` means the best encoding determined by the system will be used.
|
||||||
|
/// - label: The view that describes the action of choosing an item from the photo library.
|
||||||
|
init(
|
||||||
|
selection: Binding<Backport.PhotosPickerItem?>,
|
||||||
|
matching filter: Backport.PHPickerFilter? = nil,
|
||||||
|
preferredItemEncoding: Backport.PhotosPickerItem.EncodingDisambiguationPolicy = .automatic,
|
||||||
|
@ViewBuilder label: () -> Label
|
||||||
|
) {
|
||||||
|
_selection = .init(
|
||||||
|
get: {
|
||||||
|
[selection.wrappedValue].compactMap { $0 }
|
||||||
|
},
|
||||||
|
set: { newValue in
|
||||||
|
selection.wrappedValue = newValue.first
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.filter = filter
|
||||||
|
self.maxSelection = 1
|
||||||
|
self.selectionBehavior = .default
|
||||||
|
self.encoding = preferredItemEncoding
|
||||||
|
self.library = .shared()
|
||||||
|
self.label = label()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a Photos picker that selects a `PhotosPickerItem` from a given photo library.
|
||||||
|
///
|
||||||
|
/// The user explicitly grants access only to items they choose, so photo library access authorization is not needed.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - selection: The item being shown and selected in the Photos picker.
|
||||||
|
/// - filter: Types of items that can be shown. Default is `nil`. Setting it to `nil` means all supported types can be shown.
|
||||||
|
/// - preferredItemEncoding: The encoding disambiguation policy of the selected item. Default is `.automatic`. Setting it to `.automatic` means the best encoding determined by the system will be used.
|
||||||
|
/// - photoLibrary: The photo library to choose from.
|
||||||
|
/// - label: The view that describes the action of choosing an item from the photo library.
|
||||||
|
init(
|
||||||
|
selection: Binding<Backport.PhotosPickerItem?>,
|
||||||
|
matching filter: Backport.PHPickerFilter? = nil,
|
||||||
|
preferredItemEncoding: Backport.PhotosPickerItem.EncodingDisambiguationPolicy = .automatic,
|
||||||
|
photoLibrary: PHPhotoLibrary,
|
||||||
|
@ViewBuilder label: () -> Label
|
||||||
|
) {
|
||||||
|
_selection = .init(
|
||||||
|
get: {
|
||||||
|
[selection.wrappedValue].compactMap { $0 }
|
||||||
|
},
|
||||||
|
set: { newValue in
|
||||||
|
selection.wrappedValue = newValue.first
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.filter = filter
|
||||||
|
self.maxSelection = 1
|
||||||
|
self.selectionBehavior = .default
|
||||||
|
self.encoding = preferredItemEncoding
|
||||||
|
self.library = photoLibrary
|
||||||
|
self.label = label()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Single selection
|
||||||
|
|
||||||
|
@available(iOS 14, *)
|
||||||
|
public extension Backport<Any>.PhotosPicker<Text> {
|
||||||
|
/// Creates a Photos picker with its label generated from a localized string key that selects a `PhotosPickerItem`.
|
||||||
|
///
|
||||||
|
/// The user explicitly grants access only to items they choose, so photo library access authorization is not needed.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - titleKey: A localized string key that describes the purpose of showing the picker.
|
||||||
|
/// - selection: The item being shown and selected in the Photos picker.
|
||||||
|
/// - filter: Types of items that can be shown. Default is `nil`. Setting it to `nil` means all supported types can be shown.
|
||||||
|
/// - preferredItemEncoding: The encoding disambiguation policy of the selected item. Default is `.automatic`. Setting it to `.automatic` means the best encoding determined by the system will be used.
|
||||||
|
init(
|
||||||
|
_ titleKey: LocalizedStringKey,
|
||||||
|
selection: Binding<Backport.PhotosPickerItem?>,
|
||||||
|
matching filter: Backport.PHPickerFilter? = nil,
|
||||||
|
preferredItemEncoding: Backport.PhotosPickerItem.EncodingDisambiguationPolicy = .automatic
|
||||||
|
) {
|
||||||
|
_selection = .init(
|
||||||
|
get: {
|
||||||
|
[selection.wrappedValue].compactMap { $0 }
|
||||||
|
},
|
||||||
|
set: { newValue in
|
||||||
|
selection.wrappedValue = newValue.first
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.filter = filter
|
||||||
|
self.maxSelection = 1
|
||||||
|
self.selectionBehavior = .default
|
||||||
|
self.encoding = preferredItemEncoding
|
||||||
|
self.library = .shared()
|
||||||
|
self.label = Text(titleKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a Photos picker with its label generated from a string that selects a `PhotosPickerItem`.
|
||||||
|
///
|
||||||
|
/// The user explicitly grants access only to items they choose, so photo library access authorization is not needed.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - title: A string that describes the purpose of showing the picker.
|
||||||
|
/// - selection: The item being shown and selected in the Photos picker.
|
||||||
|
/// - filter: Types of items that can be shown. Default is `nil`. Setting it to `nil` means all supported types can be shown.
|
||||||
|
/// - preferredItemEncoding: The encoding disambiguation policy of the selected item. Default is `.automatic`. Setting it to `.automatic` means the best encoding determined by the system will be used.
|
||||||
|
init<S>(
|
||||||
|
_ title: S,
|
||||||
|
selection: Binding<Backport.PhotosPickerItem?>,
|
||||||
|
matching filter: Backport.PHPickerFilter? = nil,
|
||||||
|
preferredItemEncoding: Backport.PhotosPickerItem.EncodingDisambiguationPolicy = .automatic
|
||||||
|
) where S: StringProtocol {
|
||||||
|
_selection = .init(
|
||||||
|
get: {
|
||||||
|
[selection.wrappedValue].compactMap { $0 }
|
||||||
|
},
|
||||||
|
set: { newValue in
|
||||||
|
selection.wrappedValue = newValue.first
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.filter = filter
|
||||||
|
self.maxSelection = 1
|
||||||
|
self.selectionBehavior = .default
|
||||||
|
self.encoding = preferredItemEncoding
|
||||||
|
self.library = .shared()
|
||||||
|
self.label = Text(title)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a Photos picker with its label generated from a localized string key that selects a `PhotosPickerItem` from a given photo library.
|
||||||
|
///
|
||||||
|
/// The user explicitly grants access only to items they choose, so photo library access authorization is not needed.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - titleKey: A localized string key that describes the purpose of showing the picker.
|
||||||
|
/// - selection: The item being shown and selected in the Photos picker.
|
||||||
|
/// - filter: Types of items that can be shown. Default is `nil`. Setting it to `nil` means all supported types can be shown.
|
||||||
|
/// - preferredItemEncoding: The encoding disambiguation policy of the selected item. Default is `.automatic`. Setting it to `.automatic` means the best encoding determined by the system will be used.
|
||||||
|
/// - photoLibrary: The photo library to choose from.
|
||||||
|
init(
|
||||||
|
_ titleKey: LocalizedStringKey,
|
||||||
|
selection: Binding<Backport.PhotosPickerItem?>,
|
||||||
|
matching filter: Backport.PHPickerFilter? = nil,
|
||||||
|
preferredItemEncoding: Backport.PhotosPickerItem.EncodingDisambiguationPolicy = .automatic,
|
||||||
|
photoLibrary: PHPhotoLibrary
|
||||||
|
) {
|
||||||
|
_selection = .init(
|
||||||
|
get: {
|
||||||
|
[selection.wrappedValue].compactMap { $0 }
|
||||||
|
},
|
||||||
|
set: { newValue in
|
||||||
|
selection.wrappedValue = newValue.first
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.filter = filter
|
||||||
|
self.maxSelection = 1
|
||||||
|
self.selectionBehavior = .default
|
||||||
|
self.encoding = preferredItemEncoding
|
||||||
|
self.library = photoLibrary
|
||||||
|
self.label = Text(titleKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a Photos picker with its label generated from a string that selects a `PhotosPickerItem` from a given photo library.
|
||||||
|
///
|
||||||
|
/// The user explicitly grants access only to items they choose, so photo library access authorization is not needed.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - title: A string that describes the purpose of showing the picker.
|
||||||
|
/// - selection: The item being shown and selected in the Photos picker.
|
||||||
|
/// - filter: Types of items that can be shown. Default is `nil`. Setting it to `nil` means all supported types can be shown.
|
||||||
|
/// - preferredItemEncoding: The encoding disambiguation policy of the selected item. Default is `.automatic`. Setting it to `.automatic` means the best encoding determined by the system will be used.
|
||||||
|
/// - photoLibrary: The photo library to choose from.
|
||||||
|
init<S>(
|
||||||
|
_ title: S,
|
||||||
|
selection: Binding<Backport.PhotosPickerItem?>,
|
||||||
|
matching filter: Backport.PHPickerFilter? = nil,
|
||||||
|
preferredItemEncoding: Backport.PhotosPickerItem.EncodingDisambiguationPolicy = .automatic,
|
||||||
|
photoLibrary: PHPhotoLibrary
|
||||||
|
) where S: StringProtocol {
|
||||||
|
_selection = .init(
|
||||||
|
get: {
|
||||||
|
[selection.wrappedValue].compactMap { $0 }
|
||||||
|
},
|
||||||
|
set: { newValue in
|
||||||
|
selection.wrappedValue = newValue.first
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.filter = filter
|
||||||
|
self.maxSelection = 1
|
||||||
|
self.selectionBehavior = .default
|
||||||
|
self.encoding = preferredItemEncoding
|
||||||
|
self.library = photoLibrary
|
||||||
|
self.label = Text(title)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Multiple selection
|
||||||
|
|
||||||
@available(iOS 15, *)
|
@available(iOS 15, *)
|
||||||
public extension Backport.PhotosPicker where Wrapped == Any {
|
public extension Backport<Any>.PhotosPicker {
|
||||||
|
/// Creates a Photos picker that selects a collection of `PhotosPickerItem`.
|
||||||
|
///
|
||||||
|
/// The user explicitly grants access only to items they choose, so photo library access authorization is not needed.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - selection: All items being shown and selected in the Photos picker.
|
||||||
|
/// - maxSelectionCount: The maximum number of items that can be selected. Default is `nil`. Setting it to `nil` means maximum supported by the system.
|
||||||
|
/// - selectionBehavior: The selection behavior of the Photos picker. Default is `.default`.
|
||||||
|
/// - filter: Types of items that can be shown. Default is `nil`. Setting it to `nil` means all supported types can be shown.
|
||||||
|
/// - preferredItemEncoding: The encoding disambiguation policy of selected items. Default is `.automatic`. Setting it to `.automatic` means the best encoding determined by the system will be used.
|
||||||
|
/// - label: The view that describes the action of choosing items from the photo library.
|
||||||
|
init(
|
||||||
|
selection: Binding<[Backport.PhotosPickerItem]>,
|
||||||
|
maxSelectionCount: Int? = nil,
|
||||||
|
selectionBehavior: Backport.PhotosPickerSelectionBehavior = .default,
|
||||||
|
matching filter: Backport.PHPickerFilter? = nil,
|
||||||
|
preferredItemEncoding: Backport.PhotosPickerItem.EncodingDisambiguationPolicy = .automatic,
|
||||||
|
@ViewBuilder label: () -> Label
|
||||||
|
) {
|
||||||
|
_selection = selection
|
||||||
|
self.filter = filter
|
||||||
|
self.maxSelection = maxSelectionCount
|
||||||
|
self.selectionBehavior = selectionBehavior
|
||||||
|
self.encoding = preferredItemEncoding
|
||||||
|
self.library = .shared()
|
||||||
|
self.label = label()
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a Photos picker that selects a collection of `PhotosPickerItem` from a given photo library.
|
/// Creates a Photos picker that selects a collection of `PhotosPickerItem` from a given photo library.
|
||||||
///
|
///
|
||||||
/// The user explicitly grants access only to items they choose, so photo library access authorization is not needed.
|
/// The user explicitly grants access only to items they choose, so photo library access authorization is not needed.
|
||||||
|
@ -126,12 +352,12 @@ public extension Backport.PhotosPicker where Wrapped == Any {
|
||||||
/// - photoLibrary: The photo library to choose from.
|
/// - photoLibrary: The photo library to choose from.
|
||||||
/// - label: The view that describes the action of choosing items from the photo library.
|
/// - label: The view that describes the action of choosing items from the photo library.
|
||||||
init(
|
init(
|
||||||
selection: Binding<[Backport<Any>.PhotosPickerItem]>,
|
selection: Binding<[Backport.PhotosPickerItem]>,
|
||||||
maxSelectionCount: Int? = nil,
|
maxSelectionCount: Int? = nil,
|
||||||
selectionBehavior: Backport<Any>.PhotosPickerSelectionBehavior = .default,
|
selectionBehavior: Backport.PhotosPickerSelectionBehavior = .default,
|
||||||
matching filter: Backport<Any>.PHPickerFilter? = nil,
|
matching filter: Backport.PHPickerFilter? = nil,
|
||||||
preferredItemEncoding: Backport<Any>.PhotosPickerItem.EncodingDisambiguationPolicy = .automatic,
|
preferredItemEncoding: Backport.PhotosPickerItem.EncodingDisambiguationPolicy = .automatic,
|
||||||
photoLibrary: PHPhotoLibrary = .shared(),
|
photoLibrary: PHPhotoLibrary,
|
||||||
@ViewBuilder label: () -> Label
|
@ViewBuilder label: () -> Label
|
||||||
) {
|
) {
|
||||||
_selection = selection
|
_selection = selection
|
||||||
|
@ -144,45 +370,94 @@ public extension Backport.PhotosPicker where Wrapped == Any {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@available(iOS 14, *)
|
@available(iOS 15, *)
|
||||||
public extension Backport.PhotosPicker where Wrapped == Any, Label == Text {
|
public extension Backport<Any>.PhotosPicker<Text> {
|
||||||
/// Creates a Photos picker with its label generated from a string that selects a `PhotosPickerItem` from a given photo library.
|
/// Creates a Photos picker with its label generated from a localized string key that selects a collection of `PhotosPickerItem`.
|
||||||
|
///
|
||||||
|
/// The user explicitly grants access only to items they choose, so photo library access authorization is not needed.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - titleKey: A localized string key that describes the purpose of showing the picker.
|
||||||
|
/// - selection: All items being shown and selected in the Photos picker.
|
||||||
|
/// - maxSelectionCount: The maximum number of items that can be selected. Default is `nil`. Setting it to `nil` means maximum supported by the system.
|
||||||
|
/// - selectionBehavior: The selection behavior of the Photos picker. Default is `.default`.
|
||||||
|
/// - filter: Types of items that can be shown. Default is `nil`. Setting it to `nil` means all supported types can be shown.
|
||||||
|
/// - preferredItemEncoding: The encoding disambiguation policy of selected items. Default is `.automatic`. Setting it to `.automatic` means the best encoding determined by the system will be used.
|
||||||
|
init(
|
||||||
|
_ titleKey: LocalizedStringKey,
|
||||||
|
selection: Binding<[Backport.PhotosPickerItem]>,
|
||||||
|
maxSelectionCount: Int? = nil,
|
||||||
|
selectionBehavior: Backport.PhotosPickerSelectionBehavior = .default,
|
||||||
|
matching filter: Backport.PHPickerFilter? = nil,
|
||||||
|
preferredItemEncoding: Backport.PhotosPickerItem.EncodingDisambiguationPolicy = .automatic
|
||||||
|
) {
|
||||||
|
_selection = selection
|
||||||
|
self.filter = filter
|
||||||
|
self.maxSelection = maxSelectionCount
|
||||||
|
self.selectionBehavior = selectionBehavior
|
||||||
|
self.encoding = preferredItemEncoding
|
||||||
|
self.library = .shared()
|
||||||
|
self.label = Text(titleKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a Photos picker with its label generated from a string that selects a collection of `PhotosPickerItem`.
|
||||||
///
|
///
|
||||||
/// The user explicitly grants access only to items they choose, so photo library access authorization is not needed.
|
/// The user explicitly grants access only to items they choose, so photo library access authorization is not needed.
|
||||||
///
|
///
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - title: A string that describes the purpose of showing the picker.
|
/// - title: A string that describes the purpose of showing the picker.
|
||||||
/// - selection: The item being shown and selected in the Photos picker.
|
/// - selection: All items being shown and selected in the Photos picker.
|
||||||
|
/// - maxSelectionCount: The maximum number of items that can be selected. Default is `nil`. Setting it to `nil` means maximum supported by the system.
|
||||||
|
/// - selectionBehavior: The selection behavior of the Photos picker. Default is `.default`.
|
||||||
/// - filter: Types of items that can be shown. Default is `nil`. Setting it to `nil` means all supported types can be shown.
|
/// - filter: Types of items that can be shown. Default is `nil`. Setting it to `nil` means all supported types can be shown.
|
||||||
/// - preferredItemEncoding: The encoding disambiguation policy of the selected item. Default is `.automatic`. Setting it to `.automatic` means the best encoding determined by the system will be used.
|
/// - preferredItemEncoding: The encoding disambiguation policy of selected items. Default is `.automatic`. Setting it to `.automatic` means the best encoding determined by the system will be used.
|
||||||
/// - photoLibrary: The photo library to choose from.
|
|
||||||
init<S>(
|
init<S>(
|
||||||
_ title: S,
|
_ title: S,
|
||||||
selection: Binding<Backport<Any>.PhotosPickerItem?>,
|
selection: Binding<[Backport.PhotosPickerItem]>,
|
||||||
maxSelectionCount: Int? = nil,
|
maxSelectionCount: Int? = nil,
|
||||||
matching filter: Backport<Any>.PHPickerFilter? = nil,
|
selectionBehavior: Backport.PhotosPickerSelectionBehavior = .default,
|
||||||
preferredItemEncoding: Backport<Any>.PhotosPickerItem.EncodingDisambiguationPolicy = .automatic,
|
matching filter: Backport.PHPickerFilter? = nil,
|
||||||
photoLibrary: PHPhotoLibrary = .shared()
|
preferredItemEncoding: Backport.PhotosPickerItem.EncodingDisambiguationPolicy = .automatic
|
||||||
) where S: StringProtocol {
|
) where S: StringProtocol {
|
||||||
_selection = .init(
|
_selection = selection
|
||||||
get: {
|
|
||||||
[selection.wrappedValue].compactMap { $0 }
|
|
||||||
},
|
|
||||||
set: { newValue in
|
|
||||||
selection.wrappedValue = newValue.first
|
|
||||||
}
|
|
||||||
)
|
|
||||||
self.filter = filter
|
self.filter = filter
|
||||||
self.maxSelection = maxSelectionCount
|
self.maxSelection = maxSelectionCount
|
||||||
self.selectionBehavior = .default
|
self.selectionBehavior = selectionBehavior
|
||||||
self.encoding = preferredItemEncoding
|
self.encoding = preferredItemEncoding
|
||||||
self.library = photoLibrary
|
self.library = .shared()
|
||||||
self.label = Text(title)
|
self.label = Text(title)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@available(iOS 15, *)
|
/// Creates a Photos picker with its label generated from a localized string key that selects a collection of `PhotosPickerItem` from a given photo library.
|
||||||
public extension Backport.PhotosPicker where Wrapped == Any, Label == Text {
|
///
|
||||||
|
/// The user explicitly grants access only to items they choose, so photo library access authorization is not needed.
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - titleKey: A localized string key that describes the purpose of showing the picker.
|
||||||
|
/// - selection: All items being shown and selected in the Photos picker.
|
||||||
|
/// - maxSelectionCount: The maximum number of items that can be selected. Default is `nil`. Setting it to `nil` means maximum supported by the system.
|
||||||
|
/// - selectionBehavior: The selection behavior of the Photos picker. Default is `.default`.
|
||||||
|
/// - filter: Types of items that can be shown. Default is `nil`. Setting it to `nil` means all supported types can be shown.
|
||||||
|
/// - preferredItemEncoding: The encoding disambiguation policy of selected items. Default is `.automatic`. Setting it to `.automatic` means the best encoding determined by the system will be used.
|
||||||
|
/// - photoLibrary: The photo library to choose from.
|
||||||
|
init(
|
||||||
|
_ titleKey: LocalizedStringKey,
|
||||||
|
selection: Binding<[Backport.PhotosPickerItem]>,
|
||||||
|
maxSelectionCount: Int? = nil,
|
||||||
|
selectionBehavior: Backport.PhotosPickerSelectionBehavior = .default,
|
||||||
|
matching filter: Backport.PHPickerFilter? = nil,
|
||||||
|
preferredItemEncoding: Backport.PhotosPickerItem.EncodingDisambiguationPolicy = .automatic,
|
||||||
|
photoLibrary: PHPhotoLibrary
|
||||||
|
) {
|
||||||
|
_selection = selection
|
||||||
|
self.filter = filter
|
||||||
|
self.maxSelection = maxSelectionCount
|
||||||
|
self.selectionBehavior = selectionBehavior
|
||||||
|
self.encoding = preferredItemEncoding
|
||||||
|
self.library = photoLibrary
|
||||||
|
self.label = Text(titleKey)
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a Photos picker with its label generated from a string that selects a collection of `PhotosPickerItem` from a given photo library.
|
/// Creates a Photos picker with its label generated from a string that selects a collection of `PhotosPickerItem` from a given photo library.
|
||||||
///
|
///
|
||||||
/// The user explicitly grants access only to items they choose, so photo library access authorization is not needed.
|
/// The user explicitly grants access only to items they choose, so photo library access authorization is not needed.
|
||||||
|
@ -197,12 +472,12 @@ public extension Backport.PhotosPicker where Wrapped == Any, Label == Text {
|
||||||
/// - photoLibrary: The photo library to choose from.
|
/// - photoLibrary: The photo library to choose from.
|
||||||
init<S>(
|
init<S>(
|
||||||
_ title: S,
|
_ title: S,
|
||||||
selection: Binding<[Backport<Any>.PhotosPickerItem]>,
|
selection: Binding<[Backport.PhotosPickerItem]>,
|
||||||
maxSelectionCount: Int? = nil,
|
maxSelectionCount: Int? = nil,
|
||||||
selectionBehavior: Backport<Any>.PhotosPickerSelectionBehavior = .default,
|
selectionBehavior: Backport.PhotosPickerSelectionBehavior = .default,
|
||||||
matching filter: Backport<Any>.PHPickerFilter? = nil,
|
matching filter: Backport.PHPickerFilter? = nil,
|
||||||
preferredItemEncoding: Backport<Any>.PhotosPickerItem.EncodingDisambiguationPolicy = .automatic,
|
preferredItemEncoding: Backport.PhotosPickerItem.EncodingDisambiguationPolicy = .automatic,
|
||||||
photoLibrary: PHPhotoLibrary = .shared()
|
photoLibrary: PHPhotoLibrary
|
||||||
) where S: StringProtocol {
|
) where S: StringProtocol {
|
||||||
_selection = selection
|
_selection = selection
|
||||||
self.filter = filter
|
self.filter = filter
|
||||||
|
|
|
@ -1,79 +1,112 @@
|
||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
import PhotosUI
|
import PhotosUI
|
||||||
|
import CoreServices
|
||||||
|
|
||||||
@available(iOS, introduced: 13, deprecated: 16)
|
@available(iOS, introduced: 13, deprecated: 16)
|
||||||
public extension Backport where Wrapped == Any {
|
public extension Backport where Wrapped == Any {
|
||||||
/// A filter that restricts which types of assets to show
|
/// A filter that restricts which types of assets to show
|
||||||
struct PHPickerFilter: Equatable, Hashable {
|
struct PHPickerFilter: Equatable, Hashable {
|
||||||
let predicate: NSPredicate
|
internal let predicate: NSPredicate
|
||||||
|
// this enables us to support iOS 13 for images vs videos
|
||||||
|
internal let mediaTypes: [String]
|
||||||
|
|
||||||
/// The filter for images.
|
internal init(mediaTypes: [String]) {
|
||||||
public static var images: Self {
|
self.predicate = .init(value: true)
|
||||||
.init(predicate: NSPredicate(format: "(mediaSubtypes & %d) != 0", argumentArray: [PHAssetMediaType.image]))
|
self.mediaTypes = mediaTypes
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The filter for videos.
|
internal init(predicate: NSPredicate) {
|
||||||
public static var videos: Self {
|
self.predicate = predicate
|
||||||
.init(predicate: NSPredicate(format: "(mediaSubtypes & %d) != 0", argumentArray: [PHAssetMediaType.video]))
|
self.mediaTypes = []
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The filter for live photos.
|
@available(iOS 13, *)
|
||||||
public static var livePhotos: Self {
|
public extension Backport<Any>.PHPickerFilter {
|
||||||
.init(predicate: NSPredicate(format: "(mediaSubtypes & %d) != 0", argumentArray: [PHAssetMediaSubtype.photoLive]))
|
/// The filter for images.
|
||||||
|
static var images: Self {
|
||||||
|
if #available(iOS 14, *) {
|
||||||
|
return .init(predicate: NSPredicate(format: "(mediaSubtypes & %d) != 0", argumentArray: [PHAssetMediaType.image]))
|
||||||
|
} else {
|
||||||
|
return .init(mediaTypes: [String(kUTTypeImage)])
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The filter for Depth Effect photos.
|
/// The filter for videos.
|
||||||
public static var depthEffectPhotos: Self {
|
static var videos: Self {
|
||||||
.init(predicate: NSPredicate(format: "(mediaSubtypes & %d) != 0", argumentArray: [PHAssetMediaSubtype.photoDepthEffect]))
|
if #available(iOS 14, *) {
|
||||||
|
return .init(predicate: NSPredicate(format: "(mediaSubtypes & %d) != 0", argumentArray: [PHAssetMediaType.video]))
|
||||||
|
} else {
|
||||||
|
return .init(mediaTypes: [String(kUTTypeMovie)])
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The filter for panorama photos.
|
/// The filter for live photos.
|
||||||
public static var panoramas: Self {
|
static var livePhotos: Self {
|
||||||
.init(predicate: NSPredicate(format: "(mediaSubtypes & %d) != 0", argumentArray: [PHAssetMediaSubtype.photoPanorama]))
|
if #available(iOS 14, *) {
|
||||||
|
return .init(predicate: NSPredicate(format: "(mediaSubtypes & %d) != 0", argumentArray: [PHAssetMediaSubtype.photoLive]))
|
||||||
|
} else {
|
||||||
|
return .init(mediaTypes: [String(kUTTypeMovie), String(kUTTypeLivePhoto)])
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The filter for screenshots.
|
@available(iOS 14, *)
|
||||||
public static var screenshots: Self {
|
public extension Backport<Any>.PHPickerFilter {
|
||||||
.init(predicate: NSPredicate(format: "(mediaSubtypes & %d) != 0", argumentArray: [PHAssetMediaSubtype.photoScreenshot]))
|
/// The filter for Depth Effect photos.
|
||||||
}
|
static var depthEffectPhotos: Self {
|
||||||
|
.init(predicate: NSPredicate(format: "(mediaSubtypes & %d) != 0", argumentArray: [PHAssetMediaSubtype.photoDepthEffect]))
|
||||||
|
}
|
||||||
|
|
||||||
/// The filter for Slow-Mo videos.
|
/// The filter for panorama photos.
|
||||||
public static var slomoVideos: Self {
|
static var panoramas: Self {
|
||||||
.init(predicate: NSPredicate(format: "(mediaSubtypes & %d) != 0", argumentArray: [PHAssetMediaSubtype.videoHighFrameRate]))
|
.init(predicate: NSPredicate(format: "(mediaSubtypes & %d) != 0", argumentArray: [PHAssetMediaSubtype.photoPanorama]))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The filter for time-lapse videos.
|
/// The filter for screenshots.
|
||||||
public static var timelapseVideos: Self {
|
static var screenshots: Self {
|
||||||
.init(predicate: NSPredicate(format: "(mediaSubtypes & %d) != 0", argumentArray: [PHAssetMediaSubtype.videoTimelapse]))
|
.init(predicate: NSPredicate(format: "(mediaSubtypes & %d) != 0", argumentArray: [PHAssetMediaSubtype.photoScreenshot]))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The filter for Cinematic videos.
|
/// The filter for Slow-Mo videos.
|
||||||
@available(iOS 15.0, *)
|
static var slomoVideos: Self {
|
||||||
public static var cinematicVideos: Self {
|
.init(predicate: NSPredicate(format: "(mediaSubtypes & %d) != 0", argumentArray: [PHAssetMediaSubtype.videoHighFrameRate]))
|
||||||
.init(predicate: NSPredicate(format: "(mediaSubtypes & %d) != 0", argumentArray: [PHAssetMediaSubtype.videoCinematic]))
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a new filter based on the asset playback style.
|
/// The filter for time-lapse videos.
|
||||||
#warning("NEEDS TESTING!")
|
static var timelapseVideos: Self {
|
||||||
public static func playbackStyle(_ playbackStyle: PHAsset.PlaybackStyle) -> Self {
|
.init(predicate: NSPredicate(format: "(mediaSubtypes & %d) != 0", argumentArray: [PHAssetMediaSubtype.videoTimelapse]))
|
||||||
.init(predicate: NSPredicate(format: "(playbackStyle & %d) != 0", argumentArray: [playbackStyle.rawValue]))
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a new filter formed by OR-ing the filters in a given array.
|
/// Returns a new filter based on the asset playback style.
|
||||||
public static func any(of subfilters: [Self]) -> Self {
|
#warning("NEEDS TESTING!")
|
||||||
.init(predicate: NSCompoundPredicate(orPredicateWithSubpredicates: subfilters.map { $0.predicate }))
|
static func playbackStyle(_ playbackStyle: PHAsset.PlaybackStyle) -> Self {
|
||||||
}
|
.init(predicate: NSPredicate(format: "(playbackStyle & %d) != 0", argumentArray: [playbackStyle.rawValue]))
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a new filter formed by AND-ing the filters in a given array.
|
/// Returns a new filter formed by OR-ing the filters in a given array.
|
||||||
public static func all(of subfilters: [Self]) -> Self {
|
static func any(of subfilters: [Self]) -> Self {
|
||||||
.init(predicate: NSCompoundPredicate(andPredicateWithSubpredicates: subfilters.map { $0.predicate }))
|
.init(predicate: NSCompoundPredicate(orPredicateWithSubpredicates: subfilters.map { $0.predicate }))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a new filter formed by negating the given filter.
|
/// Returns a new filter formed by AND-ing the filters in a given array.
|
||||||
public static func not(_ filter: Self) -> Self {
|
static func all(of subfilters: [Self]) -> Self {
|
||||||
.init(predicate: NSCompoundPredicate(notPredicateWithSubpredicate: filter.predicate))
|
.init(predicate: NSCompoundPredicate(andPredicateWithSubpredicates: subfilters.map { $0.predicate }))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a new filter formed by negating the given filter.
|
||||||
|
static func not(_ filter: Self) -> Self {
|
||||||
|
.init(predicate: NSCompoundPredicate(notPredicateWithSubpredicate: filter.predicate))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(iOS 15.0, *)
|
||||||
|
public extension Backport<Any>.PHPickerFilter {
|
||||||
|
/// The filter for Cinematic videos.
|
||||||
|
static var cinematicVideos: Self {
|
||||||
|
.init(predicate: NSPredicate(format: "(mediaSubtypes & %d) != 0", argumentArray: [PHAssetMediaSubtype.videoCinematic]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue