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

[file_selector] Switch to Pigeon for macOS #6902

Merged
merged 6 commits into from
Jan 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/file_selector/file_selector_macos/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.9.0+4

* Converts platform channel to Pigeon.

## 0.9.0+3

* Changes XTypeGroup initialization from final to const.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,13 @@ class exampleTests: XCTestCase {
panelController.openURLs = [URL(fileURLWithPath: returnPath)]

let called = XCTestExpectation()
let call = FlutterMethodCall(methodName: "openFile", arguments: [:])
plugin.handle(call) { result in
XCTAssertEqual((result as! [String]?)![0], returnPath)
let options = OpenPanelOptions(
allowsMultipleSelection: false,
canChooseDirectories: false,
canChooseFiles: true,
baseOptions: SavePanelOptions())
plugin.displayOpenPanel(options: options) { paths in
XCTAssertEqual(paths[0], returnPath)
called.fulfill()
}

Expand All @@ -72,16 +76,16 @@ class exampleTests: XCTestCase {
panelController.openURLs = [URL(fileURLWithPath: returnPath)]

let called = XCTestExpectation()
let call = FlutterMethodCall(
methodName: "openFile",
arguments: [
"initialDirectory": "/some/dir",
"suggestedName": "a name",
"confirmButtonText": "Open it!",
]
)
plugin.handle(call) { result in
XCTAssertEqual((result as! [String]?)![0], returnPath)
let options = OpenPanelOptions(
allowsMultipleSelection: false,
canChooseDirectories: false,
canChooseFiles: true,
baseOptions: SavePanelOptions(
directoryPath: "/some/dir",
nameFieldStringValue: "a name",
prompt: "Open it!"))
plugin.displayOpenPanel(options: options) { paths in
XCTAssertEqual(paths[0], returnPath)
called.fulfill()
}

Expand All @@ -104,12 +108,12 @@ class exampleTests: XCTestCase {
panelController.openURLs = returnPaths.map({ path in URL(fileURLWithPath: path) })

let called = XCTestExpectation()
let call = FlutterMethodCall(
methodName: "openFile",
arguments: ["multiple": true]
)
plugin.handle(call) { result in
let paths = (result as! [String]?)!
let options = OpenPanelOptions(
allowsMultipleSelection: true,
canChooseDirectories: false,
canChooseFiles: true,
baseOptions: SavePanelOptions())
plugin.displayOpenPanel(options: options) { paths in
XCTAssertEqual(paths.count, returnPaths.count)
XCTAssertEqual(paths[0], returnPaths[0])
XCTAssertEqual(paths[1], returnPaths[1])
Expand All @@ -130,17 +134,17 @@ class exampleTests: XCTestCase {
panelController.openURLs = [URL(fileURLWithPath: returnPath)]

let called = XCTestExpectation()
let call = FlutterMethodCall(
methodName: "openFile",
arguments: [
"acceptedTypes": [
"extensions": ["txt", "json"],
"UTIs": ["public.text", "public.image"],
]
]
)
plugin.handle(call) { result in
XCTAssertEqual((result as! [String]?)![0], returnPath)
let options = OpenPanelOptions(
allowsMultipleSelection: true,
canChooseDirectories: false,
canChooseFiles: true,
baseOptions: SavePanelOptions(
allowedFileTypes: AllowedTypes(
extensions: ["txt", "json"],
mimeTypes: [],
utis: ["public.text", "public.image"])))
plugin.displayOpenPanel(options: options) { paths in
XCTAssertEqual(paths[0], returnPath)
called.fulfill()
}

Expand All @@ -158,9 +162,13 @@ class exampleTests: XCTestCase {
panelController: panelController)

let called = XCTestExpectation()
let call = FlutterMethodCall(methodName: "openFile", arguments: [:])
plugin.handle(call) { result in
XCTAssertNil(result)
let options = OpenPanelOptions(
allowsMultipleSelection: false,
canChooseDirectories: false,
canChooseFiles: true,
baseOptions: SavePanelOptions())
plugin.displayOpenPanel(options: options) { paths in
XCTAssertEqual(paths.count, 0)
called.fulfill()
}

Expand All @@ -178,9 +186,9 @@ class exampleTests: XCTestCase {
panelController.saveURL = URL(fileURLWithPath: returnPath)

let called = XCTestExpectation()
let call = FlutterMethodCall(methodName: "getSavePath", arguments: [:])
plugin.handle(call) { result in
XCTAssertEqual(result as! String?, returnPath)
let options = SavePanelOptions()
plugin.displaySavePanel(options: options) { path in
XCTAssertEqual(path, returnPath)
called.fulfill()
}

Expand All @@ -198,15 +206,11 @@ class exampleTests: XCTestCase {
panelController.saveURL = URL(fileURLWithPath: returnPath)

let called = XCTestExpectation()
let call = FlutterMethodCall(
methodName: "getSavePath",
arguments: [
"initialDirectory": "/some/dir",
"confirmButtonText": "Save it!",
]
)
plugin.handle(call) { result in
XCTAssertEqual(result as! String?, returnPath)
let options = SavePanelOptions(
directoryPath: "/some/dir",
prompt: "Save it!")
plugin.displaySavePanel(options: options) { path in
XCTAssertEqual(path, returnPath)
called.fulfill()
}

Expand All @@ -225,9 +229,9 @@ class exampleTests: XCTestCase {
panelController: panelController)

let called = XCTestExpectation()
let call = FlutterMethodCall(methodName: "getSavePath", arguments: [:])
plugin.handle(call) { result in
XCTAssertNil(result)
let options = SavePanelOptions()
plugin.displaySavePanel(options: options) { path in
XCTAssertNil(path)
called.fulfill()
}

Expand All @@ -245,9 +249,13 @@ class exampleTests: XCTestCase {
panelController.openURLs = [URL(fileURLWithPath: returnPath)]

let called = XCTestExpectation()
let call = FlutterMethodCall(methodName: "getDirectoryPath", arguments: [:])
plugin.handle(call) { result in
XCTAssertEqual(result as! String?, returnPath)
let options = OpenPanelOptions(
allowsMultipleSelection: false,
canChooseDirectories: true,
canChooseFiles: false,
baseOptions: SavePanelOptions())
plugin.displayOpenPanel(options: options) { paths in
XCTAssertEqual(paths[0], returnPath)
called.fulfill()
}

Expand All @@ -270,9 +278,13 @@ class exampleTests: XCTestCase {
panelController: panelController)

let called = XCTestExpectation()
let call = FlutterMethodCall(methodName: "getDirectoryPath", arguments: [:])
plugin.handle(call) { result in
XCTAssertNil(result)
let options = OpenPanelOptions(
allowsMultipleSelection: false,
canChooseDirectories: true,
canChooseFiles: false,
baseOptions: SavePanelOptions())
plugin.displayOpenPanel(options: options) { paths in
XCTAssertEqual(paths.count, 0)
called.fulfill()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,12 @@
// found in the LICENSE file.

import 'package:file_selector_platform_interface/file_selector_platform_interface.dart';
import 'package:flutter/foundation.dart' show visibleForTesting;
import 'package:flutter/services.dart';

const MethodChannel _channel =
MethodChannel('plugins.flutter.io/file_selector_macos');
import 'src/messages.g.dart';

/// An implementation of [FileSelectorPlatform] for macOS.
class FileSelectorMacOS extends FileSelectorPlatform {
/// The MethodChannel that is being used by this implementation of the plugin.
@visibleForTesting
MethodChannel get channel => _channel;
final FileSelectorApi _hostApi = FileSelectorApi();

/// Registers the macOS implementation.
static void registerWith() {
Expand All @@ -26,16 +21,17 @@ class FileSelectorMacOS extends FileSelectorPlatform {
String? initialDirectory,
String? confirmButtonText,
}) async {
final List<String>? path = await _channel.invokeListMethod<String>(
'openFile',
<String, dynamic>{
'acceptedTypes': _allowedTypeListFromTypeGroups(acceptedTypeGroups),
'initialDirectory': initialDirectory,
'confirmButtonText': confirmButtonText,
'multiple': false,
},
);
return path == null ? null : XFile(path.first);
final List<String?> paths =
await _hostApi.displayOpenPanel(OpenPanelOptions(
allowsMultipleSelection: false,
canChooseDirectories: false,
canChooseFiles: true,
baseOptions: SavePanelOptions(
allowedFileTypes: _allowedTypesFromTypeGroups(acceptedTypeGroups),
directoryPath: initialDirectory,
prompt: confirmButtonText,
)));
return paths.isEmpty ? null : XFile(paths.first!);
}

@override
Expand All @@ -44,16 +40,17 @@ class FileSelectorMacOS extends FileSelectorPlatform {
String? initialDirectory,
String? confirmButtonText,
}) async {
final List<String>? pathList = await _channel.invokeListMethod<String>(
'openFile',
<String, dynamic>{
'acceptedTypes': _allowedTypeListFromTypeGroups(acceptedTypeGroups),
'initialDirectory': initialDirectory,
'confirmButtonText': confirmButtonText,
'multiple': true,
},
);
return pathList?.map((String path) => XFile(path)).toList() ?? <XFile>[];
final List<String?> paths =
await _hostApi.displayOpenPanel(OpenPanelOptions(
allowsMultipleSelection: true,
canChooseDirectories: false,
canChooseFiles: true,
baseOptions: SavePanelOptions(
allowedFileTypes: _allowedTypesFromTypeGroups(acceptedTypeGroups),
directoryPath: initialDirectory,
prompt: confirmButtonText,
)));
return paths.map((String? path) => XFile(path!)).toList();
}

@override
Expand All @@ -63,46 +60,42 @@ class FileSelectorMacOS extends FileSelectorPlatform {
String? suggestedName,
String? confirmButtonText,
}) async {
return _channel.invokeMethod<String>(
'getSavePath',
<String, dynamic>{
'acceptedTypes': _allowedTypeListFromTypeGroups(acceptedTypeGroups),
'initialDirectory': initialDirectory,
'suggestedName': suggestedName,
'confirmButtonText': confirmButtonText,
},
);
return _hostApi.displaySavePanel(SavePanelOptions(
allowedFileTypes: _allowedTypesFromTypeGroups(acceptedTypeGroups),
directoryPath: initialDirectory,
nameFieldStringValue: suggestedName,
prompt: confirmButtonText,
));
}

@override
Future<String?> getDirectoryPath({
String? initialDirectory,
String? confirmButtonText,
}) async {
return _channel.invokeMethod<String>(
'getDirectoryPath',
<String, dynamic>{
'initialDirectory': initialDirectory,
'confirmButtonText': confirmButtonText,
},
);
final List<String?> paths =
await _hostApi.displayOpenPanel(OpenPanelOptions(
allowsMultipleSelection: false,
canChooseDirectories: true,
canChooseFiles: false,
baseOptions: SavePanelOptions(
directoryPath: initialDirectory,
prompt: confirmButtonText,
)));
return paths.isEmpty ? null : paths.first;
}

// Converts the type group list into a flat list of all allowed types, since
// macOS doesn't support filter groups.
Map<String, List<String>>? _allowedTypeListFromTypeGroups(
List<XTypeGroup>? typeGroups) {
const String extensionKey = 'extensions';
const String mimeTypeKey = 'mimeTypes';
const String utiKey = 'UTIs';
AllowedTypes? _allowedTypesFromTypeGroups(List<XTypeGroup>? typeGroups) {
if (typeGroups == null || typeGroups.isEmpty) {
return null;
}
final Map<String, List<String>> allowedTypes = <String, List<String>>{
extensionKey: <String>[],
mimeTypeKey: <String>[],
utiKey: <String>[],
};
final AllowedTypes allowedTypes = AllowedTypes(
extensions: <String>[],
mimeTypes: <String>[],
utis: <String>[],
);
for (final XTypeGroup typeGroup in typeGroups) {
// If any group allows everything, no filtering should be done.
if (typeGroup.allowsAny) {
Expand All @@ -119,9 +112,9 @@ class FileSelectorMacOS extends FileSelectorPlatform {
'"mimeTypes" must be non-empty for macOS if anything is '
'non-empty.');
}
allowedTypes[extensionKey]!.addAll(typeGroup.extensions ?? <String>[]);
allowedTypes[mimeTypeKey]!.addAll(typeGroup.mimeTypes ?? <String>[]);
allowedTypes[utiKey]!.addAll(typeGroup.macUTIs ?? <String>[]);
allowedTypes.extensions.addAll(typeGroup.extensions ?? <String>[]);
allowedTypes.mimeTypes.addAll(typeGroup.mimeTypes ?? <String>[]);
allowedTypes.utis.addAll(typeGroup.macUTIs ?? <String>[]);
}

return allowedTypes;
Expand Down
Loading