Skip to content
This repository has been archived by the owner on Apr 1, 2023. It is now read-only.

Commit

Permalink
add customExtensions picking capacity for iOS
Browse files Browse the repository at this point in the history
  • Loading branch information
GabrielNSD committed Oct 6, 2022
1 parent 34fc588 commit 1fb4708
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 8 deletions.
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,12 @@ Open the file picker that allows the user to select one or more files.

#### PickFilesOptions

| Prop | Type | Description |
| -------------- | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`types`** | <code>string[]</code> | List of accepted file types. Look at [IANA Media Types](https://www.iana.org/assignments/media-types/media-types.xhtml) for a complete list of standard media types. This option cannot be used with `multiple: true` on Android. Example: `['image/png', 'application/pdf']` |
| **`multiple`** | <code>boolean</code> | Whether multiple files may be selected. Default: `false` |
| **`readData`** | <code>boolean</code> | Whether to read the file data. Default: `true` |
| Prop | Type | Description |
| ---------------------- | --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`types`** | <code>string[]</code> | List of accepted file types. Look at [IANA Media Types](https://www.iana.org/assignments/media-types/media-types.xhtml) for a complete list of standard media types. This option cannot be used with `multiple: true` on Android. Example: `['image/png', 'application/pdf']` |
| **`customExtensions`** | <code>string[]</code> | List of custom extensions. Necessary in iOS since the mimetype alone is not enought Example: `['cs2']` |
| **`multiple`** | <code>boolean</code> | Whether multiple files may be selected. Default: `false` |
| **`readData`** | <code>boolean</code> | Whether to read the file data. Default: `true` |

</docgen-api>

Expand Down
12 changes: 12 additions & 0 deletions ios/Plugin/FilePicker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Foundation
import Capacitor
import UIKit
import MobileCoreServices
import UniformTypeIdentifiers

@objc public class FilePicker: NSObject {
private var plugin: FilePickerPlugin?
Expand All @@ -21,6 +22,17 @@ import MobileCoreServices
}
}

@available(iOS 14.0, *)
public func updatedOpenDocumentPicker(multiple: Bool, documentTypes: [UTType]) {
DispatchQueue.main.async {
let documentPicker = UIDocumentPickerViewController(forOpeningContentTypes: documentTypes)
documentPicker.delegate = self
documentPicker.allowsMultipleSelection = multiple
documentPicker.modalPresentationStyle = .fullScreen
self.plugin?.bridge?.viewController?.present(documentPicker, animated: true, completion: nil)
}
}

public func getPathFromUrl(_ url: URL) -> String {
return url.absoluteString
}
Expand Down
50 changes: 47 additions & 3 deletions ios/Plugin/FilePickerPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Foundation
import Capacitor
import UIKit
import MobileCoreServices
import UniformTypeIdentifiers

/**
* Please read the Capacitor iOS Plugin Development Guide
Expand All @@ -22,10 +23,20 @@ public class FilePickerPlugin: CAPPlugin {

let multiple = call.getBool("multiple", false)
let types = call.getArray("types", String.self) ?? []
let parsedTypes = parseTypesOption(types)
let documentTypes = parsedTypes.isEmpty ? ["public.data"] : parsedTypes
let fileExtensions = call.getArray("customExtensions", String.self) ?? []
if #available(iOS 14.0, *) {
let parsedTypes = newParseTypesOption(types)
let parsedExtensions = parseCustomExtensions(fileExtensions)
let concatenatedTypes = parsedTypes + parsedExtensions
let documentTypes = concatenatedTypes.isEmpty ? [.jpeg] : concatenatedTypes
implementation?.updatedOpenDocumentPicker(multiple: multiple, documentTypes: documentTypes)
} else {
// Fallback on earlier versions
let parsedTypes = parseTypesOption(types)
let documentTypes = parsedTypes.isEmpty ? ["public.data"] : parsedTypes

implementation?.openDocumentPicker(multiple: multiple, documentTypes: documentTypes)
implementation?.openDocumentPicker(multiple: multiple, documentTypes: documentTypes)
}
}

@objc func parseTypesOption(_ types: [String]) -> [String] {
Expand All @@ -39,6 +50,30 @@ public class FilePickerPlugin: CAPPlugin {
return parsedTypes
}

@available(iOS 14.0, *)
@objc func newParseTypesOption(_ types: [String]) -> [UTType] {
var parsedTypes: [UTType] = []
for (_, type) in types.enumerated() {
guard let utType: UTType = UTType(mimeType: type) else {
continue
}
parsedTypes.append(utType)
}
return parsedTypes
}

@available(iOS 14.0, *)
@objc func parseCustomExtensions(_ extensions: [String]) -> [UTType] {
var parsedExtensions: [UTType] = []
for (_, exten) in extensions.enumerated() {
guard let utType: UTType = UTType(filenameExtension: exten) else {
continue
}
parsedExtensions.append(utType)
}
return parsedExtensions
}

@objc func handleDocumentPickerResult(urls: [URL]?) {
guard let savedCall = savedCall else {
return
Expand All @@ -48,9 +83,17 @@ public class FilePickerPlugin: CAPPlugin {
savedCall.reject(errorPickFileCanceled)
return
}
for (url) in urls {
guard url.startAccessingSecurityScopedResource() else {
return
}
}
do {
var result = JSObject()
let filesResult = try urls.map {(url: URL) -> JSObject in
guard url.startAccessingSecurityScopedResource() else {
return
}
var file = JSObject()
file["path"] = implementation?.getPathFromUrl(url) ?? ""
file["name"] = implementation?.getNameFromUrl(url) ?? ""
Expand All @@ -59,6 +102,7 @@ public class FilePickerPlugin: CAPPlugin {
}
file["mimeType"] = implementation?.getMimeTypeFromUrl(url) ?? ""
file["size"] = try implementation?.getSizeFromUrl(url) ?? ""
url.stopAccessingSecurityScopedResource()
return file
}
result["files"] = filesResult
Expand Down
6 changes: 6 additions & 0 deletions src/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ export interface PickFilesOptions {
* Example: `['image/png', 'application/pdf']`
*/
types?: string[];
/**
* List of custom extensions. Necessary in iOS since the mimetype alone is not enought
*
* Example: `['cs2']`
*/
customExtensions?: string[];
/**
* Whether multiple files may be selected.
*
Expand Down

0 comments on commit 1fb4708

Please sign in to comment.