Skip to content

Commit

Permalink
Merge pull request #21360 from wordpress-mobile/task/phpicker-editor
Browse files Browse the repository at this point in the history
Integrate PHPickerViewController in Page Editor
  • Loading branch information
kean authored Aug 22, 2023
2 parents d9c1024 + 8d08f37 commit dd4c591
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@ class GutenbergMediaInserterHelper: NSObject {
callback(formattedMedia)
}

func insertFromDevice(_ selection: [Any], callback: @escaping MediaPickerDidPickMediaCallback) {
if let assets = selection as? [PHAsset] {
insertFromDevice(assets: assets, callback: callback)
} else if let providers = selection as? [NSItemProvider] {
insertItemProviders(providers, callback: callback)
} else {
callback(nil)
}
}

func insertFromDevice(assets: [PHAsset], callback: @escaping MediaPickerDidPickMediaCallback) {
guard (assets as [AsyncImage]).filter({ $0.isEdited }).isEmpty else {
insertFromMediaEditor(assets: assets, callback: callback)
Expand Down Expand Up @@ -93,6 +103,22 @@ class GutenbergMediaInserterHelper: NSObject {
}
}

private func insertItemProviders(_ providers: [NSItemProvider], callback: @escaping MediaPickerDidPickMediaCallback) {
let media: [MediaInfo] = providers.compactMap {
// WARNING: Media is a CoreData entity and has to be thread-confined
guard let media = insert(exportableAsset: $0, source: .deviceLibrary) else {
return nil
}
// Gutenberg fails to add an image if the preview `url` is `nil`. But
// it doesn't need to point anywhere. The placeholder gets displayed
// as soon as `MediaImportService` generated it (see `MediaState.thumbnailReady`).
// This way we, dramatically cut CPU and especially memory usage.
let previewURL = URL(fileURLWithPath: NSTemporaryDirectory() + "\(media.gutenbergUploadID)")
return MediaInfo(id: media.gutenbergUploadID, url: previewURL.absoluteString, type: media.mediaTypeString)
}
callback(media)
}

func insertFromDevice(url: URL, callback: @escaping MediaPickerDidPickMediaCallback) {
guard let media = insert(exportableAsset: url as NSURL, source: .otherApps) else {
callback([])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import Foundation
import CoreServices
import UIKit
import Photos
import PhotosUI
import WordPressShared
import WPMediaPicker
import Gutenberg
import UniformTypeIdentifiers

public typealias GutenbergMediaPickerHelperCallback = ([WPMediaAsset]?) -> Void
public typealias GutenbergMediaPickerHelperCallback = ([Any]?) -> Void

class GutenbergMediaPickerHelper: NSObject {

Expand Down Expand Up @@ -47,7 +48,33 @@ class GutenbergMediaPickerHelper: NSObject {
dataSourceType: MediaPickerDataSourceType = .device,
allowMultipleSelection: Bool,
callback: @escaping GutenbergMediaPickerHelperCallback) {
if dataSourceType == .device, FeatureFlag.nativePhotoPicker.enabled {
presentNativePicker(filter: filter, allowMultipleSelection: allowMultipleSelection, completion: callback)
} else {
presentLegacyPicker(filter: filter, dataSourceType: dataSourceType, allowMultipleSelection: allowMultipleSelection, callback: callback)
}
}

private func presentNativePicker(filter: WPMediaType, allowMultipleSelection: Bool, completion: @escaping GutenbergMediaPickerHelperCallback) {
didPickMediaCallback = completion

var configuration = PHPickerConfiguration(photoLibrary: .shared())
configuration.preferredAssetRepresentationMode = .compatible
if allowMultipleSelection {
configuration.selection = .ordered
configuration.selectionLimit = 0
}
configuration.filter = PHPickerFilter(filter)

let picker = PHPickerViewController(configuration: configuration)
picker.delegate = self
context.present(picker, animated: true)
}

private func presentLegacyPicker(filter: WPMediaType,
dataSourceType: MediaPickerDataSourceType = .device,
allowMultipleSelection: Bool,
callback: @escaping GutenbergMediaPickerHelperCallback) {
didPickMediaCallback = callback

let mediaPickerOptions = WPMediaPickerOptions.withDefaults(filter: filter, allowMultipleSelection: allowMultipleSelection)
Expand Down Expand Up @@ -215,6 +242,15 @@ extension GutenbergMediaPickerHelper: WPMediaPickerViewControllerDelegate {

}

extension GutenbergMediaPickerHelper: PHPickerViewControllerDelegate {
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
context.dismiss(animated: true)

didPickMediaCallback?(results.map(\.itemProvider))
didPickMediaCallback = nil
}
}

// MARK: - Media Editing
//
extension GutenbergMediaPickerHelper {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -660,16 +660,16 @@ extension GutenbergViewController: GutenbergBridgeDelegate {
}

func gutenbergDidRequestMediaFromDevicePicker(filter: WPMediaType, allowMultipleSelection: Bool, with callback: @escaping MediaPickerDidPickMediaCallback) {

mediaPickerHelper.presentMediaPickerFullScreen(animated: true,
filter: filter,
dataSourceType: .device,
allowMultipleSelection: allowMultipleSelection,
callback: {(assets) in
guard let phAssets = assets as? [PHAsset] else {
callback(nil)
return
}
self.mediaInserterHelper.insertFromDevice(assets: phAssets, callback: callback)
callback: { assets in
guard let assets, !assets.isEmpty else {
return callback(nil)
}
self.mediaInserterHelper.insertFromDevice(assets, callback: callback)
})
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,21 @@ extension PHPickerConfiguration {
return configuration
}
}

extension PHPickerFilter {
init?(_ type: WPMediaType) {
switch type {
case .image:
self = .images
case .video:
self = .videos
case .audio, .other:
assertionFailure("Unsupported media type: \(type)")
return nil
case .all:
return nil
default:
return nil
}
}
}

0 comments on commit dd4c591

Please sign in to comment.