diff --git a/packages/file_selector/file_selector_platform_interface/CHANGELOG.md b/packages/file_selector/file_selector_platform_interface/CHANGELOG.md index ad803fb12e66..e0b08f086977 100644 --- a/packages/file_selector/file_selector_platform_interface/CHANGELOG.md +++ b/packages/file_selector/file_selector_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.4.0 + +* Adds `getDirectoryPaths` method to the interface. + ## 2.3.0 * Replaces `macUTIs` with `uniformTypeIdentifiers`. `macUTIs` is available as an alias, but will be deprecated in a future release. diff --git a/packages/file_selector/file_selector_platform_interface/lib/src/method_channel/method_channel_file_selector.dart b/packages/file_selector/file_selector_platform_interface/lib/src/method_channel/method_channel_file_selector.dart index d6aebd01730f..98184cab8768 100644 --- a/packages/file_selector/file_selector_platform_interface/lib/src/method_channel/method_channel_file_selector.dart +++ b/packages/file_selector/file_selector_platform_interface/lib/src/method_channel/method_channel_file_selector.dart @@ -16,7 +16,6 @@ class MethodChannelFileSelector extends FileSelectorPlatform { @visibleForTesting MethodChannel get channel => _channel; - /// Load a file from user's computer and return it as an XFile @override Future openFile({ List? acceptedTypeGroups, @@ -37,7 +36,6 @@ class MethodChannelFileSelector extends FileSelectorPlatform { return path == null ? null : XFile(path.first); } - /// Load multiple files from user's computer and return it as an XFile @override Future> openFiles({ List? acceptedTypeGroups, @@ -58,7 +56,6 @@ class MethodChannelFileSelector extends FileSelectorPlatform { return pathList?.map((String path) => XFile(path)).toList() ?? []; } - /// Gets the path from a save dialog @override Future getSavePath({ List? acceptedTypeGroups, @@ -79,7 +76,6 @@ class MethodChannelFileSelector extends FileSelectorPlatform { ); } - /// Gets a directory path from a dialog @override Future getDirectoryPath({ String? initialDirectory, @@ -93,4 +89,17 @@ class MethodChannelFileSelector extends FileSelectorPlatform { }, ); } + + @override + Future> getDirectoryPaths( + {String? initialDirectory, String? confirmButtonText}) async { + final List? pathList = await _channel.invokeListMethod( + 'getDirectoryPaths', + { + 'initialDirectory': initialDirectory, + 'confirmButtonText': confirmButtonText, + }, + ); + return pathList ?? []; + } } diff --git a/packages/file_selector/file_selector_platform_interface/lib/src/platform_interface/file_selector_interface.dart b/packages/file_selector/file_selector_platform_interface/lib/src/platform_interface/file_selector_interface.dart index eb4563c47917..ad4fe617e44e 100644 --- a/packages/file_selector/file_selector_platform_interface/lib/src/platform_interface/file_selector_interface.dart +++ b/packages/file_selector/file_selector_platform_interface/lib/src/platform_interface/file_selector_interface.dart @@ -36,7 +36,7 @@ abstract class FileSelectorPlatform extends PlatformInterface { _instance = instance; } - /// Open file dialog for loading files and return a file path + /// Opens a file dialog for loading files and returns a file path. /// Returns `null` if user cancels the operation. Future openFile({ List? acceptedTypeGroups, @@ -46,7 +46,7 @@ abstract class FileSelectorPlatform extends PlatformInterface { throw UnimplementedError('openFile() has not been implemented.'); } - /// Open file dialog for loading files and return a list of file paths + /// Opens a file dialog for loading files and returns a list of file paths. Future> openFiles({ List? acceptedTypeGroups, String? initialDirectory, @@ -55,7 +55,7 @@ abstract class FileSelectorPlatform extends PlatformInterface { throw UnimplementedError('openFiles() has not been implemented.'); } - /// Open file dialog for saving files and return a file path at which to save + /// Opens a file dialog for saving files and returns a file path at which to save. /// Returns `null` if user cancels the operation. Future getSavePath({ List? acceptedTypeGroups, @@ -66,7 +66,7 @@ abstract class FileSelectorPlatform extends PlatformInterface { throw UnimplementedError('getSavePath() has not been implemented.'); } - /// Open file dialog for loading directories and return a directory path + /// Opens a file dialog for loading directories and returns a directory path. /// Returns `null` if user cancels the operation. Future getDirectoryPath({ String? initialDirectory, @@ -74,4 +74,12 @@ abstract class FileSelectorPlatform extends PlatformInterface { }) { throw UnimplementedError('getDirectoryPath() has not been implemented.'); } + + /// Opens a file dialog for loading directories and returns multiple directory paths. + Future> getDirectoryPaths({ + String? initialDirectory, + String? confirmButtonText, + }) { + throw UnimplementedError('getDirectoryPaths() has not been implemented.'); + } } diff --git a/packages/file_selector/file_selector_platform_interface/pubspec.yaml b/packages/file_selector/file_selector_platform_interface/pubspec.yaml index ac8727c09e36..4ab63acbf7e6 100644 --- a/packages/file_selector/file_selector_platform_interface/pubspec.yaml +++ b/packages/file_selector/file_selector_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ repository: https://github.com/flutter/plugins/tree/main/packages/file_selector/ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+file_selector%22 # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 2.3.0 +version: 2.4.0 environment: sdk: ">=2.12.0 <3.0.0" diff --git a/packages/file_selector/file_selector_platform_interface/test/file_selector_platform_interface_test.dart b/packages/file_selector/file_selector_platform_interface/test/file_selector_platform_interface_test.dart index 91e78b452961..18334e885fc7 100644 --- a/packages/file_selector/file_selector_platform_interface/test/file_selector_platform_interface_test.dart +++ b/packages/file_selector/file_selector_platform_interface/test/file_selector_platform_interface_test.dart @@ -19,6 +19,16 @@ void main() { FileSelectorPlatform.instance = ExtendsFileSelectorPlatform(); }); }); + + group('#GetDirectoryPaths', () { + test('Should throw unimplemented exception', () async { + final FileSelectorPlatform fileSelector = ExtendsFileSelectorPlatform(); + + await expectLater(() async { + return fileSelector.getDirectoryPaths(); + }, throwsA(isA())); + }); + }); } class ExtendsFileSelectorPlatform extends FileSelectorPlatform {} diff --git a/packages/file_selector/file_selector_platform_interface/test/method_channel_file_selector_test.dart b/packages/file_selector/file_selector_platform_interface/test/method_channel_file_selector_test.dart index 0f5f3a17ae0c..9caa76c02bcb 100644 --- a/packages/file_selector/file_selector_platform_interface/test/method_channel_file_selector_test.dart +++ b/packages/file_selector/file_selector_platform_interface/test/method_channel_file_selector_test.dart @@ -43,49 +43,46 @@ void main() { await plugin .openFile(acceptedTypeGroups: [group, groupTwo]); - expect( + expectMethodCall( log, - [ - isMethodCall('openFile', arguments: { - 'acceptedTypeGroups': >[ - group.toJSON(), - groupTwo.toJSON() - ], - 'initialDirectory': null, - 'confirmButtonText': null, - 'multiple': false, - }), - ], + 'openFile', + arguments: { + 'acceptedTypeGroups': >[ + group.toJSON(), + groupTwo.toJSON() + ], + 'initialDirectory': null, + 'confirmButtonText': null, + 'multiple': false, + }, ); }); test('passes initialDirectory correctly', () async { await plugin.openFile(initialDirectory: '/example/directory'); - expect( + expectMethodCall( log, - [ - isMethodCall('openFile', arguments: { - 'acceptedTypeGroups': null, - 'initialDirectory': '/example/directory', - 'confirmButtonText': null, - 'multiple': false, - }), - ], + 'openFile', + arguments: { + 'acceptedTypeGroups': null, + 'initialDirectory': '/example/directory', + 'confirmButtonText': null, + 'multiple': false, + }, ); }); test('passes confirmButtonText correctly', () async { await plugin.openFile(confirmButtonText: 'Open File'); - expect( + expectMethodCall( log, - [ - isMethodCall('openFile', arguments: { - 'acceptedTypeGroups': null, - 'initialDirectory': null, - 'confirmButtonText': 'Open File', - 'multiple': false, - }), - ], + 'openFile', + arguments: { + 'acceptedTypeGroups': null, + 'initialDirectory': null, + 'confirmButtonText': 'Open File', + 'multiple': false, + }, ); }); }); @@ -108,49 +105,46 @@ void main() { await plugin .openFiles(acceptedTypeGroups: [group, groupTwo]); - expect( + expectMethodCall( log, - [ - isMethodCall('openFile', arguments: { - 'acceptedTypeGroups': >[ - group.toJSON(), - groupTwo.toJSON() - ], - 'initialDirectory': null, - 'confirmButtonText': null, - 'multiple': true, - }), - ], + 'openFile', + arguments: { + 'acceptedTypeGroups': >[ + group.toJSON(), + groupTwo.toJSON() + ], + 'initialDirectory': null, + 'confirmButtonText': null, + 'multiple': true, + }, ); }); test('passes initialDirectory correctly', () async { await plugin.openFiles(initialDirectory: '/example/directory'); - expect( + expectMethodCall( log, - [ - isMethodCall('openFile', arguments: { - 'acceptedTypeGroups': null, - 'initialDirectory': '/example/directory', - 'confirmButtonText': null, - 'multiple': true, - }), - ], + 'openFile', + arguments: { + 'acceptedTypeGroups': null, + 'initialDirectory': '/example/directory', + 'confirmButtonText': null, + 'multiple': true, + }, ); }); test('passes confirmButtonText correctly', () async { await plugin.openFiles(confirmButtonText: 'Open File'); - expect( + expectMethodCall( log, - [ - isMethodCall('openFile', arguments: { - 'acceptedTypeGroups': null, - 'initialDirectory': null, - 'confirmButtonText': 'Open File', - 'multiple': true, - }), - ], + 'openFile', + arguments: { + 'acceptedTypeGroups': null, + 'initialDirectory': null, + 'confirmButtonText': 'Open File', + 'multiple': true, + }, ); }); }); @@ -174,79 +168,109 @@ void main() { await plugin .getSavePath(acceptedTypeGroups: [group, groupTwo]); - expect( + expectMethodCall( log, - [ - isMethodCall('getSavePath', arguments: { - 'acceptedTypeGroups': >[ - group.toJSON(), - groupTwo.toJSON() - ], - 'initialDirectory': null, - 'suggestedName': null, - 'confirmButtonText': null, - }), - ], + 'getSavePath', + arguments: { + 'acceptedTypeGroups': >[ + group.toJSON(), + groupTwo.toJSON() + ], + 'initialDirectory': null, + 'suggestedName': null, + 'confirmButtonText': null, + }, ); }); test('passes initialDirectory correctly', () async { await plugin.getSavePath(initialDirectory: '/example/directory'); - expect( + expectMethodCall( log, - [ - isMethodCall('getSavePath', arguments: { - 'acceptedTypeGroups': null, - 'initialDirectory': '/example/directory', - 'suggestedName': null, - 'confirmButtonText': null, - }), - ], + 'getSavePath', + arguments: { + 'acceptedTypeGroups': null, + 'initialDirectory': '/example/directory', + 'suggestedName': null, + 'confirmButtonText': null, + }, ); }); test('passes confirmButtonText correctly', () async { await plugin.getSavePath(confirmButtonText: 'Open File'); - expect( + expectMethodCall( log, - [ - isMethodCall('getSavePath', arguments: { - 'acceptedTypeGroups': null, - 'initialDirectory': null, - 'suggestedName': null, - 'confirmButtonText': 'Open File', - }), - ], + 'getSavePath', + arguments: { + 'acceptedTypeGroups': null, + 'initialDirectory': null, + 'suggestedName': null, + 'confirmButtonText': 'Open File', + }, ); }); - group('#getDirectoryPath', () { - test('passes initialDirectory correctly', () async { - await plugin.getDirectoryPath(initialDirectory: '/example/directory'); - - expect( - log, - [ - isMethodCall('getDirectoryPath', arguments: { - 'initialDirectory': '/example/directory', - 'confirmButtonText': null, - }), - ], - ); - }); - test('passes confirmButtonText correctly', () async { - await plugin.getDirectoryPath(confirmButtonText: 'Open File'); - - expect( - log, - [ - isMethodCall('getDirectoryPath', arguments: { - 'initialDirectory': null, - 'confirmButtonText': 'Open File', - }), - ], - ); - }); + }); + group('#getDirectoryPath', () { + test('passes initialDirectory correctly', () async { + await plugin.getDirectoryPath(initialDirectory: '/example/directory'); + + expectMethodCall( + log, + 'getDirectoryPath', + arguments: { + 'initialDirectory': '/example/directory', + 'confirmButtonText': null, + }, + ); + }); + test('passes confirmButtonText correctly', () async { + await plugin.getDirectoryPath(confirmButtonText: 'Select Folder'); + + expectMethodCall( + log, + 'getDirectoryPath', + arguments: { + 'initialDirectory': null, + 'confirmButtonText': 'Select Folder', + }, + ); + }); + }); + group('#getDirectoryPaths', () { + test('passes initialDirectory correctly', () async { + await plugin.getDirectoryPaths(initialDirectory: '/example/directory'); + + expectMethodCall( + log, + 'getDirectoryPaths', + arguments: { + 'initialDirectory': '/example/directory', + 'confirmButtonText': null, + }, + ); + }); + test('passes confirmButtonText correctly', () async { + await plugin.getDirectoryPaths( + confirmButtonText: 'Select one or more Folders'); + + expectMethodCall( + log, + 'getDirectoryPaths', + arguments: { + 'initialDirectory': null, + 'confirmButtonText': 'Select one or more Folders', + }, + ); }); }); }); } + +void expectMethodCall( + List log, + String methodName, { + Map? arguments, +}) { + expect(log, [isMethodCall(methodName, arguments: arguments)]); +}