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

[file_selector] initial implementation #3140

Merged
merged 156 commits into from
Nov 20, 2020
Merged

Conversation

tugorez
Copy link
Contributor

@tugorez tugorez commented Oct 12, 2020

Description

Add the API for the file_selector plugin.

Related Issues

flutter/flutter#65403

Checklist

Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes ([x]). This will ensure a smooth and quick review process.

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • My PR includes unit or integration tests for all changed/updated/fixed behaviors (See Contributor Guide).
  • All existing and new tests are passing.
  • I updated/added relevant documentation (doc comments with ///).
  • The analyzer (flutter analyze) does not report any problems on my PR.
  • I read and followed the Flutter Style Guide.
  • The title of the PR starts with the name of the plugin surrounded by square brackets, e.g. [shared_preferences]
  • I updated pubspec.yaml with an appropriate new version according to the pub versioning philosophy.
  • I updated CHANGELOG.md to add a description of the change.
  • I signed the CLA.
  • I am willing to follow-up on review comments in a timely manner.

Breaking Change

Does your PR require plugin users to manually update their apps to accommodate your change?

  • Yes, this is a breaking change (please indicate a breaking change in CHANGELOG.md and increment major revision).
  • No, this is not a breaking change.

Change some variables to final, condense for loops and some if statements.
Also some refactoring of plugin code to accomplish tests
new fromData constructor in XFile class
@tugorez
Copy link
Contributor Author

tugorez commented Oct 30, 2020

Some very high level comments based on an initial skim.

In addition to the comments below: why isn't there a driver/integration test as part of this?

Those tests should and will be added as part as each platform implementation.

@stuartmorgan-g
Copy link
Contributor

stuartmorgan-g commented Nov 1, 2020

Some very high level comments based on an initial skim.
In addition to the comments below: why isn't there a driver/integration test as part of this?

Those tests should and will be added as part as each platform implementation.

Every plugin I've implemented for desktop here has integration tests at both layers. Why would we do less testing in this plugin?

Examples:
https://github.com/flutter/plugins/tree/master/packages/url_launcher/url_launcher/example/integration_test
https://github.com/flutter/plugins/tree/master/packages/path_provider/path_provider/example/integration_test
https://github.com/flutter/plugins/tree/master/packages/shared_preferences/shared_preferences/example/integration_test

@ditman
Copy link
Member

ditman commented Nov 2, 2020

Every plugin I've implemented for desktop here has integration tests at both layers.

@stuartmorgan most plugins so far have a purely programmatic API that never leaves the Flutter App under test. In this case, the test would need to drive native OS dialogs (I don't know if that's doable?) or bypass all that altogether by adding a mock method channel handler (which wouldn't work for the web case).

I don't see how this end of the plugin can be integration-tested in a way that is somewhat platform agnostic. Do you have any idea about that?

As a bad example, look at the tests for the image picker ;)

@stuartmorgan-g
Copy link
Contributor

Oh, right. I wasn't thinking about the fact that this is UI based; sorry about that. Yes, that does probably mean integration tests can't live at this layer.

(We should still unit test the app-facing API though, using a mock platform interface implementaiton, per my other comments.)

@ditman
Copy link
Member

ditman commented Nov 2, 2020

We should still unit test the app-facing API though, using a mock platform interface implementaiton, per my other comments.

@stuartmorgan yes, those should be easy to add; it's just verify that the mock platform methods are being called (if done with Mockito and a Mock platform implementation) or by doing the method logging technique.

Copy link
Member

@ditman ditman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for addressing this! I think it's ready to go, even though, there's a small change incoming regarding the cross_file package (we should be able to hide that fact from the platform_interface package, possibly!)

If Stuart is happy with the current implementation, let's get this merged!

import 'package:file_selector/file_selector.dart';
import 'package:flutter/material.dart';

/// Screen that shows an example of openFile(s)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This screen shows an example of getDirectoryPath, it seems :P

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great catch! Fixed here and (hopefully) everywhere.

@ditman
Copy link
Member

ditman commented Nov 19, 2020

Note to all: package: cross_file is now a thing:

https://pub.dev/packages/cross_file

Copy link
Contributor

@stuartmorgan-g stuartmorgan-g left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the expanded test coverage and examples! LGTM with some minor nits.

class GetDirectoryPage extends StatelessWidget {
void _getDirectoryPath(BuildContext context) async {
final String initialDirectory = '~/Desktop';
final String confirmButtonText = 'Choose a cool directory';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: This is a lot of text for a button. Maybe pick something more realistic to demonstrate, like "Choose"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

/// Screen that shows an example of openFile(s)
class GetDirectoryPage extends StatelessWidget {
void _getDirectoryPath(BuildContext context) async {
final String initialDirectory = '~/Desktop';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do the various OS file dialogs actually expand "~"? The robust way to do this would be to use path_provider; if we don't want to depend on that I would suggest we just don't set a starting directory in the example.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a good point. I'm not sure if ~ gets actually expanded so I will play safe here and remove it.
Thanks @stuartmorgan :)!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that path_provider doesn't work in web at all AFAIK (U_U)

extensions: ['jpg', 'jpeg'],
);
final XTypeGroup pngTypeGroup = XTypeGroup(
extensions: ['png'],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why no label?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed!

class OpenMultipleImagesPage extends StatelessWidget {
void _openImageFile(BuildContext context) async {
final XTypeGroup jpgsTypeGroup = XTypeGroup(
label: 'images',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems odd to call this "images" rather than "JPEGs" given that the other option is also an image type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

@tugorez
Copy link
Contributor Author

tugorez commented Nov 20, 2020

Note to all: package: cross_file is now a thing:

https://pub.dev/packages/cross_file

flutter/flutter#70950 to track the integration. Thanks for the heads up :)!

@ditman
Copy link
Member

ditman commented Nov 20, 2020

Let's go with this one! Thanks all for the hard work!

@ditman ditman merged commit 576f04a into flutter:master Nov 20, 2020
@stuartmorgan-g
Copy link
Contributor

While doing manual testing on Windows with the example I noticed that none of the example calls handle the user pressing cancel (in which case the returned path will be null). Right now canceling any dialog in the example will throw an exception.

@ditman
Copy link
Member

ditman commented Nov 24, 2020

@stuartmorgan that's an interesting "edge" case for the web; in web you never get called back if the user cancels the selection (no events, null path... nothing!)

amantoux pushed a commit to amantoux/plugins that referenced this pull request Feb 8, 2021
adsonpleal pushed a commit to nubank/plugins that referenced this pull request Feb 26, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants