-
Notifications
You must be signed in to change notification settings - Fork 468
Fix macios filepicker #2981
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Fix macios filepicker #2981
Changes from 6 commits
4d9487c
ed5f254
47ddfe5
07be3c6
7757fce
f87e43d
08f9ffd
102300e
d88f395
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -29,30 +29,41 @@ async Task<string> InternalSaveAsync(string initialPath, string fileName, Stream | |||||||
| } | ||||||||
|
|
||||||||
| var fileUrl = tempDirectoryPath.Append(fileName, false); | ||||||||
| await WriteStream(stream, fileUrl.Path ?? throw new Exception("Path cannot be null."), progress, cancellationToken); | ||||||||
| try | ||||||||
| { | ||||||||
| await WriteStream(stream, fileUrl.Path ?? throw new Exception("Path cannot be null."), progress, cancellationToken); | ||||||||
|
|
||||||||
| cancellationToken.ThrowIfCancellationRequested(); | ||||||||
| taskCompetedSource?.TrySetCanceled(CancellationToken.None); | ||||||||
| var tcs = taskCompetedSource = new(cancellationToken); | ||||||||
| cancellationToken.ThrowIfCancellationRequested(); | ||||||||
| taskCompetedSource?.TrySetCanceled(CancellationToken.None); | ||||||||
| var tcs = taskCompetedSource = new(cancellationToken); | ||||||||
|
|
||||||||
| documentPickerViewController = new([fileUrl]) | ||||||||
| { | ||||||||
| DirectoryUrl = NSUrl.FromString(initialPath) | ||||||||
| }; | ||||||||
| documentPickerViewController.DidPickDocumentAtUrls += DocumentPickerViewControllerOnDidPickDocumentAtUrls; | ||||||||
| documentPickerViewController.WasCancelled += DocumentPickerViewControllerOnWasCancelled; | ||||||||
| documentPickerViewController = new([fileUrl], true) | ||||||||
| { | ||||||||
| DirectoryUrl = NSUrl.FromString(initialPath) | ||||||||
| }; | ||||||||
| documentPickerViewController.DidPickDocumentAtUrls += DocumentPickerViewControllerOnDidPickDocumentAtUrls; | ||||||||
| documentPickerViewController.WasCancelled += DocumentPickerViewControllerOnWasCancelled; | ||||||||
|
|
||||||||
| var currentViewController = Platform.GetCurrentUIViewController(); | ||||||||
| if (currentViewController is not null) | ||||||||
| { | ||||||||
| currentViewController.PresentViewController(documentPickerViewController, true, null); | ||||||||
| var currentViewController = Platform.GetCurrentUIViewController(); | ||||||||
| if (currentViewController is not null) | ||||||||
| { | ||||||||
| currentViewController.PresentViewController(documentPickerViewController, true, () => | ||||||||
| { | ||||||||
| fileManager.Remove(tempDirectoryPath, out _); | ||||||||
| }); | ||||||||
| } | ||||||||
| else | ||||||||
| { | ||||||||
| throw new FileSaveException("Unable to get a window where to present the file saver UI."); | ||||||||
| } | ||||||||
|
|
||||||||
| return await tcs.Task.WaitAsync(cancellationToken).ConfigureAwait(false); | ||||||||
| } | ||||||||
| else | ||||||||
| catch | ||||||||
| { | ||||||||
| throw new FileSaveException("Unable to get a window where to present the file saver UI."); | ||||||||
| fileManager.Remove(tempDirectoryPath, out _); | ||||||||
|
||||||||
| fileManager.Remove(tempDirectoryPath, out _); | |
| fileManager.Remove(tempDirectoryPath, out _); | |
| InternalDispose(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The temporary directory cleanup in the completion callback may execute prematurely before the file picker operations complete. The completion callback of
PresentViewControlleris invoked immediately after the presentation animation finishes, not after the user completes their interaction with the document picker.This means the temp directory (and the file within it) could be deleted while the UIDocumentPickerViewController is still displaying and before the user has saved the file to their chosen location, which would cause the save operation to fail.
Consider removing the cleanup from the completion callback and instead perform the cleanup in the event handlers (
DocumentPickerViewControllerOnDidPickDocumentAtUrlsandDocumentPickerViewControllerOnWasCancelled) where the actual file picker interaction is complete.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@VladislavAntonyuk what are your thoughts on this? I had the cleanup method, which could be called in a
finallyor as part ofInternalDispose, that will always check for the file and remove it if it exists. If we restore that, it's always safe to call, and can be called from any catch or finally block, from dispose, or from the event handlers suggested here.