diff --git a/index.d.ts b/index.d.ts index 49950213..c9936f61 100644 --- a/index.d.ts +++ b/index.d.ts @@ -57,6 +57,7 @@ declare module 'react-native-document-picker' { xls: '.xls'; xlsx: '.xlsx'; zip: '.zip .gz'; + folder: 'folder'; }; }; type PlatformTypes = { diff --git a/index.js b/index.js index 52eedab0..4e6dab3e 100644 --- a/index.js +++ b/index.js @@ -62,6 +62,12 @@ function pick(opts) { ); } + if (Array.isArray(opts.type) && opts.type.length > 1) { + if (opts.type.includes('folder')) { + throw new TypeError('When type array is folder then other options are not supported'); + } + } + if ('mode' in opts && !['import', 'open'].includes(opts.mode)) { throw new TypeError('Invalid mode option: ' + opts.mode); } @@ -140,6 +146,7 @@ const Types = { xls: '.xls', xlsx: '.xlsx', zip: '.zip .gz', + folder: 'folder', }, }; diff --git a/windows/RNDocumentPicker/RCTDocumentPickerModule.cs b/windows/RNDocumentPicker/RCTDocumentPickerModule.cs index cbcc2f56..882bf22c 100644 --- a/windows/RNDocumentPicker/RCTDocumentPickerModule.cs +++ b/windows/RNDocumentPicker/RCTDocumentPickerModule.cs @@ -20,7 +20,9 @@ class RCTDocumentPickerModule : ReactContextNativeModuleBase, ILifecycleEventLis private static readonly String E_FAILED_TO_SHOW_PICKER = "FAILED_TO_SHOW_PICKER"; private static readonly String E_DOCUMENT_PICKER_CANCELED = "DOCUMENT_PICKER_CANCELED"; - private static readonly String E_UNEXPECTED_EXCEPTION = "UNEXPECTED_EXCEPTION"; + private static readonly String E_FOLDER_PICKER_CANCELED = "FOLDER_PICKER_CANCELED"; + + private static readonly String E_UNEXPECTED_EXCEPTION = "UNEXPECTED_EXCEPTION"; private static readonly String OPTION_TYPE = "type"; private static readonly String CACHE_TYPE = "cache"; @@ -76,11 +78,20 @@ public void pick(JObject options, IPromise promise) // Get file type array options var fileTypeArray = options.Value(OPTION_TYPE); var cache = options.Value(CACHE_TYPE); + + //if pick called to launch folder picker. + bool isFolderPicker = false; + // Init file type filter if (fileTypeArray != null && fileTypeArray.Count > 0) { foreach (String typeString in fileTypeArray) { + if(typeString == "folder"){ + isFolderPicker = true; + break; + } + List types = typeString.Split(' ').ToList(); foreach (String type in types) { @@ -96,33 +107,63 @@ public void pick(JObject options, IPromise promise) openPicker.FileTypeFilter.Add("*"); } - RunOnDispatcher(async () => + if(isFolderPicker) { - try + var openFolderPicker = new FolderPicker(); + + RunOnDispatcher(async () => { - if (_isInForeground) + try { - var isMultiple = options.Value(OPTION_MULIPLE); - var readContent = options.Value(OPTION_READ_CONTENT); - if (isMultiple) + if (_isInForeground) { - await PickMultipleFileAsync(openPicker, cache, readContent, promise); + openFolderPicker.ViewMode = PickerViewMode.List; + openFolderPicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary; + openFolderPicker.FileTypeFilter.Add("*"); + + await PickFolderAsync(openFolderPicker, promise); } else { - await PickSingleFileAsync(openPicker, cache, readContent, promise); + _pendingPicker = openPicker; } } - else + catch (Exception ex) { - _pendingPicker = openPicker; + promise.Reject(E_FAILED_TO_SHOW_PICKER, ex.Message); } - } - catch (Exception ex) + }); + } + else + { + RunOnDispatcher(async () => { - promise.Reject(E_FAILED_TO_SHOW_PICKER, ex.Message); - } - }); + try + { + if (_isInForeground) + { + var isMultiple = options.Value(OPTION_MULIPLE); + var readContent = options.Value(OPTION_READ_CONTENT); + if (isMultiple) + { + await PickMultipleFileAsync(openPicker, cache, readContent, promise); + } + else + { + await PickSingleFileAsync(openPicker, cache, readContent, promise); + } + } + else + { + _pendingPicker = openPicker; + } + } + catch (Exception ex) + { + promise.Reject(E_FAILED_TO_SHOW_PICKER, ex.Message); + } + }); + } } catch (Exception ex) { promise.Reject(E_UNEXPECTED_EXCEPTION, ex.Message); @@ -208,6 +249,36 @@ private async Task PickSingleFileAsync(FileOpenPicker picker, Boolean cach return true; } + private async Task PrepareFolder(StorageFolder folder) + { + String base64Content = null; + var basicProperties = await folder.GetBasicPropertiesAsync(); + + return new JObject { + { FIELD_URI, folder.Path }, + { FIELD_FILE_COPY_URI, folder.Path }, + { FIELD_NAME, folder.Name }, + { FIELD_SIZE, basicProperties.Size}, + { FIELD_CONTENT, base64Content } + }; + } + + private async Task PickFolderAsync(FolderPicker picker, IPromise promise) + { + var folder = await picker.PickSingleFolderAsync().AsTask().ConfigureAwait(false); + if (folder != null) + { + JArray jarrayObj = new JArray(); + jarrayObj.Add(PrepareFolder(folder).Result); + promise.Resolve(jarrayObj); + } + else + { + promise.Reject(E_FOLDER_PICKER_CANCELED, "User canceled document picker"); + } + + return true; + } private void OnInvoked(Object error, Object success, ICallback callback) { callback.Invoke(error, success);