Skip to content

Commit 98659b7

Browse files
[file_selector] Fix unknown extensions on macOS (flutter#4946)
Fixes a bug in the type lookup that would cause the dynamic `UTType` created for unknown extensions to not work as a save/open panel filter. As incidental cleanup, removes test timeouts that shouldn't exist per Flutter policy. Fixes flutter#134963
1 parent 09df102 commit 98659b7

File tree

4 files changed

+68
-19
lines changed

4 files changed

+68
-19
lines changed

packages/file_selector/file_selector_macos/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.9.3+3
2+
3+
* Fixes handling of unknown file extensions on macOS 11+.
4+
15
## 0.9.3+2
26

37
* Adds pub topics to package metadata.

packages/file_selector/file_selector_macos/example/macos/RunnerTests/RunnerTests.swift

Lines changed: 59 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class exampleTests: XCTestCase {
6767
called.fulfill()
6868
}
6969

70-
wait(for: [called], timeout: 0.5)
70+
wait(for: [called])
7171
XCTAssertNotNil(panelController.openPanel)
7272
if let panel = panelController.openPanel {
7373
XCTAssertTrue(panel.canChooseFiles)
@@ -104,7 +104,7 @@ class exampleTests: XCTestCase {
104104
called.fulfill()
105105
}
106106

107-
wait(for: [called], timeout: 0.5)
107+
wait(for: [called])
108108
XCTAssertNotNil(panelController.openPanel)
109109
if let panel = panelController.openPanel {
110110
XCTAssertEqual(panel.directoryURL?.path, "/some/dir")
@@ -140,7 +140,7 @@ class exampleTests: XCTestCase {
140140
called.fulfill()
141141
}
142142

143-
wait(for: [called], timeout: 0.5)
143+
wait(for: [called])
144144
XCTAssertNotNil(panelController.openPanel)
145145
}
146146

@@ -173,7 +173,7 @@ class exampleTests: XCTestCase {
173173
called.fulfill()
174174
}
175175

176-
wait(for: [called], timeout: 0.5)
176+
wait(for: [called])
177177
XCTAssertNotNil(panelController.openPanel)
178178
if let panel = panelController.openPanel {
179179
if #available(macOS 11.0, *) {
@@ -188,6 +188,51 @@ class exampleTests: XCTestCase {
188188
}
189189
}
190190

191+
func testFilterUnknownFileExtension() throws {
192+
let panelController = TestPanelController()
193+
let plugin = FileSelectorPlugin(
194+
viewProvider: TestViewProvider(),
195+
panelController: panelController)
196+
197+
let unknownExtension = "somenewextension"
198+
let returnPath = "/foo/bar"
199+
panelController.openURLs = [URL(fileURLWithPath: returnPath)]
200+
201+
let called = XCTestExpectation()
202+
let options = OpenPanelOptions(
203+
allowsMultipleSelection: true,
204+
canChooseDirectories: false,
205+
canChooseFiles: true,
206+
baseOptions: SavePanelOptions(
207+
allowedFileTypes: AllowedTypes(
208+
extensions: [unknownExtension],
209+
mimeTypes: [],
210+
utis: [])))
211+
plugin.displayOpenPanel(options: options) { result in
212+
switch result {
213+
case .success(let paths):
214+
XCTAssertEqual(paths[0], returnPath)
215+
case .failure(let error):
216+
XCTFail("\(error)")
217+
}
218+
called.fulfill()
219+
}
220+
221+
wait(for: [called])
222+
XCTAssertNotNil(panelController.openPanel)
223+
if let panel = panelController.openPanel {
224+
if #available(macOS 11.0, *) {
225+
XCTAssertEqual(panel.allowedContentTypes.count, 1)
226+
XCTAssertEqual(panel.allowedContentTypes[0].preferredFilenameExtension, unknownExtension)
227+
// If this isn't true, the dynamic type created for the extension won't work as a file
228+
// extension filter.
229+
XCTAssertTrue(panel.allowedContentTypes[0].conforms(to: UTType.data))
230+
} else {
231+
XCTAssertEqual(panel.allowedFileTypes, [unknownExtension])
232+
}
233+
}
234+
}
235+
191236
func testOpenWithFilterLegacy() throws {
192237
let panelController = TestPanelController()
193238
let plugin = FileSelectorPlugin(
@@ -218,7 +263,7 @@ class exampleTests: XCTestCase {
218263
called.fulfill()
219264
}
220265

221-
wait(for: [called], timeout: 0.5)
266+
wait(for: [called])
222267
XCTAssertNotNil(panelController.openPanel)
223268
if let panel = panelController.openPanel {
224269
// On the legacy path, the allowedFileTypes should be set directly.
@@ -257,7 +302,7 @@ class exampleTests: XCTestCase {
257302
called.fulfill()
258303
}
259304

260-
wait(for: [called], timeout: 0.5)
305+
wait(for: [called])
261306
XCTAssertNotNil(panelController.openPanel)
262307
}
263308

@@ -282,7 +327,7 @@ class exampleTests: XCTestCase {
282327
called.fulfill()
283328
}
284329

285-
wait(for: [called], timeout: 0.5)
330+
wait(for: [called])
286331
XCTAssertNotNil(panelController.savePanel)
287332
}
288333

@@ -309,7 +354,7 @@ class exampleTests: XCTestCase {
309354
called.fulfill()
310355
}
311356

312-
wait(for: [called], timeout: 0.5)
357+
wait(for: [called])
313358
XCTAssertNotNil(panelController.savePanel)
314359
if let panel = panelController.savePanel {
315360
XCTAssertEqual(panel.directoryURL?.path, "/some/dir")
@@ -335,7 +380,7 @@ class exampleTests: XCTestCase {
335380
called.fulfill()
336381
}
337382

338-
wait(for: [called], timeout: 0.5)
383+
wait(for: [called])
339384
XCTAssertNotNil(panelController.savePanel)
340385
}
341386

@@ -364,7 +409,7 @@ class exampleTests: XCTestCase {
364409
called.fulfill()
365410
}
366411

367-
wait(for: [called], timeout: 0.5)
412+
wait(for: [called])
368413
XCTAssertNotNil(panelController.openPanel)
369414
if let panel = panelController.openPanel {
370415
XCTAssertTrue(panel.canChooseDirectories)
@@ -398,7 +443,7 @@ class exampleTests: XCTestCase {
398443
called.fulfill()
399444
}
400445

401-
wait(for: [called], timeout: 0.5)
446+
wait(for: [called])
402447
XCTAssertNotNil(panelController.openPanel)
403448
}
404449

@@ -408,7 +453,7 @@ class exampleTests: XCTestCase {
408453
viewProvider: TestViewProvider(),
409454
panelController: panelController)
410455

411-
let returnPaths = ["/foo/bar", "/foo/test"];
456+
let returnPaths = ["/foo/bar", "/foo/test"]
412457
panelController.openURLs = returnPaths.map({ path in URL(fileURLWithPath: path) })
413458

414459
let called = XCTestExpectation()
@@ -427,7 +472,7 @@ class exampleTests: XCTestCase {
427472
called.fulfill()
428473
}
429474

430-
wait(for: [called], timeout: 0.5)
475+
wait(for: [called])
431476
XCTAssertNotNil(panelController.openPanel)
432477
if let panel = panelController.openPanel {
433478
XCTAssertTrue(panel.canChooseDirectories)
@@ -459,7 +504,7 @@ class exampleTests: XCTestCase {
459504
called.fulfill()
460505
}
461506

462-
wait(for: [called], timeout: 0.5)
507+
wait(for: [called])
463508
XCTAssertNotNil(panelController.openPanel)
464509
}
465510
}

packages/file_selector/file_selector_macos/macos/Classes/FileSelectorPlugin.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,12 @@ public class FileSelectorPlugin: NSObject, FlutterPlugin, FileSelectorApi {
105105
// that via the types; see messages.dart and https://github.com/flutter/flutter/issues/97848
106106
allowedTypes.append(contentsOf: acceptedTypes.utis.compactMap({ UTType($0!) }))
107107
allowedTypes.append(
108-
contentsOf: acceptedTypes.extensions.flatMap({
109-
UTType.types(tag: $0!, tagClass: UTTagClass.filenameExtension, conformingTo: nil)
108+
contentsOf: acceptedTypes.extensions.compactMap({
109+
UTType.init(filenameExtension: $0!)
110110
}))
111111
allowedTypes.append(
112-
contentsOf: acceptedTypes.mimeTypes.flatMap({
113-
UTType.types(tag: $0!, tagClass: UTTagClass.mimeType, conformingTo: nil)
112+
contentsOf: acceptedTypes.mimeTypes.compactMap({
113+
UTType.init(mimeType: $0!)
114114
}))
115115
if !allowedTypes.isEmpty {
116116
panel.allowedContentTypes = allowedTypes

packages/file_selector/file_selector_macos/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: file_selector_macos
22
description: macOS implementation of the file_selector plugin.
33
repository: https://github.com/flutter/packages/tree/main/packages/file_selector/file_selector_macos
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+file_selector%22
5-
version: 0.9.3+2
5+
version: 0.9.3+3
66

77
environment:
88
sdk: ">=2.19.0 <4.0.0"

0 commit comments

Comments
 (0)