[file_selector_platform_interface] File selector nnbd (#3509)

Migrating file_selector_interface to null-safety
diff --git a/packages/file_selector/file_selector_platform_interface/CHANGELOG.md b/packages/file_selector/file_selector_platform_interface/CHANGELOG.md
index aafe4db..2fbe18d 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.0.0-nullsafety.0
+
+* Migration to null-safety
+
 ## 1.0.3+1
 
 * Bump the [cross_file](https://pub.dev/packages/cross_file) package version.
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 586b1ab..e14239f 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
@@ -19,57 +19,57 @@
 
   /// Load a file from user's computer and return it as an XFile
   @override
-  Future<XFile> openFile({
-    List<XTypeGroup> acceptedTypeGroups,
-    String initialDirectory,
-    String confirmButtonText,
+  Future<XFile?> openFile({
+    List<XTypeGroup>? acceptedTypeGroups,
+    String? initialDirectory,
+    String? confirmButtonText,
   }) async {
-    final List<String> path = await _channel.invokeListMethod<String>(
+    final List<String>? path = await _channel.invokeListMethod<String>(
       'openFile',
       <String, dynamic>{
         'acceptedTypeGroups':
-            acceptedTypeGroups?.map((group) => group.toJSON())?.toList(),
+            acceptedTypeGroups?.map((group) => group.toJSON()).toList(),
         'initialDirectory': initialDirectory,
         'confirmButtonText': confirmButtonText,
         'multiple': false,
       },
     );
-    return path == null ? null : XFile(path?.first);
+    return path == null ? null : XFile(path.first);
   }
 
   /// Load multiple files from user's computer and return it as an XFile
   @override
   Future<List<XFile>> openFiles({
-    List<XTypeGroup> acceptedTypeGroups,
-    String initialDirectory,
-    String confirmButtonText,
+    List<XTypeGroup>? acceptedTypeGroups,
+    String? initialDirectory,
+    String? confirmButtonText,
   }) async {
-    final List<String> pathList = await _channel.invokeListMethod<String>(
+    final List<String>? pathList = await _channel.invokeListMethod<String>(
       'openFile',
       <String, dynamic>{
         'acceptedTypeGroups':
-            acceptedTypeGroups?.map((group) => group.toJSON())?.toList(),
+            acceptedTypeGroups?.map((group) => group.toJSON()).toList(),
         'initialDirectory': initialDirectory,
         'confirmButtonText': confirmButtonText,
         'multiple': true,
       },
     );
-    return pathList?.map((path) => XFile(path))?.toList() ?? [];
+    return pathList?.map((path) => XFile(path)).toList() ?? [];
   }
 
   /// Gets the path from a save dialog
   @override
-  Future<String> getSavePath({
-    List<XTypeGroup> acceptedTypeGroups,
-    String initialDirectory,
-    String suggestedName,
-    String confirmButtonText,
+  Future<String?> getSavePath({
+    List<XTypeGroup>? acceptedTypeGroups,
+    String? initialDirectory,
+    String? suggestedName,
+    String? confirmButtonText,
   }) async {
     return _channel.invokeMethod<String>(
       'getSavePath',
       <String, dynamic>{
         'acceptedTypeGroups':
-            acceptedTypeGroups?.map((group) => group.toJSON())?.toList(),
+            acceptedTypeGroups?.map((group) => group.toJSON()).toList(),
         'initialDirectory': initialDirectory,
         'suggestedName': suggestedName,
         'confirmButtonText': confirmButtonText,
@@ -79,9 +79,9 @@
 
   /// Gets a directory path from a dialog
   @override
-  Future<String> getDirectoryPath({
-    String initialDirectory,
-    String confirmButtonText,
+  Future<String?> getDirectoryPath({
+    String? initialDirectory,
+    String? confirmButtonText,
   }) async {
     return _channel.invokeMethod<String>(
       'getDirectoryPath',
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 e7b3263..0be02c2 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
@@ -38,37 +38,40 @@
   }
 
   /// Open file dialog for loading files and return a file path
-  Future<XFile> openFile({
-    List<XTypeGroup> acceptedTypeGroups,
-    String initialDirectory,
-    String confirmButtonText,
+  /// Returns `null` if user cancels the operation.
+  Future<XFile?> openFile({
+    List<XTypeGroup>? acceptedTypeGroups,
+    String? initialDirectory,
+    String? confirmButtonText,
   }) {
     throw UnimplementedError('openFile() has not been implemented.');
   }
 
   /// Open file dialog for loading files and return a list of file paths
   Future<List<XFile>> openFiles({
-    List<XTypeGroup> acceptedTypeGroups,
-    String initialDirectory,
-    String confirmButtonText,
+    List<XTypeGroup>? acceptedTypeGroups,
+    String? initialDirectory,
+    String? confirmButtonText,
   }) {
     throw UnimplementedError('openFiles() has not been implemented.');
   }
 
   /// Open file dialog for saving files and return a file path at which to save
-  Future<String> getSavePath({
-    List<XTypeGroup> acceptedTypeGroups,
-    String initialDirectory,
-    String suggestedName,
-    String confirmButtonText,
+  /// Returns `null` if user cancels the operation.
+  Future<String?> getSavePath({
+    List<XTypeGroup>? acceptedTypeGroups,
+    String? initialDirectory,
+    String? suggestedName,
+    String? confirmButtonText,
   }) {
     throw UnimplementedError('getSavePath() has not been implemented.');
   }
 
   /// Open file dialog for loading directories and return a directory path
-  Future<String> getDirectoryPath({
-    String initialDirectory,
-    String confirmButtonText,
+  /// Returns `null` if user cancels the operation.
+  Future<String?> getDirectoryPath({
+    String? initialDirectory,
+    String? confirmButtonText,
   }) {
     throw UnimplementedError('getDirectoryPath() has not been implemented.');
   }
diff --git a/packages/file_selector/file_selector_platform_interface/lib/src/types/x_type_group/x_type_group.dart b/packages/file_selector/file_selector_platform_interface/lib/src/types/x_type_group/x_type_group.dart
index fb591f2..f3f05e2 100644
--- a/packages/file_selector/file_selector_platform_interface/lib/src/types/x_type_group/x_type_group.dart
+++ b/packages/file_selector/file_selector_platform_interface/lib/src/types/x_type_group/x_type_group.dart
@@ -17,19 +17,19 @@
   });
 
   /// The 'name' or reference to this group of types
-  final String label;
+  final String? label;
 
   /// The extensions for this group
-  final List<String> extensions;
+  final List<String>? extensions;
 
   /// The MIME types for this group
-  final List<String> mimeTypes;
+  final List<String>? mimeTypes;
 
   /// The UTIs for this group
-  final List<String> macUTIs;
+  final List<String>? macUTIs;
 
   /// The web wild cards for this group (ex: image/*, video/*)
-  final List<String> webWildCards;
+  final List<String>? webWildCards;
 
   /// Converts this object into a JSON formatted object
   Map<String, dynamic> toJSON() {
diff --git a/packages/file_selector/file_selector_platform_interface/lib/src/web_helpers/web_helpers.dart b/packages/file_selector/file_selector_platform_interface/lib/src/web_helpers/web_helpers.dart
index 9e40e56..5330c5c 100644
--- a/packages/file_selector/file_selector_platform_interface/lib/src/web_helpers/web_helpers.dart
+++ b/packages/file_selector/file_selector_platform_interface/lib/src/web_helpers/web_helpers.dart
@@ -1,7 +1,7 @@
 import 'dart:html';
 
 /// Create anchor element with download attribute
-AnchorElement createAnchorElement(String href, String suggestedName) {
+AnchorElement createAnchorElement(String href, String? suggestedName) {
   final element = AnchorElement(href: href);
 
   if (suggestedName == null) {
@@ -27,7 +27,7 @@
   if (target == null) {
     final Element targetElement = Element.tag('flt-x-file')..id = id;
 
-    querySelector('body').children.add(targetElement);
+    querySelector('body')!.children.add(targetElement);
     target = targetElement;
   }
   return target;
diff --git a/packages/file_selector/file_selector_platform_interface/pubspec.yaml b/packages/file_selector/file_selector_platform_interface/pubspec.yaml
index f1d0038..9735bce 100644
--- a/packages/file_selector/file_selector_platform_interface/pubspec.yaml
+++ b/packages/file_selector/file_selector_platform_interface/pubspec.yaml
@@ -3,23 +3,23 @@
 homepage: https://github.com/flutter/plugins/tree/master/packages/file_selector/file_selector_platform_interface
 # 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: 1.0.3+1
+version: 2.0.0-nullsafety.0
 
 dependencies:
   flutter:
     sdk: flutter
   meta: ^1.0.5
-  http: ^0.12.0+1
-  plugin_platform_interface: ^1.0.1
-  cross_file: ^0.2.0
+  http: ^0.13.0-nullsafety.0
+  plugin_platform_interface: ^1.1.0-nullsafety.2
+  cross_file: ^0.3.0-nullsafety
 
 dev_dependencies:
   test: ^1.15.0
   flutter_test:
     sdk: flutter
-  mockito: ^4.1.1
+  mockito: ^5.0.0-nullsafety.5
   pedantic: ^1.8.0
 
 environment:
-  sdk: ">=2.1.0 <3.0.0"
+  sdk: '>=2.12.0-0 <3.0.0'
   flutter: ">=1.9.1+hotfix.4"
diff --git a/packages/file_selector/file_selector_web/pubspec.yaml b/packages/file_selector/file_selector_web/pubspec.yaml
index a170d5f..79181e8 100644
--- a/packages/file_selector/file_selector_web/pubspec.yaml
+++ b/packages/file_selector/file_selector_web/pubspec.yaml
@@ -22,8 +22,8 @@
 dev_dependencies:
   flutter_test:
     sdk: flutter
-  mockito: ^4.1.1
-  pedantic: ^1.8.0
+  mockito: ^5.0.0-nullsafety.5
+  pedantic: ^1.10.0-nullsafety.3
   integration_test:
     path: ../../integration_test
 
diff --git a/script/nnbd_plugins.sh b/script/nnbd_plugins.sh
index 742487a..1e57db9 100644
--- a/script/nnbd_plugins.sh
+++ b/script/nnbd_plugins.sh
@@ -10,6 +10,7 @@
   "connectivity"
   "cross_file"
   "device_info"
+  "file_selector"
   "flutter_plugin_android_lifecycle"
   "flutter_webview"
   "google_sign_in"
@@ -32,7 +33,6 @@
 readonly NON_NNBD_PLUGINS_LIST=(
   # "android_alarm_manager"
   "camera"
-  # "file_selector"
   # "google_maps_flutter"
   # "image_picker"
   # "in_app_purchase"