Skip to content

Commit 45f57bc

Browse files
authored
feat: add explicit pickDirectory() ios implementation (#483)
1 parent d3e5632 commit 45f57bc

File tree

4 files changed

+22
-11
lines changed

4 files changed

+22
-11
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Requires RN >= 0.63, Android 5.0+ and iOS 11+
2727
- [RN >= 0.63](#rn--063)
2828
- [API](#api)
2929
- [DocumentPicker.pickMultiple(options) / DocumentPicker.pickSingle(options) / DocumentPicker.pick(options)](#documentpickerpickmultipleoptions--documentpickerpicksingleoptions--documentpickerpickoptions)
30-
- [[Android and Windows only] DocumentPicker.pickDirectory()](#android-and-windows-only-documentpickerpickdirectory)
30+
- [DocumentPicker.pickDirectory()](#documentpickerpickdirectory)
3131
- [DocumentPicker.pick(options) and DocumentPicker.pickMultiple(options)](#documentpickerpickoptions-and-documentpickerpickmultipleoptions)
3232
- [Options](#options)
3333
- [allowMultiSelection:boolean](#allowmultiselectionboolean)
@@ -73,7 +73,7 @@ If you are using RN >= 0.63, only run `pod install` from the ios directory. Then
7373

7474
Use `pickMultiple`, `pickSingle` or `pick` to open a document picker for the user to select file(s). All methods return a Promise.
7575

76-
#### [Android and Windows only] `DocumentPicker.pickDirectory()`
76+
#### `DocumentPicker.pickDirectory()`
7777

7878
Open a system directory picker. Returns a promise that resolves to (`{ uri: string }`) of the directory selected by user.
7979

example/src/App.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ export default function App() {
8383
}}
8484
/>
8585
<Button
86-
title="open directory picker (android+windows only)"
86+
title="open directory picker"
8787
onPress={() => {
8888
DocumentPicker.pickDirectory().then(setResult).catch(handleError)
8989
}}

ios/RNDocumentPicker.m

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#import <React/RCTUtils.h>
88
#import "RNCPromiseWrapper.h"
99

10+
1011
static NSString *const E_DOCUMENT_PICKER_CANCELED = @"DOCUMENT_PICKER_CANCELED";
1112
static NSString *const E_INVALID_DATA_RETURNED = @"INVALID_DATA_RETURNED";
1213

@@ -87,7 +88,8 @@ - (dispatch_queue_t)methodQueue
8788
[promiseWrapper setPromiseWithInProgressCheck:resolve rejecter:reject fromCallSite:@"pick"];
8889

8990
NSArray *allowedUTIs = [RCTConvert NSArray:options[OPTION_TYPE]];
90-
UIDocumentPickerViewController *documentPicker = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:(NSArray *)allowedUTIs inMode:mode];
91+
UIDocumentPickerViewController *documentPicker = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:allowedUTIs inMode:mode];
92+
9193
documentPicker.modalPresentationStyle = presentationStyle;
9294

9395
documentPicker.delegate = self;
@@ -126,6 +128,7 @@ - (NSMutableDictionary *)getMetadataForUrl:(NSURL *)url error:(NSError **)error
126128
[urlsInOpenMode addObject:url];
127129
}
128130

131+
// TODO handle error
129132
[url startAccessingSecurityScopedResource];
130133

131134
NSFileCoordinator *coordinator = [NSFileCoordinator new];
@@ -158,7 +161,7 @@ - (NSMutableDictionary *)getMetadataForUrl:(NSURL *)url error:(NSError **)error
158161
}
159162

160163
if (newURL.pathExtension != nil) {
161-
CFStringRef extension = (__bridge CFStringRef)[newURL pathExtension];
164+
CFStringRef extension = (__bridge CFStringRef) newURL.pathExtension;
162165
CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, extension, NULL);
163166
CFStringRef mimeType = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType);
164167
if (uti) {
@@ -238,7 +241,8 @@ - (void)documentPickerWasCancelled:(UIDocumentPickerViewController *)controller
238241
[self rejectAsUserCancellationError];
239242
}
240243

241-
- (void)presentationControllerDidDismiss:(UIPresentationController *)presentationController {
244+
- (void)presentationControllerDidDismiss:(UIPresentationController *)presentationController
245+
{
242246
[self rejectAsUserCancellationError];
243247
}
244248

src/index.tsx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,19 @@ export type DocumentPickerOptions<OS extends SupportedPlatforms> = {
3636
allowMultiSelection?: boolean
3737
} & Pick<ModalPropsIOS, 'presentationStyle'>
3838

39-
export function pickDirectory(): Promise<DirectoryPickerResponse | null> {
40-
if (Platform.OS === 'android' || Platform.OS === 'windows') {
41-
return RNDocumentPicker.pickDirectory()
39+
export async function pickDirectory<OS extends SupportedPlatforms>(
40+
params?: Pick<DocumentPickerOptions<OS>, 'presentationStyle'>,
41+
): Promise<DirectoryPickerResponse | null> {
42+
if (Platform.OS === 'ios') {
43+
const result = await pick({
44+
...params,
45+
mode: 'open',
46+
allowMultiSelection: false,
47+
type: ['public.folder'],
48+
})
49+
return { uri: result[0].uri }
4250
} else {
43-
// TODO iOS impl
44-
return Promise.resolve(null)
51+
return RNDocumentPicker.pickDirectory()
4552
}
4653
}
4754

0 commit comments

Comments
 (0)