Skip to content

Commit

Permalink
feat(file-picker): replace multiple option with limit (#148)
Browse files Browse the repository at this point in the history
* feat(file-picker): replace `multiple` option with `limit`

* wip
  • Loading branch information
robingenz committed Feb 27, 2024
1 parent a02faf2 commit 965e912
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 61 deletions.
5 changes: 5 additions & 0 deletions .changeset/olive-mugs-provide.md
@@ -0,0 +1,5 @@
---
'@capawesome/capacitor-file-picker': major
---

feat: replace `multiple` option with `limit`
6 changes: 6 additions & 0 deletions packages/file-picker/BREAKING.md
Expand Up @@ -6,6 +6,12 @@ This is a comprehensive list of the breaking changes introduced in the major ver

- [Version 5.x.x](#version-5xx)

## Version 6.x.x

### Replace the `multiple` option

The `multiple` option has been replaced by a new `limit` option in the `pickFiles(...)`, `pickImages(...)`, `pickMedia(...)` and `pickVideos(...)` methods.

## Version 5.x.x

### Capacitor 5
Expand Down
23 changes: 11 additions & 12 deletions packages/file-picker/README.md
Expand Up @@ -264,22 +264,21 @@ Remove all listeners for this plugin.

#### PickFilesOptions

| Prop | Type | Description | Default |
| -------------- | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ |
| **`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. | |
| **`multiple`** | <code>boolean</code> | Whether multiple files may be selected. | <code>false</code> |
| **`readData`** | <code>boolean</code> | Whether to read the file data. | <code>false</code> |
| Prop | Type | Description | Default | Since |
| -------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | ----- |
| **`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 is ignored if `limit` is set. | | |
| **`limit`** | <code>number</code> | The maximum number of files that the user can select. Setting this to `0` sets the selection limit to unlimited. Currently, only `0` and `1` are supported. | <code>0</code> | 6.0.0 |
| **`readData`** | <code>boolean</code> | Whether to read the file data. | <code>false</code> | |


#### PickMediaOptions

| Prop | Type | Description | Default | Since |
| --------------------- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | ----- |
| **`multiple`** | <code>boolean</code> | Whether multiple files may be selected. | <code>false</code> | |
| **`readData`** | <code>boolean</code> | Whether to read the file data. | <code>false</code> | |
| **`skipTranscoding`** | <code>boolean</code> | Whether to avoid transcoding, if possible. On iOS, for example, HEIC images are automatically transcoded to JPEG. Only available on iOS. | <code>false</code> | |
| **`limit`** | <code>number</code> | The maximum number of files that the user can select. This option is ignored if `multiple` is set to `false`. Only available on iOS. | <code>0 (unlimited)</code> | |
| **`ordered`** | <code>boolean</code> | Whether an ordered number is displayed instead of a check mark in the selection badge. Only available on iOS (15+). | <code>false</code> | 5.3.0 |
| Prop | Type | Description | Default | Since |
| --------------------- | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | ----- |
| **`readData`** | <code>boolean</code> | Whether to read the file data. | <code>false</code> | |
| **`skipTranscoding`** | <code>boolean</code> | Whether to avoid transcoding, if possible. On iOS, for example, HEIC images are automatically transcoded to JPEG. Only available on iOS. | <code>false</code> | |
| **`limit`** | <code>number</code> | The maximum number of files that the user can select. Setting this to `0` sets the selection limit to unlimited. On Android and Web, only `0` and `1` are supported. | <code>0</code> | 5.2.0 |
| **`ordered`** | <code>boolean</code> | Whether an ordered number is displayed instead of a check mark in the selection badge. Only available on iOS (15+). | <code>false</code> | 5.3.0 |


#### PluginListenerHandle
Expand Down
Expand Up @@ -39,15 +39,15 @@ public void convertHeicToJpeg(PluginCall call) {
@PluginMethod
public void pickFiles(PluginCall call) {
try {
int limit = call.getInt("limit", 0);
JSArray types = call.getArray("types", null);
boolean multiple = call.getBoolean("multiple", false);
String[] parsedTypes = parseTypesOption(types);

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, multiple);
if (multiple == false && parsedTypes != null && parsedTypes.length > 0) {
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, limit == 0);
if (limit == 1 && parsedTypes != null && parsedTypes.length > 0) {
intent.putExtra(Intent.EXTRA_MIME_TYPES, parsedTypes);
}

Expand All @@ -62,12 +62,12 @@ public void pickFiles(PluginCall call) {
@PluginMethod
public void pickImages(PluginCall call) {
try {
boolean multiple = call.getBoolean("multiple", false);
int limit = call.getInt("limit", 0);

Intent intent = new Intent(Intent.ACTION_PICK);
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, multiple);
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, limit == 0);
intent.setType("image/*");
intent.putExtra("multi-pick", multiple);
intent.putExtra("multi-pick", limit == 0);
intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[] { "image/*" });

startActivityForResult(call, intent, "pickFilesResult");
Expand All @@ -81,12 +81,12 @@ public void pickImages(PluginCall call) {
@PluginMethod
public void pickMedia(PluginCall call) {
try {
boolean multiple = call.getBoolean("multiple", false);
int limit = call.getInt("limit", 0);

Intent intent = new Intent(Intent.ACTION_PICK);
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, multiple);
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, limit == 0);
intent.setType("*/*");
intent.putExtra("multi-pick", multiple);
intent.putExtra("multi-pick", limit == 0);
intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[] { "image/*", "video/*" });

startActivityForResult(call, intent, "pickFilesResult");
Expand All @@ -100,12 +100,12 @@ public void pickMedia(PluginCall call) {
@PluginMethod
public void pickVideos(PluginCall call) {
try {
boolean multiple = call.getBoolean("multiple", false);
int limit = call.getInt("limit", 0);

Intent intent = new Intent(Intent.ACTION_PICK);
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, multiple);
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, limit == 0);
intent.setType("video/*");
intent.putExtra("multi-pick", multiple);
intent.putExtra("multi-pick", limit == 0);
intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[] { "video/*" });

startActivityForResult(call, intent, "pickFilesResult");
Expand Down
16 changes: 8 additions & 8 deletions packages/file-picker/ios/Plugin/FilePicker.swift
Expand Up @@ -29,21 +29,21 @@ import MobileCoreServices
return targetUrl
}

public func openDocumentPicker(multiple: Bool, documentTypes: [String]) {
public func openDocumentPicker(limit: Int, documentTypes: [String]) {
DispatchQueue.main.async {
let picker = UIDocumentPickerViewController(documentTypes: documentTypes, in: .import)
picker.delegate = self
picker.allowsMultipleSelection = multiple
picker.allowsMultipleSelection = limit == 0
picker.modalPresentationStyle = .fullScreen
self.presentViewController(picker)
}
}

public func openImagePicker(multiple: Bool, skipTranscoding: Bool, limit: Int?, ordered: Bool) {
public func openImagePicker(limit: Int, skipTranscoding: Bool, ordered: Bool) {
DispatchQueue.main.async {
if #available(iOS 14, *) {
var configuration = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared())
configuration.selectionLimit = multiple ? (limit ?? 0) : 1
configuration.selectionLimit = limit

if #available(iOS 15, *) {
configuration.selection = ordered ? .ordered : .default
Expand All @@ -65,11 +65,11 @@ import MobileCoreServices
}
}

public func openMediaPicker(multiple: Bool, skipTranscoding: Bool, limit: Int?, ordered: Bool) {
public func openMediaPicker(limit: Int, skipTranscoding: Bool, ordered: Bool) {
DispatchQueue.main.async {
if #available(iOS 14, *) {
var configuration = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared())
configuration.selectionLimit = multiple ? (limit ?? 0) : 1
configuration.selectionLimit = limit

if #available(iOS 15, *) {
configuration.selection = ordered ? .ordered : .default
Expand All @@ -90,11 +90,11 @@ import MobileCoreServices
}
}

public func openVideoPicker(multiple: Bool, skipTranscoding: Bool, limit: Int?, ordered: Bool) {
public func openVideoPicker(limit: Int, skipTranscoding: Bool, ordered: Bool) {
DispatchQueue.main.async {
if #available(iOS 14, *) {
var configuration = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared())
configuration.selectionLimit = multiple ? (limit ?? 0) : 1
configuration.selectionLimit = limit

if #available(iOS 15, *) {
configuration.selection = ordered ? .ordered : .default
Expand Down
19 changes: 8 additions & 11 deletions packages/file-picker/ios/Plugin/FilePickerPlugin.swift
Expand Up @@ -52,45 +52,42 @@ public class FilePickerPlugin: CAPPlugin {
@objc func pickFiles(_ call: CAPPluginCall) {
savedCall = call

let multiple = call.getBool("multiple", false)
let limit = call.getInt("limit", 0)
let types = call.getArray("types", String.self) ?? []
let parsedTypes = parseTypesOption(types)
let documentTypes = parsedTypes.isEmpty ? ["public.data"] : parsedTypes

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

@objc func pickImages(_ call: CAPPluginCall) {
savedCall = call

let multiple = call.getBool("multiple", false)
let limit = call.getInt("limit", 0)
let skipTranscoding = call.getBool("skipTranscoding", false)
let limit = call.getInt("limit")
let ordered = call.getBool("ordered", false)

implementation?.openImagePicker(multiple: multiple, skipTranscoding: skipTranscoding, limit: limit, ordered: ordered)
implementation?.openImagePicker(limit: limit, skipTranscoding: skipTranscoding, ordered: ordered)
}

@objc func pickMedia(_ call: CAPPluginCall) {
savedCall = call

let multiple = call.getBool("multiple", false)
let limit = call.getInt("limit", 0)
let skipTranscoding = call.getBool("skipTranscoding", false)
let limit = call.getInt("limit")
let ordered = call.getBool("ordered", false)

implementation?.openMediaPicker(multiple: multiple, skipTranscoding: skipTranscoding, limit: limit, ordered: ordered)
implementation?.openMediaPicker(limit: limit, skipTranscoding: skipTranscoding, ordered: ordered)
}

@objc func pickVideos(_ call: CAPPluginCall) {
savedCall = call

let multiple = call.getBool("multiple", false)
let limit = call.getInt("limit", 0)
let skipTranscoding = call.getBool("skipTranscoding", false)
let limit = call.getInt("limit")
let ordered = call.getBool("ordered", false)

implementation?.openVideoPicker(multiple: multiple, skipTranscoding: skipTranscoding, limit: limit, ordered: ordered)
implementation?.openVideoPicker(limit: limit, skipTranscoding: skipTranscoding, ordered: ordered)
}

@objc func notifyPickerDismissedListener() {
Expand Down
30 changes: 14 additions & 16 deletions packages/file-picker/src/definitions.ts
Expand Up @@ -95,17 +95,22 @@ export interface PickFilesOptions {
* 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.
* This option is ignored if `limit` is set.
*
* @example ['image/png', 'application/pdf']
*/
types?: string[];
/**
* Whether multiple files may be selected.
* The maximum number of files that the user can select.
* Setting this to `0` sets the selection limit to unlimited.
*
* @default false
* Currently, only `0` and `1` are supported.
*
* @default 0
* @example 1
* @since 6.0.0
*/
multiple?: boolean;
limit?: number;
/**
* Whether to read the file data.
*
Expand Down Expand Up @@ -193,12 +198,6 @@ export interface File {
* @since 0.5.3
*/
export interface PickMediaOptions {
/**
* Whether multiple files may be selected.
*
* @default false
*/
multiple?: boolean;
/**
* Whether to read the file data.
*
Expand All @@ -218,14 +217,13 @@ export interface PickMediaOptions {
skipTranscoding?: boolean;
/**
* The maximum number of files that the user can select.
* Setting this to `0` sets the selection limit to unlimited.
*
* This option is ignored if `multiple` is set to `false`.
*
* Only available on iOS.
*
* @default 0 (unlimited)
* On Android and Web, only `0` and `1` are supported.
*
* @example 4
* @default 0
* @example 1
* @since 5.2.0
*/
limit?: number;
/**
Expand Down
4 changes: 2 additions & 2 deletions packages/file-picker/src/web.ts
Expand Up @@ -69,13 +69,13 @@ export class FilePickerWeb extends WebPlugin implements FilePickerPlugin {
options?: PickFilesOptions,
): Promise<File[] | undefined> {
const accept = options?.types?.join(',') || '';
const multiple = !!options?.multiple;
const limit = options?.limit === undefined ? 0 : options.limit;
return new Promise(resolve => {
let onChangeFired = false;
const input = document.createElement('input');
input.type = 'file';
input.accept = accept;
input.multiple = multiple;
input.multiple = limit === 0;
input.addEventListener(
'change',
() => {
Expand Down

0 comments on commit 965e912

Please sign in to comment.